Update to bsnes v021 release.

This is a maintainence release. I am mostly releasing this for the sake of the recently released Der Langrisser translation.
Changelog:
Windows port can once again map joypads through the Input Configuration panel
Using enter or spacebar to assign a key should no longer instantly map those keys
F11 now toggles fullscreen mode
Esc now toggles menu on and off (use F11+Esc combined to hide UI completely)
Fixed a bug in King of Dragons (J, U, E), KOFF was not cleared during S-DSP power(), thanks to FitzRoy for the report, and blargg for assistance fixing the bug
Fixed serious crashing error with File->Load on Linux/amd64 port
Hopefully fixed min/max undefined error on GCC 4.2.0, but I am unable to test to verify
Fixed many cast const char* to char* warnings for GCC 4.2.0, but some probably remain, as again, I am unable to test as I lack GCC 4.2.0
Set XV_AUTO_COLORKEY to 1 for Video/Xv renderer. Should fix some video drivers where there was no output, especially after running mplayer, etc. Thanks to sinimas for the fix
Added clear_video() to Video/Xv renderer. Green edges at the bottom and right sides of the video output are now gone, and unloading a ROM will clear video
I have finally figured out how to poll the keyboard status in real-time through Xorg: the XQueryKeymap function. I will be rewriting the Linux key capture system to use this, instead of capturing window key up / down messages through GTK+. This will finally allow me to completely abstract the UI from the hardware video, audio and input interfaces: a necessary step toward Linux joypad support.
This commit is contained in:
byuu 2007-06-10 19:27:46 +00:00
parent ebb234ba5f
commit a1980fab09
37 changed files with 517 additions and 868 deletions

View File

@ -14,14 +14,14 @@ limited to, this license, binaries, source code, documentation, and data.
"The licensor" means the copyright holder of the software, byuu.
2. Grant of Rights
Subject to the terms of this license, the licensor grants you a
non-transferable, non-exclusive, worldwide, royalty-free copyright license to
reproduce the software for non-commercial use only, provided the software
remains unmodified, and there is no charge for the software itself, its' use,
nor for the medium upon which the software is distributed. The reproduction of
modified or derivative works of the software is strictly prohibited, except when
2. Grant of Rights
Subject to the terms of this license, the licensor grants you a
non-transferable, non-exclusive, worldwide, royalty-free copyright license to
reproduce the software for non-commercial use only, provided the software
remains unmodified, and there is no charge for the software itself, its' use,
nor for the medium upon which the software is distributed. The reproduction of
modified or derivative works of the software is strictly prohibited, except when
transmitted solely to the licensor.
3. Limitations
@ -37,10 +37,10 @@ consequential damages (including, but not limited to, procurement of substitute
goods or services; loss of use, data, or profits; or business interruption)
however caused and on any theory of liability, whether in contract, strict
liability, or tort (including negligence or otherwise) arising in any way out of
the use of the software, even if advised of the possibility of such damage.
In the event that this license is determined to be invalid or unenforceable, the
Grant of Rights will become null and void, and no rights shall be granted to the
the use of the software, even if advised of the possibility of such damage.
In the event that this license is determined to be invalid or unenforceable, the
Grant of Rights will become null and void, and no rights shall be granted to the
licensee, within the scope of U.S. copyright law.
4. Exemptions

View File

@ -1,5 +1,5 @@
bsnes
Version 0.020
Version 0.021
Author: byuu

View File

@ -1,4 +1,4 @@
#define BSNES_VERSION "0.020.01"
#define BSNES_VERSION "0.021"
#define BSNES_TITLE "bsnes v" BSNES_VERSION
#define MEMCORE bMemBus
@ -31,11 +31,9 @@
#error "unsupported processor"
#endif
#include "lib/libinterp.h"
#include "lib/libsort.h"
#include "lib/libarray.h"
#include "lib/libvector.h"
#include "lib/libfile.h"
#include "lib/libstring.h"
#include "lib/libconfig.h"

View File

@ -662,7 +662,9 @@ void bDSP::power()
{
ram = (uint8*) r_smp->get_spcram_handle();
memset( &m, 0, sizeof m );
memcpy( m.regs, initial_regs, sizeof m.regs );
//memcpy( m.regs, initial_regs, sizeof m.regs );
memset(m.regs, 0, sizeof m.regs);
REG(flg) = 0xe0;
// Internal state
for ( int i = voice_count; --i >= 0; )

View File

@ -1,9 +1,9 @@
/*
libarray : version 0.08 ~byuu (2006-12-16)
libarray : version 0.09 ~byuu (2007-03-06)
*/
#ifndef __LIBARRAY
#define __LIBARRAY
#ifndef LIBARRAY_H
#define LIBARRAY_H
template<typename T> class array {
protected:

View File

@ -16,6 +16,8 @@
#include <time.h>
#include <math.h>
#include <new>
#if defined(_MSC_VER)
#include <io.h>
#include <direct.h>

View File

@ -1,5 +1,5 @@
/*
libconfig : version 0.14 ~byuu (2007-05-27)
libconfig : version 0.14 ~byuu (2007-06-10)
license: public domain
*/
@ -72,7 +72,7 @@ enum Format {
template<typename T> bool operator<=(T x) { return (T(data) <= x); }
template<typename T> bool operator< (T x) { return (T(data) < x); }
IntegerSetting(Config *parent, char *r_name, char *r_desc, uint r_format, uint r_data) {
IntegerSetting(Config *parent, const char *r_name, const char *r_desc, uint r_format, uint r_data) {
type = Setting::Integer;
name = strdup(r_name);
desc = strdup(r_desc);
@ -103,7 +103,7 @@ string data;
bool operator==(const char *x) { return !strcmp(data, x); }
bool operator!=(const char *x) { return strcmp(data, x); }
StringSetting(Config *parent, char *r_name, char *r_desc, char *r_data) {
StringSetting(Config *parent, const char *r_name, const char *r_desc, char *r_data) {
type = Setting::String;
name = strdup(r_name);
desc = strdup(r_desc);

View File

@ -1,455 +0,0 @@
/*
libfile : version 0.07 ~byuu (2007-03-01)
*/
#ifndef __LIBFILE
#define __LIBFILE
//FreeBSD fix: do not use defines for libc functions
#undef feof
#undef ferror
/*****
* file object
*****/
class file {
public:
enum { mode_read, mode_write, mode_readwrite, mode_writeread };
enum { seek_start, seek_end, seek_back, seek_forward };
virtual void read(uint8 *data, uint length) = 0;
virtual uint8 read() = 0;
virtual void write(uint8 *data, uint length) = 0;
virtual void write(uint8 data) = 0;
virtual uint32 crc32();
virtual void seek(uint offset, uint mode = seek_start) = 0;
virtual void resize(uint size) = 0;
virtual uint offset() = 0;
virtual uint size() = 0;
virtual bool eof() = 0;
virtual bool open(const char *filename, uint mode) = 0;
virtual bool open() = 0;
virtual bool flush() = 0;
virtual bool close() = 0;
};
inline uint32 file::crc32() {
uint pos = offset(), i = size();
seek(0);
uint32 crc32 = 0xffffffff;
while(i--) {
crc32 = crc32_adjust(crc32, read());
}
seek(pos);
return ~crc32;
}
/*****
* c++ wrappers
*****/
inline void fread(file &s, uint8 *data, uint length) { s.read(data, length); }
inline uint8 fread(file &s) { return s.read(); }
inline uint8 fgetc(file &s) { return s.read(); }
inline uint fgetb(file &s) { return s.read(); }
inline void fwrite(file &s, uint8 *data, uint length) { s.write(data, length); }
inline void fwrite(file &s, uint8 data) { s.write(data); }
inline void fputc(uint8 data, file &s) { s.write(data); }
inline void fputb(file &s, uint8 data) { s.write(data); }
inline uint32 fcrc32(file &s) { return s.crc32(); }
inline void fseek(file &s, uint offset, uint mode = file::seek_start) { s.seek(offset, mode); }
inline void fresize(file &s, uint size) { s.resize(size); }
inline uint ftell(file &s) { return s.offset(); }
inline uint fsize(file &s) { return s.size(); }
inline bool feof(file &s) { return s.eof(); }
inline bool fopen(file &s, const char *filename, uint mode) { return s.open(filename, mode); }
inline bool fopen(file &s) { return s.open(); }
inline bool fflush(file &s) { return s.flush(); }
inline bool fclose(file &s) { return s.close(); }
/*****
* endian wrappers
*****/
inline uint8 fgetlb(file &s) { return fgetc(s); }
inline uint8 fgetmb(file &s) { return fgetc(s); }
inline uint16 fgetlw(file &s) {
return (fgetc(s)) | (fgetc(s) << 8);
}
inline uint16 fgetmw(file &s) {
return (fgetc(s) << 8) | (fgetc(s) << 8);
}
inline uint32 fgetld(file &s) {
return (fgetc(s)) | (fgetc(s) << 8) | (fgetc(s) << 16) | (fgetc(s) << 24);
}
inline uint32 fgetmd(file &s) {
return (fgetc(s) << 24) | (fgetc(s) << 16) | (fgetc(s) << 8) | (fgetc(s));
}
inline uint64 fgetlq(file &s) {
return ((uint64)fgetc(s) << 0) | ((uint64)fgetc(s) << 8) |
((uint64)fgetc(s) << 16) | ((uint64)fgetc(s) << 24) |
((uint64)fgetc(s) << 32) | ((uint64)fgetc(s) << 40) |
((uint64)fgetc(s) << 48) | ((uint64)fgetc(s) << 56);
}
inline uint64 fgetmq(file &s) {
return ((uint64)fgetc(s) << 56) | ((uint64)fgetc(s) << 48) |
((uint64)fgetc(s) << 40) | ((uint64)fgetc(s) << 32) |
((uint64)fgetc(s) << 24) | ((uint64)fgetc(s) << 16) |
((uint64)fgetc(s) << 8) | ((uint64)fgetc(s) << 0);
}
inline void fputlb(file &s, uint8 data) { fputc(data, s); }
inline void fputmb(file &s, uint8 data) { fputc(data, s); }
inline void fputlw(file &s, uint16 data) {
fputc(data >> 0, s);
fputc(data >> 8, s);
}
inline void fputmw(file &s, uint16 data) {
fputc(data >> 8, s);
fputc(data >> 0, s);
}
inline void fputld(file &s, uint32 data) {
fputc(data >> 0, s);
fputc(data >> 8, s);
fputc(data >> 16, s);
fputc(data >> 24, s);
}
inline void fputmd(file &s, uint32 data) {
fputc(data >> 24, s);
fputc(data >> 16, s);
fputc(data >> 8, s);
fputc(data >> 0, s);
}
inline void fputlq(file &s, uint64 data) {
fputc(data >> 0, s);
fputc(data >> 8, s);
fputc(data >> 16, s);
fputc(data >> 24, s);
fputc(data >> 32, s);
fputc(data >> 40, s);
fputc(data >> 48, s);
fputc(data >> 56, s);
}
inline void fputmq(file &s, uint64 data) {
fputc(data >> 56, s);
fputc(data >> 48, s);
fputc(data >> 40, s);
fputc(data >> 32, s);
fputc(data >> 24, s);
fputc(data >> 16, s);
fputc(data >> 8, s);
fputc(data >> 0, s);
}
/*****
* ramfile
*****/
class ramfile : public file {
private:
FILE *fp;
array<uint8> filedata;
char filename[1024];
uint filepos;
uint filesize;
uint filemode;
bool fileopen;
bool filevirtual;
public:
void read(uint8 *data, uint length) {
if(!fileopen || filemode == mode_write) { return; }
memcpy(data, filedata.get(filepos + length) + filepos, length);
filepos += length;
if(filepos > filesize)filepos = filesize;
}
uint8 read() {
if(!fileopen || filemode == mode_write) { return 0; }
if(eof() == true) { return 0xff; }
return filedata[filepos++];
}
void write(uint8 *data, uint length) {
if(!fileopen || filemode == mode_read) { return; }
memcpy(filedata.get(filepos + length) + filepos, data, length);
filepos += length;
if(filepos > filesize)filesize = filepos;
}
void write(uint8 data) {
if(!fileopen || filemode == mode_read) { return; }
filedata[filepos++] = data;
if(filepos > filesize)filesize = filepos;
}
void seek(uint offset, uint mode = seek_start) {
if(!fileopen) { return; }
switch(mode) {
case seek_start: filepos = offset; break;
case seek_end: filepos = filesize + offset; break;
case seek_back: filepos -= offset; break;
case seek_forward: filepos += offset; break;
}
if(filemode == mode_read) {
if(filepos > filesize)filepos = filesize;
} else {
if(filepos > filesize)filesize = filepos;
}
}
void resize(uint size) {
filesize = size;
if(filepos > filesize)filepos = filesize;
}
uint offset() {
if(!fileopen) { return 0; }
return filepos;
}
uint size() {
if(!fileopen) { return 0; }
return filesize;
}
bool eof() {
if(!fileopen) { return true; }
return (filepos >= filesize);
}
bool open(const char *fn, uint mode) {
if(fileopen) { return false; }
strcpy(filename, fn ? fn : "");
filevirtual = (*filename == 0);
filemode = mode;
switch(filemode) {
case mode_read:
case mode_readwrite:
if(filevirtual == true) {
filesize = 0;
} else {
fp = fopen(filename, "rb");
if(!fp) { return false; }
filesize = fsize(fp);
fread(filedata.get(filesize), 1, filesize, fp);
fclose(fp);
}
break;
default:
filesize = 0;
break;
}
filepos = 0;
fileopen = true;
return true;
}
bool open() {
return fileopen;
}
bool flush() {
if(!fileopen) { return false; }
switch(filemode) {
case mode_readwrite:
case mode_write:
case mode_writeread:
if(filevirtual == false) {
fp = fopen(filename, "wb");
if(!fp) { return false; }
fwrite(filedata.get(filesize), 1, filesize, fp);
fclose(fp);
}
break;
}
return true;
}
bool close() {
if(!fileopen) { return false; }
bool result = flush();
fileopen = false;
filedata.reset();
return result;
}
ramfile() {
fileopen = false;
}
~ramfile() {
if(fileopen) { close(); }
}
};
/*****
* diskfile
*****/
class diskfile : public file {
private:
FILE *fp;
uint filemode;
public:
void read(uint8 *data, uint length) {
if(!fp || filemode == mode_write) { return; }
fread(data, 1, length, fp);
}
uint8 read() {
if(!fp || filemode == mode_write) { return 0; }
if(eof() == true) { return 0xff; }
return fgetc(fp);
}
void write(uint8 *data, uint length) {
if(!fp || filemode == mode_read) { return; }
fwrite(data, 1, length, fp);
}
void write(uint8 data) {
if(!fp || filemode == mode_read) { return; }
fputc(data, fp);
}
void seek(uint offset, uint mode = seek_start) {
if(!fp) { return; }
switch(mode) {
default:
case seek_start: fseek(fp, offset, SEEK_SET); break;
case seek_end: fseek(fp, offset, SEEK_END); break;
case seek_back: fseek(fp, offset, SEEK_CUR); break;
case seek_forward: fseek(fp, offset, SEEK_CUR); break;
}
}
void resize(uint size) {
if(!fp) { return; }
fresize(fp, size);
}
uint offset() {
if(!fp) { return 0; }
return ftell(fp);
}
uint size() {
if(!fp) { return 0; }
uint pos = ftell(fp);
fseek(fp, 0, SEEK_END);
uint filesize = ftell(fp);
fseek(fp, pos, SEEK_SET);
return filesize;
}
bool eof() {
if(!fp) { return true; }
if(feof(fp)) {
seek(size(), seek_start);
return true;
}
return false;
}
bool open(const char *filename, uint mode) {
if(fp) { return false; }
filemode = mode;
char m[8];
switch(filemode) {
default:
case mode_read: strcpy(m, "rb"); break;
case mode_write: strcpy(m, "wb"); break;
case mode_readwrite: strcpy(m, "rb+"); break;
case mode_writeread: strcpy(m, "wb+"); break;
}
fp = fopen(filename, m);
if(!fp) { return false; }
return true;
}
bool open() {
return (fp != 0);
}
bool flush() {
if(!fp) { return false; }
fflush(fp);
return true;
}
bool close() {
if(!fp) { return false; }
fclose(fp);
fp = 0;
return true;
}
diskfile() {
fp = 0;
}
~diskfile() {
if(fp) { fclose(fp); }
}
};
/*****
* directory object
*****/
class directory {
public:
void open(const char *path) {}
void close() {}
uint read(char *filename, uint maxlength) { return 0; }
};
#endif

View File

@ -1,73 +0,0 @@
/*
libinterp : version 0.01 ~byuu (2007-02-03)
*/
#ifndef __LIBINTERP
#define __LIBINTERP
static inline
double interpolate_point(
double mu,
double y0, double y1
) {
return mu < 0.5 ? y0 : y1;
}
static inline
double interpolate_linear(
double mu,
double y0, double y1
) {
return y0 + mu * (y1 - y0);
}
static inline
double interpolate_cosine(
double mu,
double y0, double y1
) {
mu = (1.0 - cos(mu * 3.14159265)) / 2.0;
return y0 + mu * (y1 - y0);
}
static inline
double interpolate_cubic(
double mu,
double y0, double y1, double y2, double y3
) {
double a0 = y3 - y2 - y0 + y1;
double a1 = y0 - y1 - a0;
double a2 = y2 - y0;
double a3 = y1;
return a0 * mu * mu * mu +
a1 * mu * mu +
a2 * mu +
a3;
}
/*
tension: (0 = normal, -1 = low, +1 = high)
bias: (0 = even, -n = left, +n = right)
*/
static inline
double interpolate_hermite(
double mu, double tension, double bias,
double y0, double y1, double y2, double y3
) {
double mu0 = ( (y1 - y0) * (1.0 + bias) * (1.0 - tension) / 2.0 ) +
( (y2 - y1) * (1.0 - bias) * (1.0 - tension) / 2.0 );
double mu1 = ( (y2 - y1) * (1.0 + bias) * (1.0 - tension) / 2.0 ) +
( (y3 - y2) * (1.0 - bias) * (1.0 - tension) / 2.0 );
double mu2 = mu * mu;
double mu3 = mu * mu * mu;
double a0 = 2.0 * mu3 - 3.0 * mu2 + 1.0;
double a1 = mu3 - 2.0 * mu2 + mu;
double a2 = mu3 - mu2;
double a3 = -2.0 * mu3 + 3.0 * mu2;
return a0 * y1 +
a1 * mu0 +
a2 * mu1 +
a3 * y2;
}
#endif

View File

@ -7,6 +7,28 @@
namespace keymap {
//TODO: use lookup table for find() functions
static char keytable[][64] = {
"none",
"esc",
"f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12",
"print_screen", "sys_req", "scroll_lock", "pause", "brk",
"grave", "tilde",
"num_1", "exclamation",
"num_2", "at",
"num_3", "pound",
"num_4", "dollar",
"num_5", "percent",
"num_6", "power",
"num_7", "ampersand",
"num_8", "asterisk",
"num_9", "lparenthesis",
"num_0", "rparenthesis",
"minus", "underscore",
"equal", "plus",
"backspace",
};
enum {
none = 0x0000,
@ -108,6 +130,8 @@ enum {
rsuper,
menu,
limit, //not an actual key -- marks the end of linear key entries
joypad_flag = 0x8000,
joypad_nummask = 0x7f00,
joypad_keymask = 0x00ff,

View File

@ -2,8 +2,8 @@
libsort : version 0.01 ~byuu (2006-11-15)
*/
#ifndef __LIBSORT
#define __LIBSORT
#ifndef LIBSORT_H
#define LIBSORT_H
template<typename T>
void sort(T list[], uint length) {

View File

@ -1,9 +1,9 @@
/*
libstring : version 0.17 ~byuu (2007-05-20)
libstring : version 0.18 ~byuu (2007-06-06)
*/
#ifndef __LIBSTRING
#define __LIBSTRING
#ifndef LIBSTRING_H
#define LIBSTRING_H
#include "libbase.h"
#include "libvector.h"
@ -189,35 +189,32 @@ uint size;
~string() { safe_free(s); }
const char *operator()();
char &operator[](const uint);
string &operator= (const int);
string &operator= (const char *);
string &operator= (const string &);
string &operator+=(const int);
string &operator+=(const char *);
string &operator+=(const string &);
bool operator==(const char *);
bool operator==(const string &);
bool operator!=(const char *);
bool operator!=(const string &);
bool operator< (const char *);
bool operator< (const string &);
bool operator<=(const char *);
bool operator<=(const string &);
bool operator> (const char *);
bool operator> (const string &);
bool operator>=(const char *);
bool operator>=(const string &);
operator const char*() const { return s; }
const char* operator()() const { return s; }
char& operator[](const uint);
string operator+(const int);
string operator+(const char *);
string operator+(const string &);
string& operator=(const int);
string& operator=(const char*);
string& operator=(const string&);
string& operator<<(const int);
string& operator<<(const char*);
string& operator<<(const string&);
bool operator==(const char*);
bool operator==(const string&);
bool operator!=(const char*);
bool operator!=(const string&);
bool operator< (const char*);
bool operator< (const string&);
bool operator<=(const char*);
bool operator<=(const string&);
bool operator> (const char*);
bool operator> (const string&);
bool operator>=(const char*);
bool operator>=(const string&);
};
string operator+(const int, const string &);
string operator+(const char *, const string &);
inline void swap(string &x, string &y) { x.swap(y); }
#endif //__LIBSTRING
#endif //LIBSTRING_H

View File

@ -1,7 +1,3 @@
const char *string::operator()() {
return s;
}
char &string::operator[](const uint index) {
reserve(index);
return s[index];
@ -22,17 +18,17 @@ string &string::operator=(const string &str) {
return *this;
}
string &string::operator+=(const int num) {
string& string::operator<<(const int num) {
strcat(*this, strfmt("%d", num));
return *this;
}
string &string::operator+=(const char *str) {
string& string::operator<<(const char* str) {
strcat(*this, str);
return *this;
}
string &string::operator+=(const string &str) {
string& string::operator<<(const string& str) {
strcat(*this, str);
return *this;
}
@ -49,35 +45,3 @@ bool string::operator> (const char *str) { return strcmp(strptr(*this), str)
bool string::operator> (const string &str) { return strcmp(strptr(*this), strptr(str)) > 0; }
bool string::operator>=(const char *str) { return strcmp(strptr(*this), str) >= 0; }
bool string::operator>=(const string &str) { return strcmp(strptr(*this), strptr(str)) >= 0; }
string string::operator+(const int num) {
string temp(*this);
strcat(temp, strfmt("%d", num));
return temp;
}
string string::operator+(const char *str) {
string temp(*this);
strcat(temp, str);
return temp;
}
string string::operator+(const string &str) {
string temp(*this);
strcat(temp, str);
return temp;
}
//
string operator+(const int x, const string &y) {
string temp(strfmt("%d", x));
strcat(temp, y);
return temp;
}
string operator+(const char *x, const string &y) {
string temp(x);
strcat(temp, y);
return temp;
}

View File

@ -1,5 +1,5 @@
/*
libui_gtk ~byuu (2007-06-05)
libui_gtk ~byuu (2007-06-06)
license: public domain
*/
@ -53,13 +53,20 @@ enum Style {
MenuBar menu;
void create(uint style, uint width, uint height, const char *caption = "");
void set_text(const char *str, ...);
void set_text(const char *str);
void set_background_color(uint8 r, uint8 g, uint8 b);
void focus();
bool focused();
void move(uint x, uint y);
void resize(uint width, uint height);
virtual void show();
virtual void hide();
void show(bool state);
bool visible();
void fullscreen();
void unfullscreen();
void fullscreen(bool state);
bool is_fullscreen();
virtual bool message(uint id, uintptr_t param = 0) { return true; }

View File

@ -321,13 +321,8 @@ void Label::create(Window &r_owner, uint style, uint x, uint y, uint width, uint
gtk_widget_show(widget);
}
void Label::set_text(const char *str, ...) {
va_list args;
va_start(args, str);
string temp;
vsprintf(temp, str, args);
va_end(args);
gtk_label_set_label(GTK_LABEL(widget), strptr(temp));
void Label::set_text(const char *str) {
gtk_label_set_label(GTK_LABEL(widget), str);
}
/*****
@ -345,13 +340,8 @@ void Button::create(Window &r_owner, uint style, uint x, uint y, uint width, uin
g_signal_connect_swapped(G_OBJECT(widget), "clicked", G_CALLBACK(libui_control_clicked), (gpointer)this);
}
void Button::set_text(const char *str, ...) {
va_list args;
va_start(args, str);
string temp;
vsprintf(temp, str, args);
va_end(args);
gtk_button_set_label(GTK_BUTTON(widget), strptr(temp));
void Button::set_text(const char *str) {
gtk_button_set_label(GTK_BUTTON(widget), str);
}
/*****
@ -447,17 +437,11 @@ void Editbox::create(Window &r_owner, uint style, uint x, uint y, uint width, ui
gtk_widget_show(widget);
}
void Editbox::set_text(const char *str, ...) {
va_list args;
va_start(args, str);
string temp;
vsprintf(temp, str, args);
va_end(args);
void Editbox::set_text(const char *str) {
if(multiline == false) {
gtk_entry_set_text(GTK_ENTRY(widget), strptr(temp));
gtk_entry_set_text(GTK_ENTRY(widget), str);
} else {
gtk_text_buffer_set_text(buffer, strptr(temp), -1);
gtk_text_buffer_set_text(buffer, str, -1);
}
}
@ -539,28 +523,16 @@ void Listbox::set_column_width(uint column, uint width) {
gtk_tree_view_column_set_max_width(column_list[column], width);
}
void Listbox::add_item(const char *data, ...) {
va_list args;
va_start(args, data);
string temp;
vsprintf(temp, data, args);
va_end(args);
void Listbox::add_item(const char *data) {
stringarray part;
split(part, "|", temp);
split(part, "|", data);
gtk_list_store_append(store, &iter);
for(uint i = 0; i < count(part); i++) {
gtk_list_store_set(store, &iter, i, strptr(part[i]), -1);
}
}
void Listbox::set_item(uint index, const char *data, ...) {
va_list args;
va_start(args, data);
string temp;
vsprintf(temp, data, args);
va_end(args);
void Listbox::set_item(uint index, const char *data) {
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subwidget));
for(uint i = 0; i <= index; i++) {
(i == 0) ?
@ -569,14 +541,14 @@ GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subwidget));
}
stringarray part;
split(part, "|", temp);
split(part, "|", data);
for(uint i = 0; i < count(part); i++) {
gtk_list_store_set(store, &iter, i, strptr(part[i]), -1);
}
}
int Listbox::get_selection() {
//... because gtk_tree_view_get_selected_row(GTK_TREE_VIEW(subwidget)) would be too easy ...
int Listbox::get_selection() {
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(subwidget));
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subwidget));
if(gtk_tree_model_get_iter_first(model, &iter) == false) { return -1; }
@ -588,18 +560,21 @@ GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subwidget));
return -1;
}
void Listbox::set_selection(int index) {
//... because gtk_tree_view_set_selected_row(GTK_TREE_VIEW(subwidget), index) would be too easy ...
void Listbox::set_selection(int index) {
int current = get_selection();
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(subwidget));
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subwidget));
gtk_tree_selection_unselect_all(selection);
if(index < 0) { return; }
if(gtk_tree_model_get_iter_first(model, &iter) == false) { return; }
if(index == 0) { gtk_tree_selection_select_iter(selection, &iter); return; }
if(index < 0) { goto end; }
if(gtk_tree_model_get_iter_first(model, &iter) == false) { goto end; }
if(index == 0) { gtk_tree_selection_select_iter(selection, &iter); goto end; }
for(uint i = 1; i < 100000; i++) {
if(gtk_tree_model_iter_next(model, &iter) == false) { return; }
if(index == i) { gtk_tree_selection_select_iter(selection, &iter); return; }
if(gtk_tree_model_iter_next(model, &iter) == false) { goto end; }
if(index == i) { gtk_tree_selection_select_iter(selection, &iter); goto end; }
}
end:
if(current != index) { owner->message(Message::Changed, (uintptr_t)this); }
}
void Listbox::reset() {

View File

@ -148,12 +148,12 @@ class Frame : public Control { public:
class Label : public Control { public:
void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = "");
void set_text(const char *str, ...);
void set_text(const char *str);
};
class Button : public Control { public:
void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = "");
void set_text(const char *str, ...);
void set_text(const char *str);
};
class Checkbox : public Control { public:
@ -185,7 +185,7 @@ enum {
};
void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *caption = "");
void set_text(const char *str, ...);
void set_text(const char *str);
uint get_text(char *str, uint length);
private:
@ -210,8 +210,8 @@ enum {
void create(Window &owner, uint style, uint x, uint y, uint width, uint height, const char *columns = "");
void autosize_columns();
void set_column_width(uint column, uint width);
void add_item(const char *data, ...);
void set_item(uint index, const char *data, ...);
void add_item(const char *data);
void set_item(uint index, const char *data);
int get_selection();
void set_selection(int index);
void reset();

View File

@ -56,6 +56,10 @@ void Window::focus() {
gtk_window_present(GTK_WINDOW(info.window));
}
bool Window::focused() {
return GTK_WIDGET_HAS_FOCUS(info.window);
}
void Window::move(uint x, uint y) {
//if window was centered before, GTK+ will ignore move requests,
//therfore we must turn off auto-centering.
@ -75,13 +79,32 @@ void Window::hide() {
gtk_widget_hide(info.window);
}
void Window::set_text(const char *str, ...) {
va_list args;
va_start(args, str);
string temp;
vsprintf(temp, str, args);
va_end(args);
gtk_window_set_title(GTK_WINDOW(info.window), strptr(temp));
void Window::show(bool state) {
(state == true) ? show() : hide();
}
bool Window::visible() {
return GTK_WIDGET_VISIBLE(info.window);
}
void Window::fullscreen() {
gtk_window_fullscreen(GTK_WINDOW(info.window));
}
void Window::unfullscreen() {
gtk_window_unfullscreen(GTK_WINDOW(info.window));
}
void Window::fullscreen(bool state) {
(state == true) ? fullscreen() : unfullscreen();
}
bool Window::is_fullscreen() {
return false;
};
void Window::set_text(const char *str) {
gtk_window_set_title(GTK_WINDOW(info.window), str);
}
void Window::set_background_color(uint8 r, uint8 g, uint8 b) {

View File

@ -170,6 +170,19 @@ uint16 translate_key(uint key) {
case VK_ESCAPE: return keymap::esc;
case VK_F1: return keymap::f1;
case VK_F2: return keymap::f2;
case VK_F3: return keymap::f3;
case VK_F4: return keymap::f4;
case VK_F5: return keymap::f5;
case VK_F6: return keymap::f6;
case VK_F7: return keymap::f7;
case VK_F8: return keymap::f8;
case VK_F9: return keymap::f9;
case VK_F10: return keymap::f10;
case VK_F11: return keymap::f11;
case VK_F12: return keymap::f12;
case VK_TAB: return keymap::tab;
case VK_RETURN: return keymap::enter;
case VK_SPACE: return keymap::space;

View File

@ -1,5 +1,5 @@
/*
libui_win ~byuu (2007-06-05)
libui_win ~byuu (2007-06-10)
license: public domain
*/
@ -60,10 +60,17 @@ MenuBar menu;
void set_text(const char *str, ...);
void set_background_color(uint8 r, uint8 g, uint8 b);
void focus();
bool focused();
void move(uint x, uint y);
void resize(uint width, uint height);
virtual void show();
virtual void hide();
void show(bool state);
bool visible();
void fullscreen();
void unfullscreen();
void fullscreen(bool state);
bool is_fullscreen();
virtual bool message(uint id, uintptr_t param = 0) { return true; }
@ -78,6 +85,7 @@ MenuBar menu;
//private:
struct {
uint width, height;
bool fullscreen;
HWND hwnd;
HWND hwnd_resize;

View File

@ -4,6 +4,10 @@ namespace libui {
* Control
*****/
void Control::move(uint x, uint y) {
SetWindowPos(hwnd, 0, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
}
void Control::resize(uint width, uint height) {
SetWindowPos(hwnd, 0, 0, 0, width, height, SWP_NOZORDER | SWP_NOMOVE);
}
@ -355,11 +359,20 @@ long __stdcall label_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
BeginPaint(hwnd, &ps);
RECT rc;
char t[4096];
GetWindowText(hwnd, t, 4095);
GetWindowText(hwnd, t, 4095); //TODO: use internal buffer, so length is not limited ...
GetClientRect(hwnd, &rc);
SetTextColor(ps.hdc, RGB(0, 0, 0));
SetBkMode(ps.hdc, TRANSPARENT);
SelectObject(ps.hdc, (HGDIOBJ)libui::font.variable);
//center text if text height < control height, otherwise draw from top left corner
RECT trc;
GetClientRect(hwnd, &trc);
DrawText(ps.hdc, t, strlen(t), &trc, DT_CALCRECT);
if(trc.bottom < rc.bottom) {
rc.top = (rc.bottom - trc.bottom) / 2;
rc.bottom = rc.top + trc.bottom;
}
//
DrawText(ps.hdc, t, strlen(t), &rc, DT_END_ELLIPSIS | DT_NOPREFIX);
EndPaint(hwnd, &ps);
} break;

View File

@ -25,6 +25,7 @@ namespace ControlType {
class Control { public:
uint type;
void move(uint x, uint y);
void resize(uint width, uint height);
void focus();

View File

@ -131,10 +131,14 @@ void Window::attach(Control &control) {
}
void Window::focus() {
show();
if(!visible()) { show(); }
SetFocus(info.hwnd);
}
bool Window::focused() {
return (GetForegroundWindow() == info.hwnd);
}
void Window::move(Control &control, uint x, uint y) {
SetWindowPos(control.hwnd, 0, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
}
@ -180,6 +184,13 @@ RECT rc;
}
void Window::resize(uint width, uint height) {
if(info.fullscreen == true) {
info.width = GetSystemMetrics(SM_CXSCREEN);
info.height = GetSystemMetrics(SM_CYSCREEN);
SetWindowPos(info.hwnd, 0, 0, 0, info.width, info.height, SWP_NOZORDER);
return;
}
info.width = width;
info.height = height;
@ -212,6 +223,36 @@ void Window::hide() {
ShowWindow(info.hwnd, SW_HIDE);
}
void Window::show(bool state) {
(state == true) ? show() : hide();
}
bool Window::visible() {
return GetWindowLong(info.hwnd, GWL_STYLE) & WS_VISIBLE;
}
void Window::fullscreen() {
if(info.fullscreen)return;
info.fullscreen = true;
SetWindowLong(info.hwnd, GWL_STYLE, WS_VISIBLE | WS_POPUP);
resize(get_screen_width(), get_screen_height());
}
void Window::unfullscreen() {
if(!info.fullscreen)return;
info.fullscreen = false;
SetWindowLong(info.hwnd, GWL_STYLE, WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | WS_VISIBLE);
resize(info.width, info.height);
}
void Window::fullscreen(bool state) {
(state == true) ? fullscreen() : unfullscreen();
}
bool Window::is_fullscreen() {
return info.fullscreen;
}
//
void Window::set_text(const char *str, ...) {
@ -234,6 +275,7 @@ HBRUSH old_brush = info.background;
//
Window::Window() {
info.fullscreen = false;
info.background = 0;
info.center = false;
info.control_index = 1;

View File

@ -64,10 +64,8 @@
* and speed is less critical.
*****/
#ifndef __LIBVECTOR
#define __LIBVECTOR
#include <new>
#ifndef LIBVECTOR_H
#define LIBVECTOR_H
template<typename T> class linear_vector {
protected:

View File

@ -27,12 +27,14 @@ IntegerSetting System::speed_fastest (&config_file, "system.speed_fastest", "Fa
struct Video {
static IntegerSetting synchronize;
static IntegerSetting fullscreen;
static IntegerSetting multiplier, aspect_correction, region;
static IntegerSetting hardware_filter, software_filter;
static IntegerSetting frameskip;
static IntegerSetting use_vram;
} video;
IntegerSetting Video::synchronize(&config_file, "video.synchronize", "Synchronize to video refresh rate.", IntegerSetting::Boolean, false);
IntegerSetting Video::fullscreen(0, "video.fullscreen", "", IntegerSetting::Boolean, false);
IntegerSetting Video::multiplier(&config_file, "video.multiplier", "Video output size multiplier (1-5x)\n"
"1 = 1x (~256x224)\n"
"2 = 2x (~512x448)\n"
@ -124,4 +126,10 @@ StringSetting Input::Joypad2::r (&config_file, "input.joypad2.r", "", "
StringSetting Input::Joypad2::select(&config_file, "input.joypad2.select", "", "lbracket");
StringSetting Input::Joypad2::start (&config_file, "input.joypad2.start", "", "rbracket");
struct Misc {
static IntegerSetting show_frame_counter;
} misc;
IntegerSetting Misc::show_frame_counter(&config_file, "misc.show_frame_counter", "Display frame counter", IntegerSetting::Boolean, true);
};

View File

@ -8,6 +8,7 @@ class Input { public:
virtual void signal_key_down(uint16 key) {}
virtual void signal_key_up (uint16 key) {}
virtual void clear_input() {}
virtual void poll() {}
virtual void init() {}
virtual void term() {}

View File

@ -21,6 +21,8 @@ public:
bool key_down(uint16 key) { return keystate[key]; }
void signal_key_down(uint16 key) { keystate[key] = true; }
void signal_key_up (uint16 key) { keystate[key] = false; }
void clear_input() { memset(keystate, 0, sizeof(keystate)); }
};
#endif

View File

@ -1,115 +1,144 @@
class InputManager { public:
struct Joypad {
uint16 up, down, left, right, a, b, x, y, l, r, select, start;
} joypad1, joypad2;
struct Joystat {
bool up, down, left, right, a, b, x, y, l, r, select, start;
} joystat1, joystat2;
void bind();
void poll();
bool get_status(uint device, uint button);
} input_manager;
void InputManager::bind() {
joypad1.up = keymap::find(config::input.joypad1.up);
joypad1.down = keymap::find(config::input.joypad1.down);
joypad1.left = keymap::find(config::input.joypad1.left);
joypad1.right = keymap::find(config::input.joypad1.right);
joypad1.a = keymap::find(config::input.joypad1.a);
joypad1.b = keymap::find(config::input.joypad1.b);
joypad1.x = keymap::find(config::input.joypad1.x);
joypad1.y = keymap::find(config::input.joypad1.y);
joypad1.l = keymap::find(config::input.joypad1.l);
joypad1.r = keymap::find(config::input.joypad1.r);
joypad1.select = keymap::find(config::input.joypad1.select);
joypad1.start = keymap::find(config::input.joypad1.start);
joystat1.up = joystat1.down = joystat1.left = joystat1.right =
joystat1.a = joystat1.b = joystat1.x = joystat1.y =
joystat1.l = joystat1.r = joystat1.select = joystat1.start = false;
joypad2.up = keymap::find(config::input.joypad2.up);
joypad2.down = keymap::find(config::input.joypad2.down);
joypad2.left = keymap::find(config::input.joypad2.left);
joypad2.right = keymap::find(config::input.joypad2.right);
joypad2.a = keymap::find(config::input.joypad2.a);
joypad2.b = keymap::find(config::input.joypad2.b);
joypad2.x = keymap::find(config::input.joypad2.x);
joypad2.y = keymap::find(config::input.joypad2.y);
joypad2.l = keymap::find(config::input.joypad2.l);
joypad2.r = keymap::find(config::input.joypad2.r);
joypad2.select = keymap::find(config::input.joypad2.select);
joypad2.start = keymap::find(config::input.joypad2.start);
joystat2.up = joystat2.down = joystat2.left = joystat2.right =
joystat2.a = joystat2.b = joystat2.x = joystat2.y =
joystat2.l = joystat2.r = joystat2.select = joystat2.start = false;
}
void InputManager::poll() {
joystat1.up = uiInput->key_down(joypad1.up);
joystat1.down = uiInput->key_down(joypad1.down);
joystat1.left = uiInput->key_down(joypad1.left);
joystat1.right = uiInput->key_down(joypad1.right);
joystat1.a = uiInput->key_down(joypad1.a);
joystat1.b = uiInput->key_down(joypad1.b);
joystat1.x = uiInput->key_down(joypad1.x);
joystat1.y = uiInput->key_down(joypad1.y);
joystat1.l = uiInput->key_down(joypad1.l);
joystat1.r = uiInput->key_down(joypad1.r);
joystat1.select = uiInput->key_down(joypad1.select);
joystat1.start = uiInput->key_down(joypad1.start);
joystat2.up = uiInput->key_down(joypad2.up);
joystat2.down = uiInput->key_down(joypad2.down);
joystat2.left = uiInput->key_down(joypad2.left);
joystat2.right = uiInput->key_down(joypad2.right);
joystat2.a = uiInput->key_down(joypad2.a);
joystat2.b = uiInput->key_down(joypad2.b);
joystat2.x = uiInput->key_down(joypad2.x);
joystat2.y = uiInput->key_down(joypad2.y);
joystat2.l = uiInput->key_down(joypad2.l);
joystat2.r = uiInput->key_down(joypad2.r);
joystat2.select = uiInput->key_down(joypad2.select);
joystat2.start = uiInput->key_down(joypad2.start);
}
bool InputManager::get_status(uint device, uint button) {
switch(device) {
case SNES::DEVICEID_JOYPAD1:
switch(button) {
case SNES::JOYPAD_UP: return joystat1.up;
case SNES::JOYPAD_DOWN: return joystat1.down;
case SNES::JOYPAD_LEFT: return joystat1.left;
case SNES::JOYPAD_RIGHT: return joystat1.right;
case SNES::JOYPAD_A: return joystat1.a;
case SNES::JOYPAD_B: return joystat1.b;
case SNES::JOYPAD_X: return joystat1.x;
case SNES::JOYPAD_Y: return joystat1.y;
case SNES::JOYPAD_L: return joystat1.l;
case SNES::JOYPAD_R: return joystat1.r;
case SNES::JOYPAD_SELECT: return joystat1.select;
case SNES::JOYPAD_START: return joystat1.start;
}
break;
case SNES::DEVICEID_JOYPAD2:
switch(button) {
case SNES::JOYPAD_UP: return joystat2.up;
case SNES::JOYPAD_DOWN: return joystat2.down;
case SNES::JOYPAD_LEFT: return joystat2.left;
case SNES::JOYPAD_RIGHT: return joystat2.right;
case SNES::JOYPAD_A: return joystat2.a;
case SNES::JOYPAD_B: return joystat2.b;
case SNES::JOYPAD_X: return joystat2.x;
case SNES::JOYPAD_Y: return joystat2.y;
case SNES::JOYPAD_L: return joystat2.l;
case SNES::JOYPAD_R: return joystat2.r;
case SNES::JOYPAD_SELECT: return joystat2.select;
case SNES::JOYPAD_START: return joystat2.start;
}
break;
}
return false;
}
class InputManager { public:
struct Joypad {
uint16 up, down, left, right, a, b, x, y, l, r, select, start;
} joypad1, joypad2;
struct Joystat {
bool up, down, left, right, a, b, x, y, l, r, select, start;
} joystat1, joystat2;
uint16 scan();
void bind();
void poll();
bool get_status(uint device, uint button);
} input_manager;
//search all key bindings, return keymap::none if no keys are active
uint16 InputManager::scan() {
uiInput->poll();
for(uint i = 0; i < keymap::limit; i++) {
if(uiInput->key_down(i)) { return i; }
}
for(uint j = 0; j < 16; j++) {
if(uiInput->key_down(keymap::joypad_flag | (j << 16) | keymap::joypad_up)) {
return (keymap::joypad_flag | (j << 16) | keymap::joypad_up);
}
if(uiInput->key_down(keymap::joypad_flag | (j << 16) | keymap::joypad_down)) {
return (keymap::joypad_flag | (j << 16) | keymap::joypad_down);
}
if(uiInput->key_down(keymap::joypad_flag | (j << 16) | keymap::joypad_left)) {
return (keymap::joypad_flag | (j << 16) | keymap::joypad_left);
}
if(uiInput->key_down(keymap::joypad_flag | (j << 16) | keymap::joypad_right)) {
return (keymap::joypad_flag | (j << 16) | keymap::joypad_right);
}
for(uint i = 0; i < 128; i++) {
if(uiInput->key_down(keymap::joypad_flag | (j << 16) | i)) {
return (keymap::joypad_flag | (j << 16) | i);
}
}
}
return keymap::none;
}
void InputManager::bind() {
joypad1.up = keymap::find(config::input.joypad1.up);
joypad1.down = keymap::find(config::input.joypad1.down);
joypad1.left = keymap::find(config::input.joypad1.left);
joypad1.right = keymap::find(config::input.joypad1.right);
joypad1.a = keymap::find(config::input.joypad1.a);
joypad1.b = keymap::find(config::input.joypad1.b);
joypad1.x = keymap::find(config::input.joypad1.x);
joypad1.y = keymap::find(config::input.joypad1.y);
joypad1.l = keymap::find(config::input.joypad1.l);
joypad1.r = keymap::find(config::input.joypad1.r);
joypad1.select = keymap::find(config::input.joypad1.select);
joypad1.start = keymap::find(config::input.joypad1.start);
joystat1.up = joystat1.down = joystat1.left = joystat1.right =
joystat1.a = joystat1.b = joystat1.x = joystat1.y =
joystat1.l = joystat1.r = joystat1.select = joystat1.start = false;
joypad2.up = keymap::find(config::input.joypad2.up);
joypad2.down = keymap::find(config::input.joypad2.down);
joypad2.left = keymap::find(config::input.joypad2.left);
joypad2.right = keymap::find(config::input.joypad2.right);
joypad2.a = keymap::find(config::input.joypad2.a);
joypad2.b = keymap::find(config::input.joypad2.b);
joypad2.x = keymap::find(config::input.joypad2.x);
joypad2.y = keymap::find(config::input.joypad2.y);
joypad2.l = keymap::find(config::input.joypad2.l);
joypad2.r = keymap::find(config::input.joypad2.r);
joypad2.select = keymap::find(config::input.joypad2.select);
joypad2.start = keymap::find(config::input.joypad2.start);
joystat2.up = joystat2.down = joystat2.left = joystat2.right =
joystat2.a = joystat2.b = joystat2.x = joystat2.y =
joystat2.l = joystat2.r = joystat2.select = joystat2.start = false;
}
void InputManager::poll() {
joystat1.up = uiInput->key_down(joypad1.up);
joystat1.down = uiInput->key_down(joypad1.down);
joystat1.left = uiInput->key_down(joypad1.left);
joystat1.right = uiInput->key_down(joypad1.right);
joystat1.a = uiInput->key_down(joypad1.a);
joystat1.b = uiInput->key_down(joypad1.b);
joystat1.x = uiInput->key_down(joypad1.x);
joystat1.y = uiInput->key_down(joypad1.y);
joystat1.l = uiInput->key_down(joypad1.l);
joystat1.r = uiInput->key_down(joypad1.r);
joystat1.select = uiInput->key_down(joypad1.select);
joystat1.start = uiInput->key_down(joypad1.start);
joystat2.up = uiInput->key_down(joypad2.up);
joystat2.down = uiInput->key_down(joypad2.down);
joystat2.left = uiInput->key_down(joypad2.left);
joystat2.right = uiInput->key_down(joypad2.right);
joystat2.a = uiInput->key_down(joypad2.a);
joystat2.b = uiInput->key_down(joypad2.b);
joystat2.x = uiInput->key_down(joypad2.x);
joystat2.y = uiInput->key_down(joypad2.y);
joystat2.l = uiInput->key_down(joypad2.l);
joystat2.r = uiInput->key_down(joypad2.r);
joystat2.select = uiInput->key_down(joypad2.select);
joystat2.start = uiInput->key_down(joypad2.start);
}
bool InputManager::get_status(uint device, uint button) {
switch(device) {
case SNES::DEVICEID_JOYPAD1:
switch(button) {
case SNES::JOYPAD_UP: return joystat1.up;
case SNES::JOYPAD_DOWN: return joystat1.down;
case SNES::JOYPAD_LEFT: return joystat1.left;
case SNES::JOYPAD_RIGHT: return joystat1.right;
case SNES::JOYPAD_A: return joystat1.a;
case SNES::JOYPAD_B: return joystat1.b;
case SNES::JOYPAD_X: return joystat1.x;
case SNES::JOYPAD_Y: return joystat1.y;
case SNES::JOYPAD_L: return joystat1.l;
case SNES::JOYPAD_R: return joystat1.r;
case SNES::JOYPAD_SELECT: return joystat1.select;
case SNES::JOYPAD_START: return joystat1.start;
}
break;
case SNES::DEVICEID_JOYPAD2:
switch(button) {
case SNES::JOYPAD_UP: return joystat2.up;
case SNES::JOYPAD_DOWN: return joystat2.down;
case SNES::JOYPAD_LEFT: return joystat2.left;
case SNES::JOYPAD_RIGHT: return joystat2.right;
case SNES::JOYPAD_A: return joystat2.a;
case SNES::JOYPAD_B: return joystat2.b;
case SNES::JOYPAD_X: return joystat2.x;
case SNES::JOYPAD_Y: return joystat2.y;
case SNES::JOYPAD_L: return joystat2.l;
case SNES::JOYPAD_R: return joystat2.r;
case SNES::JOYPAD_SELECT: return joystat2.select;
case SNES::JOYPAD_START: return joystat2.start;
}
break;
}
return false;
}

View File

@ -3,8 +3,8 @@ namespace event {
void update_frame_counter() {
if(r_ppu->status.frames_updated) {
r_ppu->status.frames_updated = false;
if(bool(true) == true) { //TODO: add config file variable to toggle fps counter
window_main.set_text("%s [%d]", BSNES_TITLE, r_ppu->status.frames_executed);
if(config::misc.show_frame_counter == true) {
window_main.set_text(string() << BSNES_TITLE << " [" << r_ppu->status.frames_executed << "]");
}
}
}
@ -16,10 +16,25 @@ uint multiplier = minmax<1, 5>(uint(config::video.multiplier));
width *= multiplier;
height *= multiplier;
if(config::video.aspect_correction == true) {
width = uint( double(width) * 8.0 / 7.0 );
if(config::video.region == 0) {
width = uint( double(width) * 8.0 / 7.0 ); //NTSC
} else {
width = uint( double(width) * 48.0 / 35.0 ); //PAL
}
}
if(config::video.fullscreen) {
//window_main.menu.hide();
window_main.fullscreen();
window_main.view.move((ui::get_screen_width() - width) / 2, (ui::get_screen_height() - height) / 2);
window_main.view.resize(width, height);
} else {
//window_main.menu.show();
window_main.unfullscreen();
window_main.resize(width, height);
window_main.view.move(0, 0);
window_main.view.resize(width, height);
}
window_main.resize(width, height);
window_main.view.resize(width, height);
}
void update_raster_settings() {
@ -40,6 +55,16 @@ uint filter, standard;
snes.set_video_standard(standard);
}
void toggle_menu() {
window_main.menu.show(!window_main.menu.visible());
update_video_settings();
}
void toggle_fullscreen() {
config::video.fullscreen = !config::video.fullscreen;
update_video_settings();
}
//
bool load_rom(char *fn) {

View File

@ -1,8 +1,10 @@
namespace event {
void update_frame_counter();
void update_video_settings();
void update_raster_settings();
void toggle_menu();
void toggle_fullscreen();
bool load_rom(char *fn);
void load_rom();

View File

@ -1,3 +1,5 @@
void run();
#if defined(PLATFORM_WIN)
#include "../../lib/libui_win.h"
#elif defined(PLATFORM_X)
@ -43,31 +45,6 @@ va_list args;
fprintf(stdout, "[%d]: %s\r\n", source, str);
}
#if 0
void set_config_filename(const char *filename) {
realpath(filename, config::filename);
//if argv[0] does not contain path information, obtain from getcwd()
//otherwise, it was retrieved from argv[0] + realpath()
if(strchr(config::filename, '/') == 0 && strchr(config::filename, '\\') == 0) {
getcwd(config::filename, PATH_MAX);
strcat(config::filename, "/");
}
//convert all path delimiters to '/'
for(int i = 0; i < strlen(config::filename); i++) {
if(config::filename[i] == '\\') { config::filename[i] = '/'; }
}
//remove program name from filename
char *p = strrchr(config::filename, '/');
if(p) { *p = 0; }
//finally, append config file name
strcat(config::filename, "/bsnes.cfg");
}
#endif
void set_config_filename() {
userpath(config::filename);
strcat(config::filename, "/.bsnes");
@ -75,6 +52,14 @@ void set_config_filename() {
strcat(config::filename, "/bsnes.cfg");
}
void run() {
while(ui::events_pending() == true) { ui::run(); }
if(cartridge.loaded() == true) {
snes.runtoframe();
event::update_frame_counter();
}
}
#if defined(PLATFORM_WIN)
int __stdcall WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) {
int argc = __argc;
@ -100,11 +85,7 @@ int main(int argc, char *argv[]) {
}
while(_term_ == false) {
while(ui::events_pending() == true) { ui::run(); }
if(cartridge.loaded() == true) {
snes.runtoframe();
event::update_frame_counter();
}
run();
}
event::unload_rom();

View File

@ -5,10 +5,10 @@ ui::Control *control = (ui::Control*)param;
set_val.enable(pos >= 0);
set_def.enable(pos >= 0);
if(pos >= 0 && pos < config_file.list_count) {
desc.set_text("(default = %s)\n%s", config_file.list[pos]->def, config_file.list[pos]->desc);
desc.set_text(string() << "(default = " << config_file.list[pos]->def << ")\n" << config_file.list[pos]->desc);
string val;
config_file.list[pos]->get(val);
edit_val.set_text("%s", strptr(val));
edit_val.set_text(strptr(val));
}
} else if(id == ui::Message::Clicked && control == &set_val) {
char t[4096];
@ -40,7 +40,7 @@ void AdvancedWindow::update(uint pos, const char *data) {
config_file.list[pos]->set(data ? data : config_file.list[pos]->def);
string val;
config_file.list[pos]->get(val);
edit_val.set_text("%s", strptr(val));
edit_val.set_text(strptr(val));
read_config(pos, val);
list.set_item(pos, strptr(val));
list.autosize_columns();

View File

@ -92,31 +92,48 @@ void InputConfigWindow::set_value(uint index, uint16 value) {
void InputConfigWindow::refresh_list() {
for(uint i = 0; i < 24; i++) {
list.set_item(i, "%s|%s", list_index[i], keymap::find(get_value(i)));
list.set_item(i, string() << list_index[i] << "|" << keymap::find(get_value(i)));
}
list.autosize_columns();
}
bool InputConfigWindow::message(uint id, uintptr_t param) {
ui::Control *control = (ui::Control*)param;
if(id == ui::Message::KeyDown) {
if(uiInput) { uiInput->signal_key_down(param); }
return true;
}
if(id == ui::Message::KeyUp) {
if(uiInput) { uiInput->signal_key_up(param); }
return true;
}
if(id == ui::Message::Changed && control == &list) {
int pos = list.get_selection();
setkey.enable(pos >= 0);
clrkey.enable(pos >= 0);
} else if((id == ui::Message::DoubleClicked && control == &list) ||
(id == ui::Message::Clicked && control == &setkey)) {
return true;
}
if((id == ui::Message::DoubleClicked && control == &list) ||
(id == ui::Message::Clicked && control == &setkey)) {
int pos = list.get_selection();
if(pos < 0) { return true; }
window_input_capture.index = pos;
window_input_capture.label.set_text("Please press a key to assign to '%s' ...", list_index[pos]);
window_input_capture.label.set_text(string() << "Please press a key to assign to " << list_index[pos] << " ...");
window_input_capture.show();
window_input_capture.focus();
} else if(id == ui::Message::Clicked && control == &clrkey) {
return true;
}
if(id == ui::Message::Clicked && control == &clrkey) {
int pos = list.get_selection();
if(pos < 0) { return true; }
set_value(pos, keymap::none);
refresh_list();
return true;
}
return true;
}
@ -124,16 +141,16 @@ void InputConfigWindow::setup() {
create(0, 475, 355);
int x = 0, y = 0;
lportA.create(*this, 0, x, y + 7, 105, 15, "Controller Port A:");
portA.create(*this, 0, x + 110, y, 125, 30);
lportA.create(*this, 0, x, y, 105, 30, "Controller Port A:");
portA.create (*this, 0, x + 110, y, 125, 30);
portA.add_item("None");
portA.add_item("Joypad 1");
portA.add_item("Joypad 2");
portA.set_selection(1);
portA.disable();
lportB.create(*this, 0, x + 240, y + 7, 105, 15, "Controller Port B:");
portB.create(*this, 0, x + 350, y, 125, 30);
lportB.create(*this, 0, x + 240, y, 105, 30, "Controller Port B:");
portB.create (*this, 0, x + 350, y, 125, 30);
portB.add_item("None");
portB.add_item("Joypad 1");
portB.add_item("Joypad 2");
@ -163,16 +180,44 @@ bool InputCaptureWindow::message(uint id, uintptr_t param) {
return false;
}
if(id == ui::Message::KeyDown) {
if(uiInput) { uiInput->signal_key_down(param); }
return true;
}
if(id == ui::Message::KeyUp) {
hide();
window_input_config.set_value(index, param);
window_input_config.refresh_list();
if(uiInput) { uiInput->signal_key_up(param); }
return true;
}
return true;
}
void InputCaptureWindow::show() {
uiInput->clear_input();
//enter and spacebar can be used to activate key capture,
//set lock on these keys if they are held down to prevent
//them from being instantly assigned to selected entry ...
uiInput->poll();
key_lock = (uiInput->key_down(keymap::enter) || uiInput->key_down(keymap::space));
Window::show();
Window::focus();
while(_term_ == false && visible() == true) {
run();
uint16 key = input_manager.scan();
if(key == keymap::none) { key_lock = false; continue; }
if(key_lock && (key == keymap::enter || key == keymap::space)) { continue; }
hide();
window_input_config.set_value(index, key);
window_input_config.refresh_list();
break;
}
uiInput->clear_input();
}
void InputCaptureWindow::setup() {
create(ui::Window::Center, 350, 100, "bsnes Key Capture");
label.create(*this, 0, 5, 5, 340, 90);

View File

@ -1,7 +1,9 @@
class InputCaptureWindow : public ui::Window { public:
ui::Label label;
uint index;
bool key_lock;
bool message(uint id, uintptr_t param = 0);
void show();
void setup();
InputCaptureWindow() : index(0) {}
} window_input_capture;

View File

@ -4,19 +4,19 @@ ui::Control *control = (ui::Control*)param;
if(control == &contrast) {
if(config::snes.contrast != contrast.get_position() - 96) {
config::snes.contrast = contrast.get_position() - 96;
lcontrast.set_text("Contrast: %d", int(config::snes.contrast));
lcontrast.set_text(string() << "Contrast: " << config::snes.contrast);
snes.update_color_lookup_table();
}
} else if(control == &brightness) {
if(config::snes.brightness != brightness.get_position() - 96) {
config::snes.brightness = brightness.get_position() - 96;
lbrightness.set_text("Brightness: %d", int(config::snes.brightness));
lbrightness.set_text(string() << "Brightness: " << config::snes.brightness);
snes.update_color_lookup_table();
}
} else if(control == &gamma) {
if(config::snes.gamma != gamma.get_position() + 10) {
config::snes.gamma = gamma.get_position() + 10;
lgamma.set_text("Gamma: %0.2f", double(config::snes.gamma) / 100.0);
lgamma.set_text(string() << "Gamma: " << config::snes.gamma); //TODO: print gamma as "%0.2f" / 100.0
snes.update_color_lookup_table();
}
}
@ -72,11 +72,11 @@ ui::Control *control = (ui::Control*)param;
//update all UI controls to match config file values ...
void RasterSettingsWindow::sync_ui() {
contrast.set_position(config::snes.contrast + 96);
lcontrast.set_text("Contrast: %d", int(config::snes.contrast));
lcontrast.set_text(string() << "Contrast: " << config::snes.contrast);
brightness.set_position(config::snes.brightness + 96);
lbrightness.set_text("Brightness: %d", int(config::snes.brightness));
lbrightness.set_text(string() << "Brightness: " << config::snes.brightness);
gamma.set_position(config::snes.gamma - 10);
lgamma.set_text("Gamma: %0.2f", double(config::snes.gamma) / 100.0);
lgamma.set_text(string() << "Gamma: " << config::snes.gamma); //TODO: print gamma as "%0.2f" / 100.0
gamma_ramp.check(config::snes.gamma_ramp);
sepia.check(config::snes.sepia);
grayscale.check(config::snes.grayscale);
@ -88,16 +88,16 @@ void RasterSettingsWindow::setup() {
create(0, 475, 355);
int x = 0, y = 0;
lcontrast.create(*this, 0, x, y + 5, 100, 15);
contrast.create(*this, 0, x + 100, y, 375, 25, 192);
lcontrast.create(*this, 0, x, y, 100, 25);
contrast.create (*this, 0, x + 100, y, 375, 25, 192);
y += 25;
lbrightness.create(*this, 0, x, y + 5, 100, 15);
brightness.create(*this, 0, x + 100, y, 375, 25, 192);
lbrightness.create(*this, 0, x, y, 100, 25);
brightness.create (*this, 0, x + 100, y, 375, 25, 192);
y += 25;
lgamma.create(*this, 0, x, y + 5, 100, 15);
gamma.create(*this, 0, x + 100, y, 375, 25, 191);
lgamma.create(*this, 0, x, y, 100, 25);
gamma.create (*this, 0, x + 100, y, 375, 25, 191);
y += 25;
gamma_ramp.create(*this, 0, x, y, 235, 20, "Gamma ramp");

View File

@ -13,6 +13,8 @@ ui::Control *control = (ui::Control*)param;
if(id == ui::Message::KeyDown) {
if(uiInput) { uiInput->signal_key_down(param); }
if(param == keymap::esc) { event::toggle_menu(); }
if(param == keymap::f11) { event::toggle_fullscreen(); }
return true;
}

View File

@ -9,6 +9,13 @@ bool VideoXv::lock(uint16 *&data, uint &pitch) {
void VideoXv::unlock() {
}
void VideoXv::clear_video() {
memset(buffer, 0, 1024 * 1024 * sizeof(uint16));
//clear twice in case video is double buffered ...
refresh(1024, 1024);
refresh(1024, 1024);
}
void VideoXv::refresh(uint r_width, uint r_height) {
Window dw;
int d0, d1;
@ -109,6 +116,10 @@ unsigned int adaptor_count;
XvFreeAdaptorInfo(adaptor_info);
if(xv_port == -1) { printf("VideoXv: failed to find valid XvPort.\n"); }
//set colorkey to auto paint, so that Xv video output is always visible
const Atom atom = XInternAtom(display, "XV_AUTOPAINT_COLORKEY", true);
if(atom != None) { XvSetPortAttribute(display, xv_port, atom, 1); }
//0x00000003 = 32-bit X8R8G8B8 [xRGB] (few drivers support this mode)
//0x32595559 = 16-bit Y8U8,Y8V8 [YUY2] (most drivers support this mode)
xvimage = XvShmCreateImage(display, xv_port, 0x32595559, 0, 1024, 1024, &shminfo);
@ -119,6 +130,7 @@ unsigned int adaptor_count;
if(!XShmAttach(display, &shminfo)) { printf("VideoXv: XShmAttach failed.\n"); }
init_yuv_tables();
clear_video();
}
VideoXv::~VideoXv() {

View File

@ -28,6 +28,7 @@ public:
uint screen_width() { return gdk_screen_width(); }
uint screen_height() { return gdk_screen_height(); }
void clear_video();
void refresh(uint width, uint height);
void init();
void term();