mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-09-19 11:21:32 +02:00
Compare commits
26 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
9b03874f32 | ||
|
a9bff19b5b | ||
|
20be19f876 | ||
|
f748a34e49 | ||
|
0af5703c47 | ||
|
f73d0908c4 | ||
|
18389cb8f7 | ||
|
448a8336b1 | ||
|
233e645772 | ||
|
f0627239bb | ||
|
ae67f268a8 | ||
|
b2331ddb85 | ||
|
2a2f50a8bc | ||
|
30b19613d5 | ||
|
98fc865130 | ||
|
f6a04682f5 | ||
|
87b91f0ace | ||
|
0114e10ede | ||
|
8c591ce44a | ||
|
e2cc164f70 | ||
|
d09e54149b | ||
|
8e4f1be189 | ||
|
f529a84fd1 | ||
|
567d415290 | ||
|
435a194ccd | ||
|
df9de289b9 |
30
readme.txt
30
readme.txt
@@ -1,5 +1,5 @@
|
|||||||
bsnes
|
bsnes
|
||||||
Version: 0.034
|
Version: 0.037a
|
||||||
Author: byuu
|
Author: byuu
|
||||||
|
|
||||||
========
|
========
|
||||||
@@ -38,9 +38,9 @@ If you wish to have multiple configuration profiles for the same user, you will
|
|||||||
need to make copies of the bsnes executable, and use each one in single-user
|
need to make copies of the bsnes executable, and use each one in single-user
|
||||||
mode.
|
mode.
|
||||||
|
|
||||||
==================
|
====================
|
||||||
Known Limitations:
|
Known Limitation(s):
|
||||||
==================
|
====================
|
||||||
|
|
||||||
S-CPU
|
S-CPU
|
||||||
- Multiply / divide register delays not implemented
|
- Multiply / divide register delays not implemented
|
||||||
@@ -60,6 +60,16 @@ Hardware Bugs
|
|||||||
- S-CPU.r1 HDMA crashing bug not emulated
|
- S-CPU.r1 HDMA crashing bug not emulated
|
||||||
- S-CPU<>S-SMP communication bus conflicts not emulated
|
- S-CPU<>S-SMP communication bus conflicts not emulated
|
||||||
|
|
||||||
|
===============
|
||||||
|
Known Issue(s):
|
||||||
|
===============
|
||||||
|
|
||||||
|
On Windows, attempting to load a ZIP, GZ or JMA compressed archive with
|
||||||
|
non-ANSI characters in the filename will fail. This is because Windows
|
||||||
|
requires UTF-16 encoding, but these libraries only work with UTF-8.
|
||||||
|
Note that loading uncompressed images (SMC, SFC, etc) with non-ANSI characters
|
||||||
|
works properly on all platforms.
|
||||||
|
|
||||||
=====================
|
=====================
|
||||||
Unsupported Hardware:
|
Unsupported Hardware:
|
||||||
=====================
|
=====================
|
||||||
@@ -89,18 +99,10 @@ SETA RISC CPU used by Quick-move Shogi Match with Nidan Rank-holder Morita 2
|
|||||||
Super Gameboy
|
Super Gameboy
|
||||||
Cartridge passthrough used for playing Gameboy games
|
Cartridge passthrough used for playing Gameboy games
|
||||||
|
|
||||||
========================
|
|
||||||
Unsupported Controllers:
|
|
||||||
========================
|
|
||||||
|
|
||||||
Mouse
|
|
||||||
Super Scope
|
|
||||||
Justifier
|
|
||||||
|
|
||||||
=============
|
=============
|
||||||
Contributors:
|
Contributors:
|
||||||
=============
|
=============
|
||||||
|
|
||||||
Andreas Naive, anomie, blargg, DMV27, FitzRoy, GIGO, Jonas Quinn, kode54, krom,
|
Andreas Naive, anomie, blargg, DMV27, FitzRoy, GIGO, Jonas Quinn, kode54, krom,
|
||||||
mudlord, Nach, neviksti, Overload, RedDwarf, Richard Bannister, tetsuo55, TRAC,
|
Matthew Callis, mudlord, Nach, neviksti, Overload, RedDwarf, Richard Bannister,
|
||||||
zones
|
tetsuo55, TRAC, zones
|
||||||
|
@@ -133,7 +133,7 @@ obj/bsnesrc.$(obj): ui/bsnes.rc; windres ui/bsnes.rc obj/bsnesrc.$(obj)
|
|||||||
### libraries ###
|
### libraries ###
|
||||||
#################
|
#################
|
||||||
|
|
||||||
obj/ruby.$(obj): lib/ruby/ruby.cpp lib/ruby/*
|
obj/ruby.$(obj): lib/ruby/ruby.cpp lib/ruby/* lib/ruby/video/* lib/ruby/audio/* lib/ruby/input/*
|
||||||
$(call compile,$(rubydef) $(rubyflags))
|
$(call compile,$(rubydef) $(rubyflags))
|
||||||
obj/hiro.$(obj): lib/hiro/hiro.cpp lib/hiro/* lib/hiro/gtk/* lib/hiro/win/*
|
obj/hiro.$(obj): lib/hiro/hiro.cpp lib/hiro/* lib/hiro/gtk/* lib/hiro/win/*
|
||||||
$(call compile,$(if $(call streq,$(platform),x),`pkg-config --cflags gtk+-2.0`))
|
$(call compile,$(if $(call streq,$(platform),x),`pkg-config --cflags gtk+-2.0`))
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
#define BSNES_VERSION "0.034"
|
#define BSNES_VERSION "0.037a"
|
||||||
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
||||||
|
|
||||||
#define BUSCORE sBus
|
#define BUSCORE sBus
|
||||||
@@ -24,12 +24,15 @@
|
|||||||
#include <nall/bit.hpp>
|
#include <nall/bit.hpp>
|
||||||
#include <nall/config.hpp>
|
#include <nall/config.hpp>
|
||||||
#include <nall/detect.hpp>
|
#include <nall/detect.hpp>
|
||||||
|
#include <nall/endian.hpp>
|
||||||
|
#include <nall/file.hpp>
|
||||||
#include <nall/function.hpp>
|
#include <nall/function.hpp>
|
||||||
#include <nall/modulo.hpp>
|
#include <nall/modulo.hpp>
|
||||||
#include <nall/new.hpp>
|
#include <nall/new.hpp>
|
||||||
#include <nall/sort.hpp>
|
#include <nall/sort.hpp>
|
||||||
#include <nall/stdint.hpp>
|
#include <nall/stdint.hpp>
|
||||||
#include <nall/string.hpp>
|
#include <nall/string.hpp>
|
||||||
|
#include <nall/utility.hpp>
|
||||||
#include <nall/vector.hpp>
|
#include <nall/vector.hpp>
|
||||||
using namespace nall;
|
using namespace nall;
|
||||||
|
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include <nall/crc32.hpp>
|
#include <nall/crc32.hpp>
|
||||||
#include <nall/ups.hpp>
|
#include <nall/ups.hpp>
|
||||||
|
|
||||||
|
#include "cart_load.cpp"
|
||||||
#include "cart_normal.cpp"
|
#include "cart_normal.cpp"
|
||||||
#include "cart_bsx.cpp"
|
#include "cart_bsx.cpp"
|
||||||
#include "cart_bsc.cpp"
|
#include "cart_bsc.cpp"
|
||||||
@@ -21,12 +22,13 @@ namespace memory {
|
|||||||
|
|
||||||
Cartridge cartridge;
|
Cartridge cartridge;
|
||||||
|
|
||||||
|
const char* Cartridge::name() { return info.filename; }
|
||||||
|
Cartridge::CartridgeMode Cartridge::mode() { return info.mode; }
|
||||||
Cartridge::MemoryMapper Cartridge::mapper() { return info.mapper; }
|
Cartridge::MemoryMapper Cartridge::mapper() { return info.mapper; }
|
||||||
Cartridge::Region Cartridge::region() { return info.region; }
|
Cartridge::Region Cartridge::region() { return info.region; }
|
||||||
|
|
||||||
bool Cartridge::loaded() { return cart.loaded; }
|
bool Cartridge::loaded() { return cart.loaded; }
|
||||||
|
|
||||||
void Cartridge::load_begin(CartridgeType cart_type) {
|
void Cartridge::load_begin(CartridgeMode mode) {
|
||||||
cart.rom = cart.ram = cart.rtc = 0;
|
cart.rom = cart.ram = cart.rtc = 0;
|
||||||
bs.ram = 0;
|
bs.ram = 0;
|
||||||
stA.rom = stA.ram = 0;
|
stA.rom = stA.ram = 0;
|
||||||
@@ -37,39 +39,11 @@ void Cartridge::load_begin(CartridgeType cart_type) {
|
|||||||
stA.rom_size = stA.ram_size = 0;
|
stA.rom_size = stA.ram_size = 0;
|
||||||
stB.rom_size = stB.ram_size = 0;
|
stB.rom_size = stB.ram_size = 0;
|
||||||
|
|
||||||
info.type = cart_type;
|
info.mode = mode;
|
||||||
info.patched = false;
|
info.patched = false;
|
||||||
|
|
||||||
info.bsxbase = false;
|
|
||||||
info.bsxcart = false;
|
info.bsxcart = false;
|
||||||
info.bsxflash = false;
|
info.bsxflash = false;
|
||||||
info.st = false;
|
|
||||||
|
|
||||||
info.superfx = false;
|
|
||||||
info.sa1 = false;
|
|
||||||
info.srtc = false;
|
|
||||||
info.sdd1 = false;
|
|
||||||
info.spc7110 = false;
|
|
||||||
info.spc7110rtc = false;
|
|
||||||
info.cx4 = false;
|
|
||||||
info.dsp1 = false;
|
|
||||||
info.dsp2 = false;
|
|
||||||
info.dsp3 = false;
|
|
||||||
info.dsp4 = false;
|
|
||||||
info.obc1 = false;
|
|
||||||
info.st010 = false;
|
|
||||||
info.st011 = false;
|
|
||||||
info.st018 = false;
|
|
||||||
|
|
||||||
info.dsp1_mapper = DSP1Unmapped;
|
|
||||||
|
|
||||||
info.header_index = 0xffc0;
|
|
||||||
info.mapper = LoROM;
|
|
||||||
info.name[0] = 0;
|
|
||||||
info.region = NTSC;
|
|
||||||
|
|
||||||
info.rom_size = 0;
|
|
||||||
info.ram_size = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cartridge::load_end() {
|
void Cartridge::load_end() {
|
||||||
@@ -90,7 +64,7 @@ void Cartridge::load_end() {
|
|||||||
memory::stBrom.write_protect(true);
|
memory::stBrom.write_protect(true);
|
||||||
memory::stBram.write_protect(false);
|
memory::stBram.write_protect(false);
|
||||||
|
|
||||||
if(fexists(get_cheat_filename(cart.fn, "cht"))) {
|
if(file::exists(get_cheat_filename(cart.fn, "cht"))) {
|
||||||
cheat.clear();
|
cheat.clear();
|
||||||
cheat.load(cheatfn);
|
cheat.load(cheatfn);
|
||||||
}
|
}
|
||||||
@@ -104,11 +78,11 @@ bool Cartridge::unload() {
|
|||||||
|
|
||||||
bus.unload_cart();
|
bus.unload_cart();
|
||||||
|
|
||||||
switch(info.type) {
|
switch(info.mode) {
|
||||||
case CartridgeNormal: unload_cart_normal(); break;
|
case ModeNormal: unload_cart_normal(); break;
|
||||||
case CartridgeBSX: unload_cart_bsx(); break;
|
case ModeBSX: unload_cart_bsx(); break;
|
||||||
case CartridgeBSC: unload_cart_bsc(); break;
|
case ModeBSC: unload_cart_bsc(); break;
|
||||||
case CartridgeSufamiTurbo: unload_cart_st(); break;
|
case ModeSufamiTurbo: unload_cart_st(); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cart.rom) { delete[] cart.rom; cart.rom = 0; }
|
if(cart.rom) { delete[] cart.rom; cart.rom = 0; }
|
||||||
@@ -120,10 +94,7 @@ bool Cartridge::unload() {
|
|||||||
if(stB.rom) { delete[] stB.rom; stB.rom = 0; }
|
if(stB.rom) { delete[] stB.rom; stB.rom = 0; }
|
||||||
if(stB.ram) { delete[] stB.ram; stB.ram = 0; }
|
if(stB.ram) { delete[] stB.ram; stB.ram = 0; }
|
||||||
|
|
||||||
char fn[PATH_MAX];
|
if(cheat.count() > 0 || file::exists(get_cheat_filename(cart.fn, "cht"))) {
|
||||||
strcpy(fn, cart.fn);
|
|
||||||
modify_extension(fn, "cht");
|
|
||||||
if(cheat.count() > 0 || fexists(get_cheat_filename(cart.fn, "cht"))) {
|
|
||||||
cheat.save(cheatfn);
|
cheat.save(cheatfn);
|
||||||
cheat.clear();
|
cheat.clear();
|
||||||
}
|
}
|
||||||
@@ -139,3 +110,58 @@ Cartridge::Cartridge() {
|
|||||||
Cartridge::~Cartridge() {
|
Cartridge::~Cartridge() {
|
||||||
if(cart.loaded == true) unload();
|
if(cart.loaded == true) unload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
void Cartridge::cartinfo_t::reset() {
|
||||||
|
type = TypeUnknown;
|
||||||
|
mapper = LoROM;
|
||||||
|
dsp1_mapper = DSP1Unmapped;
|
||||||
|
region = NTSC;
|
||||||
|
|
||||||
|
rom_size = 0;
|
||||||
|
ram_size = 0;
|
||||||
|
|
||||||
|
bsxslot = false;
|
||||||
|
superfx = false;
|
||||||
|
sa1 = false;
|
||||||
|
srtc = false;
|
||||||
|
sdd1 = false;
|
||||||
|
spc7110 = false;
|
||||||
|
spc7110rtc = false;
|
||||||
|
cx4 = false;
|
||||||
|
dsp1 = false;
|
||||||
|
dsp2 = false;
|
||||||
|
dsp3 = false;
|
||||||
|
dsp4 = false;
|
||||||
|
obc1 = false;
|
||||||
|
st010 = false;
|
||||||
|
st011 = false;
|
||||||
|
st018 = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//apply cart-specific settings to current cartridge mode settings
|
||||||
|
Cartridge::info_t& Cartridge::info_t::operator=(const Cartridge::cartinfo_t &source) {
|
||||||
|
mapper = source.mapper;
|
||||||
|
dsp1_mapper = source.dsp1_mapper;
|
||||||
|
region = source.region;
|
||||||
|
|
||||||
|
bsxslot = source.bsxslot;
|
||||||
|
superfx = source.superfx;
|
||||||
|
sa1 = source.sa1;
|
||||||
|
srtc = source.srtc;
|
||||||
|
sdd1 = source.sdd1;
|
||||||
|
spc7110 = source.spc7110;
|
||||||
|
spc7110rtc = source.spc7110rtc;
|
||||||
|
cx4 = source.cx4;
|
||||||
|
dsp1 = source.dsp1;
|
||||||
|
dsp2 = source.dsp2;
|
||||||
|
dsp3 = source.dsp3;
|
||||||
|
dsp4 = source.dsp4;
|
||||||
|
obc1 = source.obc1;
|
||||||
|
st010 = source.st010;
|
||||||
|
st011 = source.st011;
|
||||||
|
st018 = source.st018;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
103
src/cart/cart.h
103
src/cart/cart.h
@@ -1,10 +1,20 @@
|
|||||||
class Cartridge {
|
class Cartridge {
|
||||||
public:
|
public:
|
||||||
|
enum CartridgeMode {
|
||||||
|
ModeNormal,
|
||||||
|
ModeBSC,
|
||||||
|
ModeBSX,
|
||||||
|
ModeSufamiTurbo,
|
||||||
|
};
|
||||||
|
|
||||||
enum CartridgeType {
|
enum CartridgeType {
|
||||||
CartridgeNormal,
|
TypeNormal,
|
||||||
CartridgeBSX,
|
TypeBSC,
|
||||||
CartridgeBSC,
|
TypeBSXBIOS,
|
||||||
CartridgeSufamiTurbo,
|
TypeBSX,
|
||||||
|
TypeSufamiTurboBIOS,
|
||||||
|
TypeSufamiTurbo,
|
||||||
|
TypeUnknown,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum HeaderField {
|
enum HeaderField {
|
||||||
@@ -18,8 +28,7 @@ public:
|
|||||||
VERSION = 0x1b,
|
VERSION = 0x1b,
|
||||||
ICKSUM = 0x1c,
|
ICKSUM = 0x1c,
|
||||||
CKSUM = 0x1e,
|
CKSUM = 0x1e,
|
||||||
RESL = 0x3c,
|
RESETV = 0x3c,
|
||||||
RESH = 0x3d,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Region {
|
enum Region {
|
||||||
@@ -33,9 +42,9 @@ public:
|
|||||||
ExLoROM,
|
ExLoROM,
|
||||||
ExHiROM,
|
ExHiROM,
|
||||||
SPC7110ROM,
|
SPC7110ROM,
|
||||||
BSXROM,
|
|
||||||
BSCLoROM,
|
BSCLoROM,
|
||||||
BSCHiROM,
|
BSCHiROM,
|
||||||
|
BSXROM,
|
||||||
STROM,
|
STROM,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -46,6 +55,11 @@ public:
|
|||||||
DSP1HiROM,
|
DSP1HiROM,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char* name();
|
||||||
|
CartridgeMode mode();
|
||||||
|
MemoryMapper mapper();
|
||||||
|
Region region();
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool loaded;
|
bool loaded;
|
||||||
char fn[PATH_MAX];
|
char fn[PATH_MAX];
|
||||||
@@ -65,23 +79,16 @@ public:
|
|||||||
uint rom_size, ram_size;
|
uint rom_size, ram_size;
|
||||||
} stA, stB;
|
} stA, stB;
|
||||||
|
|
||||||
struct {
|
struct cartinfo_t {
|
||||||
CartridgeType type;
|
CartridgeType type;
|
||||||
|
|
||||||
uint32 crc32;
|
|
||||||
char filename[PATH_MAX * 4];
|
|
||||||
char name[128];
|
|
||||||
bool patched;
|
|
||||||
|
|
||||||
Region region;
|
|
||||||
MemoryMapper mapper;
|
MemoryMapper mapper;
|
||||||
uint rom_size;
|
DSP1MemoryMapper dsp1_mapper;
|
||||||
uint ram_size;
|
Region region;
|
||||||
|
|
||||||
bool bsxbase;
|
unsigned rom_size;
|
||||||
bool bsxcart;
|
unsigned ram_size;
|
||||||
bool bsxflash;
|
|
||||||
bool st;
|
bool bsxslot;
|
||||||
bool superfx;
|
bool superfx;
|
||||||
bool sa1;
|
bool sa1;
|
||||||
bool srtc;
|
bool srtc;
|
||||||
@@ -98,17 +105,53 @@ public:
|
|||||||
bool st011;
|
bool st011;
|
||||||
bool st018;
|
bool st018;
|
||||||
|
|
||||||
DSP1MemoryMapper dsp1_mapper;
|
void reset();
|
||||||
|
};
|
||||||
|
|
||||||
uint header_index;
|
struct info_t {
|
||||||
|
char filename[PATH_MAX * 4];
|
||||||
|
bool patched;
|
||||||
|
|
||||||
|
CartridgeMode mode;
|
||||||
|
MemoryMapper mapper;
|
||||||
|
DSP1MemoryMapper dsp1_mapper;
|
||||||
|
Region region;
|
||||||
|
|
||||||
|
bool bsxcart; //is BS-X cart inserted?
|
||||||
|
bool bsxflash; //is BS-X flash cart inserted into BS-X cart?
|
||||||
|
|
||||||
|
bool bsxslot;
|
||||||
|
bool superfx;
|
||||||
|
bool sa1;
|
||||||
|
bool srtc;
|
||||||
|
bool sdd1;
|
||||||
|
bool spc7110;
|
||||||
|
bool spc7110rtc;
|
||||||
|
bool cx4;
|
||||||
|
bool dsp1;
|
||||||
|
bool dsp2;
|
||||||
|
bool dsp3;
|
||||||
|
bool dsp4;
|
||||||
|
bool obc1;
|
||||||
|
bool st010;
|
||||||
|
bool st011;
|
||||||
|
bool st018;
|
||||||
|
|
||||||
|
info_t& operator=(const cartinfo_t&);
|
||||||
} info;
|
} info;
|
||||||
|
|
||||||
MemoryMapper mapper();
|
struct {
|
||||||
Region region();
|
char fn[PATH_MAX];
|
||||||
|
uint8_t *data;
|
||||||
|
unsigned size;
|
||||||
|
} image;
|
||||||
|
bool load_image(const char*);
|
||||||
|
bool inspect_image(cartinfo_t &cartinfo, const char *filename);
|
||||||
|
bool load_ram(const char *filename, uint8_t *&data, unsigned size, uint8_t init);
|
||||||
|
|
||||||
void load_cart_normal(const char*);
|
void load_cart_normal(const char*);
|
||||||
void load_cart_bsx(const char*, const char*);
|
|
||||||
void load_cart_bsc(const char*, const char*);
|
void load_cart_bsc(const char*, const char*);
|
||||||
|
void load_cart_bsx(const char*, const char*);
|
||||||
void load_cart_st(const char*, const char*, const char*);
|
void load_cart_st(const char*, const char*, const char*);
|
||||||
|
|
||||||
void unload_cart_normal();
|
void unload_cart_normal();
|
||||||
@@ -117,13 +160,13 @@ public:
|
|||||||
void unload_cart_st();
|
void unload_cart_st();
|
||||||
|
|
||||||
bool loaded();
|
bool loaded();
|
||||||
void load_begin(CartridgeType);
|
void load_begin(CartridgeMode);
|
||||||
void load_end();
|
void load_end();
|
||||||
bool unload();
|
bool unload();
|
||||||
|
|
||||||
void find_header();
|
void read_header(cartinfo_t &info, const uint8_t *data, unsigned size);
|
||||||
void read_header();
|
unsigned find_header(const uint8_t *data, unsigned size);
|
||||||
void read_extended_header();
|
unsigned score_header(const uint8_t *data, unsigned size, unsigned addr);
|
||||||
|
|
||||||
enum CompressionMode {
|
enum CompressionMode {
|
||||||
CompressionNone, //always load without compression
|
CompressionNone, //always load without compression
|
||||||
|
@@ -1,57 +1,36 @@
|
|||||||
#ifdef CART_CPP
|
#ifdef CART_CPP
|
||||||
|
|
||||||
void Cartridge::load_cart_bsc(const char *base, const char *slot) {
|
void Cartridge::load_cart_bsc(const char *base, const char *slot) {
|
||||||
if(!base || !*base) return;
|
uint8_t *data;
|
||||||
|
|
||||||
strcpy(cart.fn, base);
|
|
||||||
strcpy(bs.fn, slot ? slot : "");
|
|
||||||
load_begin(CartridgeBSC);
|
|
||||||
|
|
||||||
uint8_t *data = 0;
|
|
||||||
unsigned size;
|
unsigned size;
|
||||||
load_file(cart.fn, data, size, CompressionAuto);
|
strcpy(cart.fn, base);
|
||||||
cart.rom = data, cart.rom_size = size;
|
strcpy(bs.fn, slot);
|
||||||
|
|
||||||
if(load_file(get_patch_filename(cart.fn, "ups"), data, size, CompressionInspect) == true) {
|
load_begin(ModeBSC);
|
||||||
apply_patch(data, size, cart.rom, cart.rom_size);
|
if(load_image(base) == false) return;
|
||||||
delete[] data;
|
|
||||||
|
cartinfo_t cartinfo;
|
||||||
|
read_header(cartinfo, cart.rom = image.data, cart.rom_size = image.size);
|
||||||
|
info = cartinfo;
|
||||||
|
|
||||||
|
if(load_image(slot) == true) {
|
||||||
|
info.bsxflash = true;
|
||||||
|
bs.ram = image.data;
|
||||||
|
bs.ram_size = image.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(*bs.fn) {
|
if(cartinfo.ram_size > 0) {
|
||||||
if(load_file(bs.fn, data, size, CompressionAuto) == true) {
|
load_ram(get_save_filename(base, "srm"), cart.ram, cart.ram_size = cartinfo.ram_size, 0xff);
|
||||||
info.bsxflash = true;
|
|
||||||
bs.ram = data, bs.ram_size = size;
|
|
||||||
if(load_file(get_patch_filename(bs.fn, "ups"), data, size, CompressionInspect) == true) {
|
|
||||||
apply_patch(data, size, bs.ram, bs.ram_size);
|
|
||||||
delete[] data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
find_header();
|
|
||||||
read_header();
|
|
||||||
|
|
||||||
info.mapper = cartridge.info.header_index == 0x7fc0 ? BSCLoROM : BSCHiROM;
|
|
||||||
info.region = NTSC;
|
|
||||||
|
|
||||||
if(info.ram_size > 0) {
|
|
||||||
cart.ram = new uint8_t[cart.ram_size = info.ram_size];
|
|
||||||
memset(cart.ram, 0xff, cart.ram_size);
|
|
||||||
|
|
||||||
if(load_file(get_save_filename(cart.fn, "srm"), data, size, CompressionNone) == true) {
|
|
||||||
memcpy(cart.ram, data, min(size, cart.ram_size));
|
|
||||||
delete[] data;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
load_end();
|
load_end();
|
||||||
|
|
||||||
//set base filename
|
//set base filename
|
||||||
strcpy(info.filename, cart.fn);
|
strcpy(info.filename, base);
|
||||||
get_base_filename(info.filename);
|
get_base_filename(info.filename);
|
||||||
if(*bs.fn) {
|
if(*slot) {
|
||||||
char filenameBS[PATH_MAX];
|
char filenameBS[PATH_MAX];
|
||||||
strcpy(filenameBS, bs.fn);
|
strcpy(filenameBS, slot);
|
||||||
get_base_filename(filenameBS);
|
get_base_filename(filenameBS);
|
||||||
strcat(info.filename, " + ");
|
strcat(info.filename, " + ");
|
||||||
strcat(info.filename, filenameBS);
|
strcat(info.filename, filenameBS);
|
||||||
|
@@ -1,27 +1,20 @@
|
|||||||
#ifdef CART_CPP
|
#ifdef CART_CPP
|
||||||
|
|
||||||
void Cartridge::load_cart_bsx(const char *base, const char *slot) {
|
void Cartridge::load_cart_bsx(const char *base, const char *slot) {
|
||||||
if(!base || !*base) return;
|
uint8_t *data;
|
||||||
|
|
||||||
strcpy(cart.fn, base);
|
|
||||||
strcpy(bs.fn, slot ? slot : "");
|
|
||||||
|
|
||||||
load_begin(CartridgeBSX);
|
|
||||||
info.bsxbase = true;
|
|
||||||
info.bsxcart = true;
|
|
||||||
info.mapper = BSXROM;
|
|
||||||
info.region = NTSC;
|
|
||||||
|
|
||||||
uint8_t *data = 0;
|
|
||||||
unsigned size;
|
unsigned size;
|
||||||
load_file(cart.fn, data, size, CompressionAuto);
|
strcpy(cart.fn, base);
|
||||||
cart.rom = data, cart.rom_size = size;
|
strcpy(bs.fn, slot);
|
||||||
cart.ram = 0, cart.ram_size = 0;
|
|
||||||
|
|
||||||
if(load_file(get_patch_filename(cart.fn, "ups"), data, size, CompressionInspect) == true) {
|
load_begin(ModeBSX);
|
||||||
apply_patch(data, size, cart.rom, cart.rom_size);
|
if(load_image(base) == false) return;
|
||||||
delete[] data;
|
info.bsxcart = true;
|
||||||
}
|
|
||||||
|
cartinfo_t cartinfo;
|
||||||
|
read_header(cartinfo, cart.rom = image.data, cart.rom_size = image.size);
|
||||||
|
info = cartinfo;
|
||||||
|
cart.ram = 0;
|
||||||
|
cart.ram_size = 0;
|
||||||
|
|
||||||
memset(bsxcart.sram.handle (), 0x00, bsxcart.sram.size ());
|
memset(bsxcart.sram.handle (), 0x00, bsxcart.sram.size ());
|
||||||
memset(bsxcart.psram.handle(), 0x00, bsxcart.psram.size());
|
memset(bsxcart.psram.handle(), 0x00, bsxcart.psram.size());
|
||||||
@@ -36,20 +29,15 @@ void Cartridge::load_cart_bsx(const char *base, const char *slot) {
|
|||||||
delete[] data;
|
delete[] data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(*bs.fn) {
|
if(load_image(slot)) {
|
||||||
if(load_file(bs.fn, data, size, CompressionAuto) == true) {
|
info.bsxflash = true;
|
||||||
info.bsxflash = true;
|
bs.ram = image.data;
|
||||||
bs.ram = data, bs.ram_size = size;
|
bs.ram_size = image.size;
|
||||||
if(load_file(get_patch_filename(bs.fn, "ups"), data, size, CompressionInspect) == true) {
|
|
||||||
apply_patch(data, size, bs.ram, bs.ram_size);
|
|
||||||
delete[] data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
load_end();
|
load_end();
|
||||||
|
|
||||||
strcpy(info.filename, !*bs.fn ? cart.fn : bs.fn);
|
strcpy(info.filename, !*slot ? base : slot);
|
||||||
get_base_filename(info.filename);
|
get_base_filename(info.filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -47,6 +47,8 @@ char* Cartridge::get_base_filename(char *filename) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* Cartridge::get_path_filename(char *filename, const char *path, const char *source, const char *extension) {
|
char* Cartridge::get_path_filename(char *filename, const char *path, const char *source, const char *extension) {
|
||||||
@@ -87,7 +89,7 @@ char* Cartridge::get_cheat_filename(const char *source, const char *extension) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size, CompressionMode compression) {
|
bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size, CompressionMode compression) {
|
||||||
if(fexists(fn) == false) return false;
|
if(file::exists(fn) == false) return false;
|
||||||
|
|
||||||
Reader::Type filetype = Reader::Normal;
|
Reader::Type filetype = Reader::Normal;
|
||||||
if(compression == CompressionInspect) filetype = Reader::detect(fn, true);
|
if(compression == CompressionInspect) filetype = Reader::detect(fn, true);
|
||||||
@@ -120,6 +122,10 @@ bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size, CompressionM
|
|||||||
|
|
||||||
case Reader::ZIP: {
|
case Reader::ZIP: {
|
||||||
ZipReader zf(fn);
|
ZipReader zf(fn);
|
||||||
|
if(!zf.ready()) {
|
||||||
|
alert("Error loading image file (%s)!", fn);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
size = zf.size();
|
size = zf.size();
|
||||||
data = zf.read();
|
data = zf.read();
|
||||||
} break;
|
} break;
|
||||||
@@ -155,22 +161,22 @@ bool Cartridge::apply_patch(const uint8_t *pdata, const unsigned psize, uint8_t
|
|||||||
if(result == ups::output_crc32_invalid) apply = true;
|
if(result == ups::output_crc32_invalid) apply = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if patch application was successful, replace old data, size with new data, size
|
||||||
if(apply == true) {
|
if(apply == true) {
|
||||||
delete[] data;
|
delete[] data;
|
||||||
data = new uint8_t[size = outsize];
|
data = new uint8_t[size = outsize];
|
||||||
memcpy(data, outdata, outsize);
|
memcpy(data, outdata, outsize);
|
||||||
} else {
|
|
||||||
dprintf("* Warning: patch application failed!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(outdata) delete[] outdata;
|
if(outdata) delete[] outdata;
|
||||||
|
return apply;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Cartridge::save_file(const char *fn, uint8 *data, uint size) {
|
bool Cartridge::save_file(const char *fn, uint8 *data, uint size) {
|
||||||
FILE *fp = fopen(fn, "wb");
|
file fp;
|
||||||
if(!fp) return false;
|
if(!fp.open(fn, file::mode_write)) return false;
|
||||||
fwrite(data, 1, size, fp);
|
fp.write(data, size);
|
||||||
fclose(fp);
|
fp.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,30 +1,70 @@
|
|||||||
#ifdef CART_CPP
|
#ifdef CART_CPP
|
||||||
|
|
||||||
void Cartridge::read_header() {
|
void Cartridge::read_header(cartinfo_t &info, const uint8_t *data, unsigned size) {
|
||||||
uint8 *rom = cart.rom;
|
info.reset();
|
||||||
uint index = info.header_index;
|
unsigned index = find_header(data, size);
|
||||||
uint8 mapper = rom[index + MAPPER];
|
|
||||||
uint8 rom_type = rom[index + ROM_TYPE];
|
|
||||||
uint8 rom_size = rom[index + ROM_SIZE];
|
|
||||||
uint8 company = rom[index + COMPANY];
|
|
||||||
uint8 region = rom[index + REGION] & 0x7f;
|
|
||||||
|
|
||||||
//detect presence of BS-X flash cartridge connector (reads extended header information)
|
//detect BS-X flash carts
|
||||||
bool has_bsxflash = false;
|
if(data[index + 0x13] == 0x00 || data[index + 0x13] == 0xff) {
|
||||||
if(rom[index - 14] == 'Z') {
|
if(data[index + 0x14] == 0x00) {
|
||||||
if(rom[index - 11] == 'J') {
|
const uint8_t n15 = data[index + 0x15];
|
||||||
uint8 n13 = rom[index - 13];
|
if(n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c || n15 == 0xbc || n15 == 0xfc) {
|
||||||
if((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9')) {
|
if(data[index + 0x1a] == 0x33 || data[index + 0x1a] == 0xff) {
|
||||||
if(company == 0x33 || (rom[index - 10] == 0x00 && rom[index - 4] == 0x00)) {
|
info.type = TypeBSX;
|
||||||
has_bsxflash = true;
|
info.mapper = BSXROM;
|
||||||
|
info.region = NTSC; //BS-X only released in Japan
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(has_bsxflash == true) {
|
//detect Sufami Turbo carts
|
||||||
info.mapper = index == 0x7fc0 ? BSCLoROM : BSCHiROM;
|
if(!memcmp(data, "BANDAI SFC-ADX", 14)) {
|
||||||
} else if(index == 0x7fc0 && cart.rom_size >= 0x401000) {
|
if(!memcmp(data + 16, "SFC-ADX BACKUP", 14)) {
|
||||||
|
info.type = TypeSufamiTurboBIOS;
|
||||||
|
} else {
|
||||||
|
info.type = TypeSufamiTurbo;
|
||||||
|
}
|
||||||
|
info.mapper = STROM;
|
||||||
|
info.region = NTSC; //Sufami Turbo only released in Japan
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//standard cart
|
||||||
|
uint8 mapper = data[index + MAPPER];
|
||||||
|
uint8 rom_type = data[index + ROM_TYPE];
|
||||||
|
uint8 rom_size = data[index + ROM_SIZE];
|
||||||
|
uint8 company = data[index + COMPANY];
|
||||||
|
uint8 region = data[index + REGION] & 0x7f;
|
||||||
|
|
||||||
|
//detect presence of BS-X flash cartridge connector (reads extended header information)
|
||||||
|
if(data[index - 14] == 'Z') {
|
||||||
|
if(data[index - 11] == 'J') {
|
||||||
|
uint8 n13 = data[index - 13];
|
||||||
|
if((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9')) {
|
||||||
|
if(company == 0x33 || (data[index - 10] == 0x00 && data[index - 4] == 0x00)) {
|
||||||
|
info.bsxslot = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(info.bsxslot == true) {
|
||||||
|
if(!memcmp(data + index, "Satellaview BS-X ", 21)) {
|
||||||
|
//BS-X base cart
|
||||||
|
info.type = TypeBSXBIOS;
|
||||||
|
info.mapper = BSXROM;
|
||||||
|
} else {
|
||||||
|
info.type = TypeBSC;
|
||||||
|
info.mapper = (index == 0x7fc0 ? BSCLoROM : BSCHiROM);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
info.type = TypeNormal;
|
||||||
|
|
||||||
|
if(index == 0x7fc0 && size >= 0x401000) {
|
||||||
info.mapper = ExLoROM;
|
info.mapper = ExLoROM;
|
||||||
} else if(index == 0x7fc0 && mapper == 0x32) {
|
} else if(index == 0x7fc0 && mapper == 0x32) {
|
||||||
info.mapper = ExLoROM;
|
info.mapper = ExLoROM;
|
||||||
@@ -75,7 +115,7 @@ void Cartridge::read_header() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(info.dsp1 == true) {
|
if(info.dsp1 == true) {
|
||||||
if((mapper & 0x2f) == 0x20 && cart.rom_size <= 0x100000) {
|
if((mapper & 0x2f) == 0x20 && size <= 0x100000) {
|
||||||
info.dsp1_mapper = DSP1LoROM1MB;
|
info.dsp1_mapper = DSP1LoROM1MB;
|
||||||
} else if((mapper & 0x2f) == 0x20) {
|
} else if((mapper & 0x2f) == 0x20) {
|
||||||
info.dsp1_mapper = DSP1LoROM2MB;
|
info.dsp1_mapper = DSP1LoROM2MB;
|
||||||
@@ -112,86 +152,110 @@ void Cartridge::read_header() {
|
|||||||
info.st018 = true;
|
info.st018 = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(rom[info.header_index + RAM_SIZE] & 7) {
|
if(data[index + RAM_SIZE] & 7) {
|
||||||
info.ram_size = 1024 << (rom[info.header_index + RAM_SIZE] & 7);
|
info.ram_size = 1024 << (data[index + RAM_SIZE] & 7);
|
||||||
} else {
|
} else {
|
||||||
info.ram_size = 0;
|
info.ram_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//0, 1, 13 = NTSC; 2 - 12 = PAL
|
//0, 1, 13 = NTSC; 2 - 12 = PAL
|
||||||
info.region = (region <= 1 || region >= 13) ? NTSC : PAL;
|
info.region = (region <= 1 || region >= 13) ? NTSC : PAL;
|
||||||
|
|
||||||
memcpy(&info.name, &rom[info.header_index + CART_NAME], 21);
|
|
||||||
info.name[21] = 0;
|
|
||||||
trim(info.name);
|
|
||||||
|
|
||||||
//convert undisplayable characters (half-width katakana, etc) to '?' characters
|
|
||||||
for(int i = 0; i < 21; i++) {
|
|
||||||
if(info.name[i] & 0x80) info.name[i] = '?';
|
|
||||||
}
|
|
||||||
|
|
||||||
//always display something
|
|
||||||
if(!info.name[0]) strcpy(info.name, "(untitled)");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cartridge::find_header() {
|
unsigned Cartridge::find_header(const uint8_t *data, unsigned size) {
|
||||||
int32 score_lo = 0, score_hi = 0, score_ex = 0;
|
unsigned score_lo = score_header(data, size, 0x007fc0);
|
||||||
uint8_t *rom = cart.rom;
|
unsigned score_hi = score_header(data, size, 0x00ffc0);
|
||||||
|
unsigned score_ex = score_header(data, size, 0x40ffc0);
|
||||||
if(cart.rom_size < 0x010000) {
|
if(score_ex) score_ex += 4; //favor ExHiROM on images > 32mbits
|
||||||
//cart too small to be anything but lorom
|
|
||||||
info.header_index = 0x007fc0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((rom[0x7fc0 + MAPPER] & ~0x10) == 0x20) score_lo++;
|
|
||||||
if((rom[0xffc0 + MAPPER] & ~0x10) == 0x21) score_hi++;
|
|
||||||
|
|
||||||
if(rom[0x7fc0 + ROM_TYPE] < 0x08) score_lo++;
|
|
||||||
if(rom[0xffc0 + ROM_TYPE] < 0x08) score_hi++;
|
|
||||||
|
|
||||||
if(rom[0x7fc0 + ROM_SIZE] < 0x10) score_lo++;
|
|
||||||
if(rom[0xffc0 + ROM_SIZE] < 0x10) score_hi++;
|
|
||||||
|
|
||||||
if(rom[0x7fc0 + RAM_SIZE] < 0x08) score_lo++;
|
|
||||||
if(rom[0xffc0 + RAM_SIZE] < 0x08) score_hi++;
|
|
||||||
|
|
||||||
if(rom[0x7fc0 + REGION] < 14) score_lo++;
|
|
||||||
if(rom[0xffc0 + REGION] < 14) score_hi++;
|
|
||||||
|
|
||||||
if(rom[0x7fc0 + COMPANY] < 3) score_lo++;
|
|
||||||
if(rom[0xffc0 + COMPANY] < 3) score_hi++;
|
|
||||||
|
|
||||||
if(rom[0x7fc0 + RESH] & 0x80) score_lo += 2;
|
|
||||||
if(rom[0xffc0 + RESH] & 0x80) score_hi += 2;
|
|
||||||
|
|
||||||
uint16 cksum, icksum;
|
|
||||||
cksum = rom[0x7fc0 + CKSUM] | (rom[0x7fc0 + CKSUM + 1] << 8);
|
|
||||||
icksum = rom[0x7fc0 + ICKSUM] | (rom[0x7fc0 + ICKSUM + 1] << 8);
|
|
||||||
if((cksum + icksum) == 0xffff && (cksum != 0) && (icksum != 0)) {
|
|
||||||
score_lo += 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
cksum = rom[0xffc0 + CKSUM] | (rom[0xffc0 + CKSUM + 1] << 8);
|
|
||||||
icksum = rom[0xffc0 + ICKSUM] | (rom[0xffc0 + ICKSUM + 1] << 8);
|
|
||||||
if((cksum + icksum) == 0xffff && (cksum != 0) && (icksum != 0)) {
|
|
||||||
score_hi += 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(cart.rom_size < 0x401000) {
|
|
||||||
score_ex = 0;
|
|
||||||
} else {
|
|
||||||
if(rom[0x7fc0 + MAPPER] == 0x32) score_lo++;
|
|
||||||
else score_ex += 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(score_lo >= score_hi && score_lo >= score_ex) {
|
if(score_lo >= score_hi && score_lo >= score_ex) {
|
||||||
info.header_index = 0x007fc0;
|
return 0x007fc0;
|
||||||
} else if(score_hi >= score_ex) {
|
} else if(score_hi >= score_ex) {
|
||||||
info.header_index = 0x00ffc0;
|
return 0x00ffc0;
|
||||||
} else {
|
} else {
|
||||||
info.header_index = 0x40ffc0;
|
return 0x40ffc0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned Cartridge::score_header(const uint8_t *data, unsigned size, unsigned addr) {
|
||||||
|
if(size < addr + 64) return 0; //image too small to contain header at this location?
|
||||||
|
int score = 0;
|
||||||
|
|
||||||
|
uint16 resetvector = data[addr + RESETV] | (data[addr + RESETV + 1] << 8);
|
||||||
|
uint16 checksum = data[addr + CKSUM] | (data[addr + CKSUM + 1] << 8);
|
||||||
|
uint16 ichecksum = data[addr + ICKSUM] | (data[addr + ICKSUM + 1] << 8);
|
||||||
|
|
||||||
|
uint8 resetop = data[(addr & ~0x7fff) | (resetvector & 0x7fff)]; //first opcode executed upon reset
|
||||||
|
uint8 mapper = data[addr + MAPPER] & ~0x10; //mask off irrelevent FastROM-capable bit
|
||||||
|
|
||||||
|
//$00:[000-7fff] contains uninitialized RAM and MMIO.
|
||||||
|
//reset vector must point to ROM at $00:[8000-ffff] to be considered valid.
|
||||||
|
if(resetvector < 0x8000) return 0;
|
||||||
|
|
||||||
|
//some images duplicate the header in multiple locations, and others have completely
|
||||||
|
//invalid header information that cannot be relied upon.
|
||||||
|
//below code will analyze the first opcode executed at the specified reset vector to
|
||||||
|
//determine the probability that this is the correct header.
|
||||||
|
|
||||||
|
//most likely opcodes
|
||||||
|
if(resetop == 0x78 //sei
|
||||||
|
|| resetop == 0x18 //clc (clc; xce)
|
||||||
|
|| resetop == 0x38 //sec (sec; xce)
|
||||||
|
|| resetop == 0x9c //stz $nnnn (stz $4200)
|
||||||
|
|| resetop == 0x4c //jmp $nnnn
|
||||||
|
|| resetop == 0x5c //jml $nnnnnn
|
||||||
|
) score += 8;
|
||||||
|
|
||||||
|
//plausible opcodes
|
||||||
|
if(resetop == 0xc2 //rep #$nn
|
||||||
|
|| resetop == 0xe2 //sep #$nn
|
||||||
|
|| resetop == 0xad //lda $nnnn
|
||||||
|
|| resetop == 0xae //ldx $nnnn
|
||||||
|
|| resetop == 0xac //ldy $nnnn
|
||||||
|
|| resetop == 0xaf //lda $nnnnnn
|
||||||
|
|| resetop == 0xa9 //lda #$nn
|
||||||
|
|| resetop == 0xa2 //ldx #$nn
|
||||||
|
|| resetop == 0xa0 //ldy #$nn
|
||||||
|
|| resetop == 0x20 //jsr $nnnn
|
||||||
|
|| resetop == 0x22 //jsl $nnnnnn
|
||||||
|
) score += 4;
|
||||||
|
|
||||||
|
//implausible opcodes
|
||||||
|
if(resetop == 0x40 //rti
|
||||||
|
|| resetop == 0x60 //rts
|
||||||
|
|| resetop == 0x6b //rtl
|
||||||
|
|| resetop == 0xcd //cmp $nnnn
|
||||||
|
|| resetop == 0xec //cpx $nnnn
|
||||||
|
|| resetop == 0xcc //cpy $nnnn
|
||||||
|
) score -= 4;
|
||||||
|
|
||||||
|
//least likely opcodes
|
||||||
|
if(resetop == 0x00 //brk #$nn
|
||||||
|
|| resetop == 0x02 //cop #$nn
|
||||||
|
|| resetop == 0xdb //stp
|
||||||
|
|| resetop == 0x42 //wdm
|
||||||
|
|| resetop == 0xff //sbc $nnnnnn,x
|
||||||
|
) score -= 8;
|
||||||
|
|
||||||
|
//at times, both the header and reset vector's first opcode will match ...
|
||||||
|
//fallback and rely on info validity in these cases to determine more likely header.
|
||||||
|
|
||||||
|
//a valid checksum is the biggest indicator of a valid header.
|
||||||
|
if((checksum + ichecksum) == 0xffff && (checksum != 0) && (ichecksum != 0)) score += 4;
|
||||||
|
|
||||||
|
if(addr == 0x007fc0 && mapper == 0x20) score += 2; //0x20 is usually LoROM
|
||||||
|
if(addr == 0x00ffc0 && mapper == 0x21) score += 2; //0x21 is usually HiROM
|
||||||
|
if(addr == 0x007fc0 && mapper == 0x22) score += 2; //0x22 is usually ExLoROM
|
||||||
|
if(addr == 0x40ffc0 && mapper == 0x25) score += 2; //0x25 is usually ExHiROM
|
||||||
|
|
||||||
|
if(data[addr + COMPANY] == 0x33) score += 2; //0x33 indicates extended header
|
||||||
|
if(data[addr + ROM_TYPE] < 0x08) score++;
|
||||||
|
if(data[addr + ROM_SIZE] < 0x10) score++;
|
||||||
|
if(data[addr + RAM_SIZE] < 0x08) score++;
|
||||||
|
if(data[addr + REGION] < 14) score++;
|
||||||
|
|
||||||
|
if(score < 0) score = 0;
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
#endif //ifdef CART_CPP
|
#endif //ifdef CART_CPP
|
||||||
|
50
src/cart/cart_load.cpp
Normal file
50
src/cart/cart_load.cpp
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#ifdef CART_CPP
|
||||||
|
|
||||||
|
bool Cartridge::load_image(const char *filename) {
|
||||||
|
if(!filename || !*filename) return false;
|
||||||
|
|
||||||
|
uint8_t *data;
|
||||||
|
unsigned size;
|
||||||
|
if(!load_file(filename, data, size, CompressionAuto)) return false;
|
||||||
|
|
||||||
|
if((size & 0x7fff) != 512) {
|
||||||
|
image.data = data;
|
||||||
|
image.size = size;
|
||||||
|
} else {
|
||||||
|
//remove 512-byte header
|
||||||
|
image.data = new uint8_t[image.size = size - 512];
|
||||||
|
memcpy(image.data, data + 512, image.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(load_file(get_patch_filename(filename, "ups"), data, size, CompressionInspect) == true) {
|
||||||
|
apply_patch(data, size, image.data, image.size);
|
||||||
|
delete[] data;
|
||||||
|
info.patched = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Cartridge::inspect_image(cartinfo_t &cartinfo, const char *filename) {
|
||||||
|
cartinfo.reset();
|
||||||
|
if(!load_image(filename)) return false;
|
||||||
|
|
||||||
|
read_header(cartinfo, image.data, image.size);
|
||||||
|
delete[] image.data;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Cartridge::load_ram(const char *filename, uint8_t *&data, unsigned size, uint8_t init) {
|
||||||
|
data = new uint8_t[size];
|
||||||
|
memset(data, init, size);
|
||||||
|
|
||||||
|
uint8_t *savedata;
|
||||||
|
unsigned savesize;
|
||||||
|
if(load_file(filename, savedata, savesize, CompressionNone) == false) return false;
|
||||||
|
|
||||||
|
memcpy(data, savedata, min(size, savesize));
|
||||||
|
delete[] savedata;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //ifdef CART_CPP
|
@@ -1,58 +1,29 @@
|
|||||||
#ifdef CART_CPP
|
#ifdef CART_CPP
|
||||||
|
|
||||||
void Cartridge::load_cart_normal(const char *filename) {
|
void Cartridge::load_cart_normal(const char *base) {
|
||||||
if(!filename || !*filename) return;
|
uint8_t *data;
|
||||||
|
|
||||||
uint8_t *data = 0;
|
|
||||||
unsigned size;
|
unsigned size;
|
||||||
if(load_file(filename, data, size, CompressionAuto) == false) return;
|
strcpy(cart.fn, base);
|
||||||
strcpy(cart.fn, filename);
|
|
||||||
|
|
||||||
load_begin(CartridgeNormal);
|
load_begin(ModeNormal);
|
||||||
|
if(load_image(base) == false) return;
|
||||||
|
|
||||||
//load ROM data, ignore 512-byte header if detected
|
cartinfo_t cartinfo;
|
||||||
if((size & 0x7fff) != 512) {
|
read_header(cartinfo, cart.rom = image.data, cart.rom_size = image.size);
|
||||||
cart.rom = new uint8_t[cart.rom_size = size];
|
info = cartinfo;
|
||||||
memcpy(cart.rom, data, size);
|
|
||||||
} else {
|
|
||||||
cart.rom = new uint8_t[cart.rom_size = size - 512];
|
|
||||||
memcpy(cart.rom, data + 512, size - 512);
|
|
||||||
}
|
|
||||||
delete[] data;
|
|
||||||
|
|
||||||
if(load_file(get_patch_filename(cart.fn, "ups"), data, size, CompressionInspect) == true) {
|
if(cartinfo.ram_size > 0) {
|
||||||
apply_patch(data, size, cart.rom, cart.rom_size);
|
load_ram(get_save_filename(base, "srm"), cart.ram, cart.ram_size = cartinfo.ram_size, 0xff);
|
||||||
delete[] data;
|
|
||||||
info.patched = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
info.crc32 = crc32_calculate(cart.rom, cart.rom_size);
|
if(cartinfo.srtc || cartinfo.spc7110rtc) {
|
||||||
|
load_ram(get_save_filename(base, "rtc"), cart.rtc, cart.rtc_size = 20, 0x00);
|
||||||
find_header();
|
|
||||||
read_header();
|
|
||||||
|
|
||||||
if(info.ram_size > 0) {
|
|
||||||
cart.ram = new uint8_t[cart.ram_size = info.ram_size];
|
|
||||||
memset(cart.ram, 0xff, cart.ram_size);
|
|
||||||
|
|
||||||
if(load_file(get_save_filename(cart.fn, "srm"), data, size, CompressionNone) == true) {
|
|
||||||
memcpy(cart.ram, data, min(size, cart.ram_size));
|
|
||||||
delete[] data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(info.srtc || info.spc7110rtc) {
|
|
||||||
cart.rtc = new(zeromemory) uint8_t[cart.rtc_size = 20];
|
|
||||||
if(load_file(get_save_filename(cart.fn, "rtc"), data, size, CompressionNone) == true) {
|
|
||||||
memcpy(cart.rtc, data, min(size, cart.rtc_size));
|
|
||||||
delete[] data;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
load_end();
|
load_end();
|
||||||
|
|
||||||
//set base filename
|
//set base filename
|
||||||
strcpy(info.filename, cart.fn);
|
strcpy(info.filename, base);
|
||||||
get_base_filename(info.filename);
|
get_base_filename(info.filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,86 +1,52 @@
|
|||||||
#ifdef CART_CPP
|
#ifdef CART_CPP
|
||||||
|
|
||||||
void Cartridge::load_cart_st(const char *base, const char *slotA, const char *slotB) {
|
void Cartridge::load_cart_st(const char *base, const char *slotA, const char *slotB) {
|
||||||
if(!base || !*base) return;
|
uint8_t *data;
|
||||||
|
|
||||||
strcpy(cart.fn, base);
|
|
||||||
strcpy(stA.fn, slotA ? slotA : "");
|
|
||||||
strcpy(stB.fn, slotB ? slotB : "");
|
|
||||||
|
|
||||||
load_begin(CartridgeSufamiTurbo);
|
|
||||||
info.st = true;
|
|
||||||
info.mapper = STROM;
|
|
||||||
info.region = NTSC;
|
|
||||||
|
|
||||||
uint8_t *data = 0;
|
|
||||||
unsigned size;
|
unsigned size;
|
||||||
if(load_file(cart.fn, data, size, CompressionAuto) == true) {
|
strcpy(cart.fn, base);
|
||||||
cart.rom = new(zeromemory) uint8_t[cart.rom_size = 0x040000];
|
strcpy(stA.fn, slotA);
|
||||||
memcpy(cart.rom, data, min(size, cart.rom_size));
|
strcpy(stB.fn, slotB);
|
||||||
delete[] data;
|
|
||||||
if(load_file(get_patch_filename(cart.fn, "ups"), data, size, CompressionInspect) == true) {
|
load_begin(ModeSufamiTurbo);
|
||||||
apply_patch(data, size, cart.rom, cart.rom_size);
|
if(load_image(base) == false) return;
|
||||||
delete[] data;
|
|
||||||
}
|
cartinfo_t cartinfo;
|
||||||
|
read_header(cartinfo, cart.rom = image.data, cart.rom_size = image.size);
|
||||||
|
info = cartinfo;
|
||||||
|
|
||||||
|
if(load_image(slotA)) {
|
||||||
|
stA.rom = new(zeromemory) uint8_t[stA.rom_size = 0x100000];
|
||||||
|
memcpy(stA.rom, image.data, min(image.size, stA.rom_size));
|
||||||
|
delete[] image.data;
|
||||||
|
|
||||||
|
load_ram(get_save_filename(slotA, "srm"), stA.ram, stA.ram_size = 0x020000, 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(*stA.fn) {
|
if(load_image(slotB)) {
|
||||||
if(load_file(stA.fn, data, size, CompressionAuto) == true) {
|
stB.rom = new(zeromemory) uint8_t[stB.rom_size = 0x100000];
|
||||||
stA.rom = new(zeromemory) uint8_t[stA.rom_size = 0x100000];
|
memcpy(stB.rom, image.data, min(image.size, stB.rom_size));
|
||||||
memcpy(stA.rom, data, min(size, stA.rom_size));
|
delete[] image.data;
|
||||||
delete[] data;
|
|
||||||
if(load_file(get_patch_filename(stA.fn, "ups"), data, size, CompressionInspect) == true) {
|
|
||||||
apply_patch(data, size, stA.rom, stA.rom_size);
|
|
||||||
delete[] data;
|
|
||||||
}
|
|
||||||
|
|
||||||
stA.ram = new uint8_t[stA.ram_size = 0x020000];
|
load_ram(get_save_filename(slotB, "srm"), stB.ram, stB.ram_size = 0x020000, 0xff);
|
||||||
memset(stA.ram, 0xff, stA.ram_size);
|
|
||||||
|
|
||||||
if(load_file(get_save_filename(stA.fn, "srm"), data, size, CompressionNone) == true) {
|
|
||||||
memcpy(stA.ram, data, min(size, 0x020000U));
|
|
||||||
delete[] data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(*stB.fn) {
|
|
||||||
if(load_file(stB.fn, data, size, CompressionAuto) == true) {
|
|
||||||
stB.rom = new(zeromemory) uint8_t[stB.rom_size = 0x100000];
|
|
||||||
memcpy(stB.rom, data, min(size, stB.rom_size));
|
|
||||||
delete[] data;
|
|
||||||
if(load_file(get_patch_filename(stB.fn, "ups"), data, size, CompressionInspect) == true) {
|
|
||||||
apply_patch(data, size, stB.rom, stB.rom_size);
|
|
||||||
delete[] data;
|
|
||||||
}
|
|
||||||
|
|
||||||
stB.ram = new uint8_t[stB.ram_size = 0x020000];
|
|
||||||
memset(stB.ram, 0xff, stB.ram_size);
|
|
||||||
|
|
||||||
if(load_file(get_save_filename(stB.fn, "srm"), data, size, CompressionNone) == true) {
|
|
||||||
memcpy(stB.ram, data, min(size, 0x020000U));
|
|
||||||
delete[] data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
load_end();
|
load_end();
|
||||||
|
|
||||||
//set base filename
|
//set base filename
|
||||||
if(!*stA.fn && !*stB.fn) {
|
if(!*slotA && !*slotB) {
|
||||||
strcpy(info.filename, cart.fn);
|
strcpy(info.filename, cart.fn);
|
||||||
get_base_filename(info.filename);
|
get_base_filename(info.filename);
|
||||||
} else if(*stA.fn && !*stB.fn) {
|
} else if(*slotA && !*slotB) {
|
||||||
strcpy(info.filename, stA.fn);
|
strcpy(info.filename, slotA);
|
||||||
get_base_filename(info.filename);
|
get_base_filename(info.filename);
|
||||||
} else if(!*stA.fn && *stB.fn) {
|
} else if(!*slotA && *slotB) {
|
||||||
strcpy(info.filename, stB.fn);
|
strcpy(info.filename, slotB);
|
||||||
get_base_filename(info.filename);
|
get_base_filename(info.filename);
|
||||||
} else {
|
} else {
|
||||||
char filenameA[PATH_MAX], filenameB[PATH_MAX];
|
char filenameA[PATH_MAX], filenameB[PATH_MAX];
|
||||||
strcpy(filenameA, stA.fn);
|
strcpy(filenameA, slotA);
|
||||||
get_base_filename(filenameA);
|
get_base_filename(filenameA);
|
||||||
strcpy(filenameB, stB.fn);
|
strcpy(filenameB, slotB);
|
||||||
get_base_filename(filenameB);
|
get_base_filename(filenameB);
|
||||||
strcpy(info.filename, filenameA);
|
strcpy(info.filename, filenameA);
|
||||||
strcat(info.filename, " + ");
|
strcat(info.filename, " + ");
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
::@make platform=win compiler=mingw32-gcc
|
@make platform=win compiler=mingw32-gcc
|
||||||
@make platform=win compiler=mingw32-gcc enable_gzip=true enable_jma=true
|
::@make platform=win compiler=mingw32-gcc enable_gzip=true enable_jma=true
|
||||||
@pause
|
@pause
|
||||||
|
@@ -1,30 +1,53 @@
|
|||||||
#include "../base.h"
|
#include "../base.h"
|
||||||
#include "../reader/filereader.h"
|
|
||||||
|
|
||||||
Cheat cheat;
|
Cheat cheat;
|
||||||
|
|
||||||
|
Cheat::cheat_t& Cheat::cheat_t::operator=(const Cheat::cheat_t& source) {
|
||||||
|
enabled = source.enabled;
|
||||||
|
addr = source.addr;
|
||||||
|
data = source.data;
|
||||||
|
code = source.code;
|
||||||
|
desc = source.desc;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//used to sort cheat code list by description
|
||||||
|
bool Cheat::cheat_t::operator<(const Cheat::cheat_t& source) {
|
||||||
|
return strcmp(desc, source.desc) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
* string <> binary code translation routines
|
* string <> binary code translation routines
|
||||||
* decode() "7e1234:56" -> 0x7e123456
|
* decode() "7e1234:56" -> 0x7e123456
|
||||||
* encode() 0x7e123456 -> "7e1234:56"
|
* encode() 0x7e123456 -> "7e1234:56"
|
||||||
*****/
|
*****/
|
||||||
|
|
||||||
bool Cheat::decode(char *str, uint32 &addr, uint8 &data, uint8 &type) {
|
bool Cheat::decode(const char *str, unsigned &addr, uint8 &data, type_t &type) {
|
||||||
string t, part;
|
string t = str;
|
||||||
strcpy(t, str);
|
strlower(t);
|
||||||
strlower(t());
|
|
||||||
if(strlen(t) == 8 || (strlen(t) == 9 && t()[6] == ':')) {
|
#define ischr(n) ((n >= '0' && n <= '9') || (n >= 'a' && n <= 'f'))
|
||||||
|
|
||||||
|
if(strlen(t) == 8 || (strlen(t) == 9 && t[6] == ':')) {
|
||||||
|
//strip ':'
|
||||||
|
if(strlen(t) == 9 && t[6] == ':') t = string() << substr(t, 0, 6) << substr(t, 7);
|
||||||
|
//validate input
|
||||||
|
for(unsigned i = 0; i < 8; i++) if(!ischr(t[i])) return false;
|
||||||
|
|
||||||
type = ProActionReplay;
|
type = ProActionReplay;
|
||||||
replace(t, ":", "");
|
unsigned r = strhex((const char*)t);
|
||||||
uint32 r = strhex((const char*)t);
|
|
||||||
addr = r >> 8;
|
addr = r >> 8;
|
||||||
data = r & 0xff;
|
data = r & 0xff;
|
||||||
return true;
|
return true;
|
||||||
} else if(strlen(t) == 9 && t()[4] == '-') {
|
} else if(strlen(t) == 9 && t[4] == '-') {
|
||||||
|
//strip '-'
|
||||||
|
t = string() << substr(t, 0, 4) << substr(t, 5);
|
||||||
|
//validate input
|
||||||
|
for(unsigned i = 0; i < 8; i++) if(!ischr(t[i])) return false;
|
||||||
|
|
||||||
type = GameGenie;
|
type = GameGenie;
|
||||||
replace(t, "-", "");
|
|
||||||
strtr(t, "df4709156bc8a23e", "0123456789abcdef");
|
strtr(t, "df4709156bc8a23e", "0123456789abcdef");
|
||||||
uint32 r = strhex((const char*)t);
|
unsigned r = strhex((const char*)t);
|
||||||
//8421 8421 8421 8421 8421 8421
|
//8421 8421 8421 8421 8421 8421
|
||||||
//abcd efgh ijkl mnop qrst uvwx
|
//abcd efgh ijkl mnop qrst uvwx
|
||||||
//ijkl qrst opab cduv wxef ghmn
|
//ijkl qrst opab cduv wxef ghmn
|
||||||
@@ -42,16 +65,20 @@ bool Cheat::decode(char *str, uint32 &addr, uint8 &data, uint8 &type) {
|
|||||||
(!!(r & 0x000080) << 1) | (!!(r & 0x000040) << 0);
|
(!!(r & 0x000080) << 1) | (!!(r & 0x000040) << 0);
|
||||||
data = r >> 24;
|
data = r >> 24;
|
||||||
return true;
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Cheat::encode(char *str, uint32 addr, uint8 data, uint8 type) {
|
bool Cheat::encode(string &str, unsigned addr, uint8 data, type_t type) {
|
||||||
|
char t[16];
|
||||||
|
|
||||||
if(type == ProActionReplay) {
|
if(type == ProActionReplay) {
|
||||||
sprintf(str, "%0.6x:%0.2x", addr, data);
|
sprintf(t, "%0.6x:%0.2x", addr, data);
|
||||||
|
str = t;
|
||||||
return true;
|
return true;
|
||||||
} else if(type == GameGenie) {
|
} else if(type == GameGenie) {
|
||||||
uint32 r = addr;
|
unsigned r = addr;
|
||||||
addr = (!!(r & 0x008000) << 23) | (!!(r & 0x004000) << 22) |
|
addr = (!!(r & 0x008000) << 23) | (!!(r & 0x004000) << 22) |
|
||||||
(!!(r & 0x002000) << 21) | (!!(r & 0x001000) << 20) |
|
(!!(r & 0x002000) << 21) | (!!(r & 0x001000) << 20) |
|
||||||
(!!(r & 0x000080) << 19) | (!!(r & 0x000040) << 18) |
|
(!!(r & 0x000080) << 19) | (!!(r & 0x000040) << 18) |
|
||||||
@@ -64,11 +91,13 @@ bool Cheat::encode(char *str, uint32 addr, uint8 data, uint8 type) {
|
|||||||
(!!(r & 0x080000) << 5) | (!!(r & 0x040000) << 4) |
|
(!!(r & 0x080000) << 5) | (!!(r & 0x040000) << 4) |
|
||||||
(!!(r & 0x020000) << 3) | (!!(r & 0x010000) << 2) |
|
(!!(r & 0x020000) << 3) | (!!(r & 0x010000) << 2) |
|
||||||
(!!(r & 0x000800) << 1) | (!!(r & 0x000400) << 0);
|
(!!(r & 0x000800) << 1) | (!!(r & 0x000400) << 0);
|
||||||
sprintf(str, "%0.2x%0.2x-%0.4x", data, addr >> 16, addr & 0xffff);
|
sprintf(t, "%0.2x%0.2x-%0.4x", data, addr >> 16, addr & 0xffff);
|
||||||
strtr(str, "0123456789abcdef", "df4709156bc8a23e");
|
strtr(t, "0123456789abcdef", "df4709156bc8a23e");
|
||||||
|
str = t;
|
||||||
return true;
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
@@ -78,21 +107,21 @@ bool Cheat::encode(char *str, uint32 addr, uint8 data, uint8 type) {
|
|||||||
* clear() disable specified address, mirror accordingly
|
* clear() disable specified address, mirror accordingly
|
||||||
*****/
|
*****/
|
||||||
|
|
||||||
uint Cheat::mirror_address(uint addr) {
|
unsigned Cheat::mirror_address(unsigned addr) const {
|
||||||
if((addr & 0x40e000) != 0x0000) return addr;
|
if((addr & 0x40e000) != 0x0000) return addr;
|
||||||
//8k WRAM mirror
|
//8k WRAM mirror
|
||||||
//$[00-3f|80-bf]:[0000-1fff] -> $7e:[0000-1fff]
|
//$[00-3f|80-bf]:[0000-1fff] -> $7e:[0000-1fff]
|
||||||
return (0x7e0000 + (addr & 0x1fff));
|
return (0x7e0000 + (addr & 0x1fff));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cheat::set(uint32 addr) {
|
void Cheat::set(unsigned addr) {
|
||||||
addr = mirror_address(addr);
|
addr = mirror_address(addr);
|
||||||
|
|
||||||
mask[addr >> 3] |= 1 << (addr & 7);
|
mask[addr >> 3] |= 1 << (addr & 7);
|
||||||
if((addr & 0xffe000) == 0x7e0000) {
|
if((addr & 0xffe000) == 0x7e0000) {
|
||||||
//mirror $7e:[0000-1fff] to $[00-3f|80-bf]:[0000-1fff]
|
//mirror $7e:[0000-1fff] to $[00-3f|80-bf]:[0000-1fff]
|
||||||
uint mirror;
|
unsigned mirror;
|
||||||
for(int x = 0; x <= 0x3f; x++) {
|
for(unsigned x = 0; x <= 0x3f; x++) {
|
||||||
mirror = ((0x00 + x) << 16) + (addr & 0x1fff);
|
mirror = ((0x00 + x) << 16) + (addr & 0x1fff);
|
||||||
mask[mirror >> 3] |= 1 << (mirror & 7);
|
mask[mirror >> 3] |= 1 << (mirror & 7);
|
||||||
mirror = ((0x80 + x) << 16) + (addr & 0x1fff);
|
mirror = ((0x80 + x) << 16) + (addr & 0x1fff);
|
||||||
@@ -101,20 +130,20 @@ void Cheat::set(uint32 addr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cheat::clear(uint32 addr) {
|
void Cheat::clear(unsigned addr) {
|
||||||
addr = mirror_address(addr);
|
addr = mirror_address(addr);
|
||||||
|
|
||||||
//is there more than one cheat code using the same address
|
//if there is more than one cheat code using the same address,
|
||||||
//(and likely a different override value) that is enabled?
|
//(eg with a different override value) then do not clear code
|
||||||
//if so, do not clear code lookup table entry for this address.
|
//lookup table entry.
|
||||||
uint8 r;
|
uint8 r;
|
||||||
if(read(addr, r) == true)return;
|
if(read(addr, r) == true) return;
|
||||||
|
|
||||||
mask[addr >> 3] &= ~(1 << (addr & 7));
|
mask[addr >> 3] &= ~(1 << (addr & 7));
|
||||||
if((addr & 0xffe000) == 0x7e0000) {
|
if((addr & 0xffe000) == 0x7e0000) {
|
||||||
//mirror $7e:[0000-1fff] to $[00-3f|80-bf]:[0000-1fff]
|
//mirror $7e:[0000-1fff] to $[00-3f|80-bf]:[0000-1fff]
|
||||||
uint mirror;
|
unsigned mirror;
|
||||||
for(int x = 0; x <= 0x3f; x++) {
|
for(unsigned x = 0; x <= 0x3f; x++) {
|
||||||
mirror = ((0x00 + x) << 16) + (addr & 0x1fff);
|
mirror = ((0x00 + x) << 16) + (addr & 0x1fff);
|
||||||
mask[mirror >> 3] &= ~(1 << (mirror & 7));
|
mask[mirror >> 3] &= ~(1 << (mirror & 7));
|
||||||
mirror = ((0x80 + x) << 16) + (addr & 0x1fff);
|
mirror = ((0x80 + x) << 16) + (addr & 0x1fff);
|
||||||
@@ -130,12 +159,12 @@ void Cheat::clear(uint32 addr) {
|
|||||||
* when true, cheat code substitution value is stored in data.
|
* when true, cheat code substitution value is stored in data.
|
||||||
*****/
|
*****/
|
||||||
|
|
||||||
bool Cheat::read(uint32 addr, uint8 &data) {
|
bool Cheat::read(unsigned addr, uint8 &data) const {
|
||||||
addr = mirror_address(addr);
|
addr = mirror_address(addr);
|
||||||
for(int i = 0; i < cheat_count; i++) {
|
for(unsigned i = 0; i < code.size(); i++) {
|
||||||
if(enabled(i) == false) continue;
|
if(enabled(i) == false) continue;
|
||||||
if(addr == mirror_address(index[i].addr)) {
|
if(addr == mirror_address(code[i].addr)) {
|
||||||
data = index[i].data;
|
data = code[i].data;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,96 +179,74 @@ bool Cheat::read(uint32 addr, uint8 &data) {
|
|||||||
*****/
|
*****/
|
||||||
|
|
||||||
void Cheat::update_cheat_status() {
|
void Cheat::update_cheat_status() {
|
||||||
for(unsigned i = 0; i < cheat_count; i++) {
|
for(unsigned i = 0; i < code.size(); i++) {
|
||||||
if(index[i].enabled) {
|
if(code[i].enabled) {
|
||||||
cheat_enabled = true;
|
cheat_system_enabled = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cheat_enabled = false;
|
cheat_system_enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
* cheat list manipulation routines
|
* cheat list manipulation routines
|
||||||
*****/
|
*****/
|
||||||
|
|
||||||
bool Cheat::add(bool enable, char *code, char *desc) {
|
bool Cheat::add(bool enable, const char *code_, const char *desc_) {
|
||||||
if(cheat_count >= CheatLimit) return false;
|
unsigned addr;
|
||||||
|
uint8 data;
|
||||||
|
type_t type;
|
||||||
|
if(decode(code_, addr, data, type) == false) return false;
|
||||||
|
|
||||||
uint32 addr, len;
|
unsigned n = code.size();
|
||||||
uint8 data, type;
|
code[n].enabled = enable;
|
||||||
if(decode(code, addr, data, type) == false) return false;
|
code[n].addr = addr;
|
||||||
|
code[n].data = data;
|
||||||
index[cheat_count].enabled = enable;
|
code[n].code = code_;
|
||||||
index[cheat_count].addr = addr;
|
code[n].desc = desc_;
|
||||||
index[cheat_count].data = data;
|
|
||||||
len = strlen(code);
|
|
||||||
len = len > 16 ? 16 : len;
|
|
||||||
memcpy(index[cheat_count].code, code, len);
|
|
||||||
index[cheat_count].code[len] = 0;
|
|
||||||
len = strlen(desc);
|
|
||||||
len = len > 128 ? 128 : len;
|
|
||||||
memcpy(index[cheat_count].desc, desc, len);
|
|
||||||
index[cheat_count].desc[len] = 0;
|
|
||||||
cheat_count++;
|
|
||||||
(enable) ? set(addr) : clear(addr);
|
(enable) ? set(addr) : clear(addr);
|
||||||
|
|
||||||
update_cheat_status();
|
update_cheat_status();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Cheat::edit(uint32 n, bool enable, char *code, char *desc) {
|
bool Cheat::edit(unsigned n, bool enable, const char *code_, const char *desc_) {
|
||||||
if(n >= cheat_count) return false;
|
unsigned addr;
|
||||||
|
uint8 data;
|
||||||
uint32 addr, len;
|
type_t type;
|
||||||
uint8 data, type;
|
if(decode(code_, addr, data, type) == false) return false;
|
||||||
if(decode(code, addr, data, type) == false) return false;
|
|
||||||
|
|
||||||
//disable current code and clear from code lookup table
|
//disable current code and clear from code lookup table
|
||||||
index[n].enabled = false;
|
code[n].enabled = false;
|
||||||
clear(index[n].addr);
|
clear(code[n].addr);
|
||||||
|
|
||||||
//update code and enable in code lookup table
|
//update code and enable in code lookup table
|
||||||
index[n].enabled = enable;
|
code[n].enabled = enable;
|
||||||
index[n].addr = addr;
|
code[n].addr = addr;
|
||||||
index[n].data = data;
|
code[n].data = data;
|
||||||
len = strlen(code);
|
code[n].code = code_;
|
||||||
len = len > 16 ? 16 : len;
|
code[n].desc = desc_;
|
||||||
memcpy(index[n].code, code, len);
|
|
||||||
index[n].code[len] = 0;
|
|
||||||
len = strlen(desc);
|
|
||||||
len = len > 128 ? 128 : len;
|
|
||||||
memcpy(index[n].desc, desc, len);
|
|
||||||
index[n].desc[len] = 0;
|
|
||||||
set(addr);
|
set(addr);
|
||||||
|
|
||||||
update_cheat_status();
|
update_cheat_status();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Cheat::remove(uint32 n) {
|
bool Cheat::remove(unsigned n) {
|
||||||
if(n >= cheat_count) return false;
|
unsigned size = code.size();
|
||||||
|
if(n >= size) return false; //also verifies size cannot be < 1
|
||||||
|
|
||||||
for(unsigned i = n; i < cheat_count; i++) {
|
for(unsigned i = n; i < size - 1; i++) code[i] = code[i + 1];
|
||||||
index[i].enabled = index[i + 1].enabled;
|
code.resize(size - 1);
|
||||||
index[i].addr = index[i + 1].addr;
|
|
||||||
index[i].data = index[i + 1].data;
|
|
||||||
strcpy(index[i].desc, index[i + 1].desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
cheat_count--;
|
|
||||||
|
|
||||||
update_cheat_status();
|
update_cheat_status();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Cheat::get(uint32 n, bool &enable, uint32 &addr, uint8 &data, char *code, char *desc) {
|
bool Cheat::get(unsigned n, cheat_t &cheat) const {
|
||||||
if(n >= cheat_count) return false;
|
if(n >= code.size()) return false;
|
||||||
enable = index[n].enabled;
|
|
||||||
addr = index[n].addr;
|
cheat = code[n];
|
||||||
data = index[n].data;
|
|
||||||
strcpy(code, index[n].code);
|
|
||||||
strcpy(desc, index[n].desc);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,22 +254,23 @@ bool Cheat::get(uint32 n, bool &enable, uint32 &addr, uint8 &data, char *code, c
|
|||||||
* code status modifier routines
|
* code status modifier routines
|
||||||
*****/
|
*****/
|
||||||
|
|
||||||
bool Cheat::enabled(uint32 n) {
|
bool Cheat::enabled(unsigned n) const {
|
||||||
if(n >= cheat_count) return false;
|
return (n < code.size()) ? code[n].enabled : false;
|
||||||
return index[n].enabled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cheat::enable(uint32 n) {
|
void Cheat::enable(unsigned n) {
|
||||||
if(n >= cheat_count) return;
|
if(n >= code.size()) return;
|
||||||
index[n].enabled = true;
|
|
||||||
set(index[n].addr);
|
code[n].enabled = true;
|
||||||
|
set(code[n].addr);
|
||||||
update_cheat_status();
|
update_cheat_status();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cheat::disable(uint32 n) {
|
void Cheat::disable(unsigned n) {
|
||||||
if(n >= cheat_count) return;
|
if(n >= code.size()) return;
|
||||||
index[n].enabled = false;
|
|
||||||
clear(index[n].addr);
|
code[n].enabled = false;
|
||||||
|
clear(code[n].addr);
|
||||||
update_cheat_status();
|
update_cheat_status();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,40 +296,39 @@ bool Cheat::load(const char *fn) {
|
|||||||
split(part, ",", line[i]);
|
split(part, ",", line[i]);
|
||||||
if(::count(part) != 3) continue;
|
if(::count(part) != 3) continue;
|
||||||
trim(part[2], "\"");
|
trim(part[2], "\"");
|
||||||
add(part[1] == "enabled", part[0](), part[2]());
|
add(part[1] == "enabled", part[0], part[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Cheat::save(const char *fn) {
|
bool Cheat::save(const char *fn) const {
|
||||||
FILE *fp = fopen(fn, "wb");
|
file fp;
|
||||||
if(!fp) return false;
|
if(!fp.open(fn, file::mode_write)) return false;
|
||||||
for(unsigned i = 0; i < cheat_count; i++) {
|
for(unsigned i = 0; i < code.size(); i++) {
|
||||||
fprintf(fp, "%9s = %8s, \"%s\"\r\n",
|
fp.print(string()
|
||||||
index[i].code,
|
<< code[i].code << " = "
|
||||||
index[i].enabled ? "enabled" : "disabled",
|
<< (code[i].enabled ? "enabled" : "disabled") << ", "
|
||||||
index[i].desc);
|
<< "\"" << code[i].desc << "\""
|
||||||
|
<< "\r\n");
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fp.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****
|
void Cheat::sort() {
|
||||||
* initialization routines
|
if(code.size() <= 1) return; //nothing to sort?
|
||||||
*****/
|
cheat_t *buffer = new cheat_t[code.size()];
|
||||||
|
for(unsigned i = 0; i < code.size(); i++) buffer[i] = code[i];
|
||||||
|
nall::sort(buffer, code.size());
|
||||||
|
for(unsigned i = 0; i < code.size(); i++) code[i] = buffer[i];
|
||||||
|
delete[] buffer;
|
||||||
|
}
|
||||||
|
|
||||||
void Cheat::clear() {
|
void Cheat::clear() {
|
||||||
cheat_enabled = false;
|
cheat_system_enabled = false;
|
||||||
cheat_count = 0;
|
|
||||||
memset(mask, 0, 0x200000);
|
memset(mask, 0, 0x200000);
|
||||||
for(unsigned i = 0; i <= CheatLimit; i++) {
|
code.reset();
|
||||||
index[i].enabled = false;
|
|
||||||
index[i].addr = 0x000000;
|
|
||||||
index[i].data = 0x00;
|
|
||||||
strcpy(index[i].code, "");
|
|
||||||
strcpy(index[i].desc, "");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Cheat::Cheat() {
|
Cheat::Cheat() {
|
||||||
|
@@ -1,51 +1,55 @@
|
|||||||
class Cheat {
|
class Cheat {
|
||||||
public:
|
public:
|
||||||
enum { CheatLimit = 1024 };
|
enum type_t {
|
||||||
|
|
||||||
enum Type {
|
|
||||||
ProActionReplay,
|
ProActionReplay,
|
||||||
GameGenie,
|
GameGenie,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CheatIndex {
|
struct cheat_t {
|
||||||
bool enabled;
|
bool enabled;
|
||||||
uint32 addr;
|
unsigned addr;
|
||||||
uint8 data;
|
uint8 data;
|
||||||
char code[ 16 + 1];
|
string code;
|
||||||
char desc[128 + 1];
|
string desc;
|
||||||
} index[CheatLimit + 1];
|
|
||||||
|
|
||||||
bool cheat_enabled;
|
cheat_t& operator=(const cheat_t&);
|
||||||
uint32 cheat_count;
|
bool operator<(const cheat_t&);
|
||||||
uint8 mask[0x200000];
|
};
|
||||||
|
|
||||||
inline bool enabled() { return cheat_enabled; }
|
static bool decode(const char *str, unsigned &addr, uint8 &data, type_t &type);
|
||||||
inline uint count() { return cheat_count; }
|
static bool encode(string &str, unsigned addr, uint8 data, type_t type);
|
||||||
inline bool exists(uint32 addr) { return bool(mask[addr >> 3] & 1 << (addr & 7)); }
|
|
||||||
|
|
||||||
bool decode(char *str, uint32 &addr, uint8 &data, uint8 &type);
|
inline bool enabled() const { return cheat_system_enabled; }
|
||||||
bool encode(char *str, uint32 addr, uint8 data, uint8 type);
|
inline unsigned count() const { return code.size(); }
|
||||||
|
inline bool exists(unsigned addr) const { return bool(mask[addr >> 3] & 1 << (addr & 7)); }
|
||||||
|
|
||||||
bool read(uint32 addr, uint8 &data);
|
bool read(unsigned addr, uint8 &data) const;
|
||||||
|
|
||||||
|
bool add(bool enable, const char *code, const char *desc);
|
||||||
|
bool edit(unsigned n, bool enable, const char *code, const char *desc);
|
||||||
|
bool get(unsigned n, cheat_t &cheat) const;
|
||||||
|
bool remove(unsigned n);
|
||||||
|
bool enabled(unsigned n) const;
|
||||||
|
void enable(unsigned n);
|
||||||
|
void disable(unsigned n);
|
||||||
|
|
||||||
void update_cheat_status();
|
|
||||||
bool add(bool enable, char *code, char *desc);
|
|
||||||
bool edit(uint32 n, bool enable, char *code, char *desc);
|
|
||||||
bool get(uint32 n, bool &enable, uint32 &addr, uint8 &data, char *code, char *desc);
|
|
||||||
bool remove(uint32 n);
|
|
||||||
bool enabled(uint32 n);
|
|
||||||
void enable(uint32 n);
|
|
||||||
void disable(uint32 n);
|
|
||||||
bool load(const char *fn);
|
bool load(const char *fn);
|
||||||
bool save(const char *fn);
|
bool save(const char *fn) const;
|
||||||
|
|
||||||
|
void sort();
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
Cheat();
|
Cheat();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint mirror_address(uint addr);
|
bool cheat_system_enabled;
|
||||||
void set(uint32 addr);
|
uint8 mask[0x200000];
|
||||||
void clear(uint32 addr);
|
vector<cheat_t> code;
|
||||||
|
|
||||||
|
void update_cheat_status();
|
||||||
|
unsigned mirror_address(unsigned addr) const;
|
||||||
|
void set(unsigned addr);
|
||||||
|
void clear(unsigned addr);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Cheat cheat;
|
extern Cheat cheat;
|
||||||
|
@@ -8,80 +8,61 @@ void OBC1::power() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OBC1::reset() {
|
void OBC1::reset() {
|
||||||
for(uint i = 0x0000; i <= 0x1fff; i++) ram_write(i, 0xff);
|
for(unsigned i = 0x0000; i <= 0x1fff; i++) ram_write(i, 0xff);
|
||||||
|
|
||||||
status.baseptr = (ram_read(0x1ff5) & 1) ? 0x1800 : 0x1c00;
|
status.baseptr = (ram_read(0x1ff5) & 1) ? 0x1800 : 0x1c00;
|
||||||
status.address = (ram_read(0x1ff6) & 0x7f);
|
status.address = (ram_read(0x1ff6) & 0x7f);
|
||||||
status.shift = (ram_read(0x1ff6) & 3) << 1;
|
status.shift = (ram_read(0x1ff6) & 3) << 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 OBC1::read(uint addr) {
|
uint8 OBC1::read(unsigned addr) {
|
||||||
addr &= 0x1fff;
|
addr &= 0x1fff;
|
||||||
if((addr & 0x1ff8) != 0x1ff0) return ram_read(addr);
|
if((addr & 0x1ff8) != 0x1ff0) return ram_read(addr);
|
||||||
|
|
||||||
switch(addr) {
|
switch(addr) { default: //never used, avoids compiler warning
|
||||||
case 0x1ff0:
|
case 0x1ff0: return ram_read(status.baseptr + (status.address << 2) + 0);
|
||||||
return ram_read(status.baseptr + (status.address << 2) + 0);
|
case 0x1ff1: return ram_read(status.baseptr + (status.address << 2) + 1);
|
||||||
case 0x1ff1:
|
case 0x1ff2: return ram_read(status.baseptr + (status.address << 2) + 2);
|
||||||
return ram_read(status.baseptr + (status.address << 2) + 1);
|
case 0x1ff3: return ram_read(status.baseptr + (status.address << 2) + 3);
|
||||||
case 0x1ff2:
|
case 0x1ff4: return ram_read(status.baseptr + (status.address >> 2) + 0x200);
|
||||||
return ram_read(status.baseptr + (status.address << 2) + 2);
|
case 0x1ff5: case 0x1ff6: case 0x1ff7: return ram_read(addr);
|
||||||
case 0x1ff3:
|
|
||||||
return ram_read(status.baseptr + (status.address << 2) + 3);
|
|
||||||
case 0x1ff4:
|
|
||||||
return ram_read(status.baseptr + (status.address >> 2) + 0x200);
|
|
||||||
case 0x1ff5:
|
|
||||||
case 0x1ff6:
|
|
||||||
case 0x1ff7:
|
|
||||||
return ram_read(addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0x00; //never used, avoids compiler warning
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OBC1::write(uint addr, uint8 data) {
|
void OBC1::write(unsigned addr, uint8 data) {
|
||||||
addr &= 0x1fff;
|
addr &= 0x1fff;
|
||||||
if((addr & 0x1ff8) != 0x1ff0) return ram_write(addr, data);
|
if((addr & 0x1ff8) != 0x1ff0) return ram_write(addr, data);
|
||||||
|
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 0x1ff0:
|
case 0x1ff0: ram_write(status.baseptr + (status.address << 2) + 0, data); break;
|
||||||
ram_write(status.baseptr + (status.address << 2) + 0, data);
|
case 0x1ff1: ram_write(status.baseptr + (status.address << 2) + 1, data); break;
|
||||||
break;
|
case 0x1ff2: ram_write(status.baseptr + (status.address << 2) + 2, data); break;
|
||||||
case 0x1ff1:
|
case 0x1ff3: ram_write(status.baseptr + (status.address << 2) + 3, data); break;
|
||||||
ram_write(status.baseptr + (status.address << 2) + 1, data);
|
case 0x1ff4: {
|
||||||
break;
|
uint8 temp = ram_read(status.baseptr + (status.address >> 2) + 0x200);
|
||||||
case 0x1ff2:
|
temp = (temp & ~(3 << status.shift)) | ((data & 3) << status.shift);
|
||||||
ram_write(status.baseptr + (status.address << 2) + 2, data);
|
ram_write(status.baseptr + (status.address >> 2) + 0x200, temp);
|
||||||
break;
|
} break;
|
||||||
case 0x1ff3:
|
case 0x1ff5: {
|
||||||
ram_write(status.baseptr + (status.address << 2) + 3, data);
|
status.baseptr = (data & 1) ? 0x1800 : 0x1c00;
|
||||||
break;
|
ram_write(addr, data);
|
||||||
case 0x1ff4: {
|
} break;
|
||||||
uint8 temp;
|
case 0x1ff6: {
|
||||||
temp = ram_read(status.baseptr + (status.address >> 2) + 0x200);
|
status.address = (data & 0x7f);
|
||||||
temp = (temp & ~(3 << status.shift)) | ((data & 3) << status.shift);
|
status.shift = (data & 3) << 1;
|
||||||
ram_write(status.baseptr + (status.address >> 2) + 0x200, temp);
|
ram_write(addr, data);
|
||||||
} break;
|
} break;
|
||||||
case 0x1ff5:
|
case 0x1ff7: {
|
||||||
status.baseptr = (data & 1) ? 0x1800 : 0x1c00;
|
ram_write(addr, data);
|
||||||
ram_write(addr, data);
|
} break;
|
||||||
break;
|
|
||||||
case 0x1ff6:
|
|
||||||
status.address = (data & 0x7f);
|
|
||||||
status.shift = (data & 3) << 1;
|
|
||||||
ram_write(addr, data);
|
|
||||||
break;
|
|
||||||
case 0x1ff7:
|
|
||||||
ram_write(addr, data);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 OBC1::ram_read(uint addr) {
|
uint8 OBC1::ram_read(unsigned addr) {
|
||||||
return memory::cartram.read(addr & 0x1fff);
|
return memory::cartram.read(addr & 0x1fff);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OBC1::ram_write(uint addr, uint8 data) {
|
void OBC1::ram_write(unsigned addr, uint8 data) {
|
||||||
memory::cartram.write(addr & 0x1fff, data);
|
memory::cartram.write(addr & 0x1fff, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,15 +5,15 @@ public:
|
|||||||
void power();
|
void power();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
uint8 read(uint addr);
|
uint8 read(unsigned addr);
|
||||||
void write(uint addr, uint8 data);
|
void write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
OBC1();
|
OBC1();
|
||||||
~OBC1();
|
~OBC1();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8 ram_read(uint addr);
|
uint8 ram_read(unsigned addr);
|
||||||
void ram_write(uint addr, uint8 data);
|
void ram_write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint16 address;
|
uint16 address;
|
||||||
|
@@ -139,7 +139,7 @@ unsigned SRTC::weekday(unsigned year, unsigned month, unsigned day) {
|
|||||||
return (sum + 1) % 7; //1900-01-01 was a Monday
|
return (sum + 1) % 7; //1900-01-01 was a Monday
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SRTC::mmio_read(uint addr) {
|
uint8 SRTC::mmio_read(unsigned addr) {
|
||||||
addr &= 0xffff;
|
addr &= 0xffff;
|
||||||
|
|
||||||
if(addr == 0x2800) {
|
if(addr == 0x2800) {
|
||||||
@@ -160,7 +160,7 @@ uint8 SRTC::mmio_read(uint addr) {
|
|||||||
return cpu.regs.mdr;
|
return cpu.regs.mdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SRTC::mmio_write(uint addr, uint8 data) {
|
void SRTC::mmio_write(unsigned addr, uint8 data) {
|
||||||
addr &= 0xffff;
|
addr &= 0xffff;
|
||||||
|
|
||||||
if(addr == 0x2801) {
|
if(addr == 0x2801) {
|
||||||
|
@@ -8,8 +8,8 @@ public:
|
|||||||
void power();
|
void power();
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
uint8 mmio_read (uint addr);
|
uint8 mmio_read (unsigned addr);
|
||||||
void mmio_write(uint addr, uint8 data);
|
void mmio_write(unsigned addr, uint8 data);
|
||||||
|
|
||||||
SRTC();
|
SRTC();
|
||||||
|
|
||||||
|
@@ -62,6 +62,17 @@ integral_setting SNES::controller_port1(config(), "snes.controller_port1",
|
|||||||
"Controller attached to SNES port 1", integral_setting::decimal, ::SNES::Input::DeviceJoypad);
|
"Controller attached to SNES port 1", integral_setting::decimal, ::SNES::Input::DeviceJoypad);
|
||||||
integral_setting SNES::controller_port2(config(), "snes.controller_port2",
|
integral_setting SNES::controller_port2(config(), "snes.controller_port2",
|
||||||
"Controller attached to SNES port 2", integral_setting::decimal, ::SNES::Input::DeviceJoypad);
|
"Controller attached to SNES port 2", integral_setting::decimal, ::SNES::Input::DeviceJoypad);
|
||||||
|
integral_setting SNES::expansion_port(config(), "snes.expansion_port",
|
||||||
|
"Device attached to SNES expansion port\n"
|
||||||
|
"0 = None\n"
|
||||||
|
"1 = Satellaview BS-X\n"
|
||||||
|
"", integral_setting::decimal, ::SNES::ExpansionBSX);
|
||||||
|
integral_setting SNES::region(config(), "snes.region",
|
||||||
|
"SNES regional model\n"
|
||||||
|
"0 = Auto-detect based on cartridge\n"
|
||||||
|
"1 = NTSC\n"
|
||||||
|
"2 = PAL\n"
|
||||||
|
"", integral_setting::decimal, ::SNES::Autodetect);
|
||||||
|
|
||||||
integral_setting CPU::ntsc_clock_rate(config(), "cpu.ntsc_clock_rate",
|
integral_setting CPU::ntsc_clock_rate(config(), "cpu.ntsc_clock_rate",
|
||||||
"NTSC S-CPU clock rate (in hz)", integral_setting::decimal, 21477272);
|
"NTSC S-CPU clock rate (in hz)", integral_setting::decimal, 21477272);
|
||||||
@@ -82,9 +93,9 @@ integral_setting CPU::wram_init_value(config(), "cpu.wram_init_value",
|
|||||||
integral_setting::hex, 0x55);
|
integral_setting::hex, 0x55);
|
||||||
|
|
||||||
integral_setting SMP::ntsc_clock_rate(config(), "smp.ntsc_clock_rate",
|
integral_setting SMP::ntsc_clock_rate(config(), "smp.ntsc_clock_rate",
|
||||||
"NTSC S-SMP clock rate (in hz)", integral_setting::decimal, 32040 * 768);
|
"NTSC S-SMP clock rate (in hz)", integral_setting::decimal, 32041 * 768);
|
||||||
integral_setting SMP::pal_clock_rate(config(), "smp.pal_clock_rate",
|
integral_setting SMP::pal_clock_rate(config(), "smp.pal_clock_rate",
|
||||||
"PAL S-SMP clock rate (in hz)", integral_setting::decimal, 32040 * 768);
|
"PAL S-SMP clock rate (in hz)", integral_setting::decimal, 32041 * 768);
|
||||||
|
|
||||||
integral_setting PPU::Hack::render_scanline_position(config(), "ppu.hack.render_scanline_position",
|
integral_setting PPU::Hack::render_scanline_position(config(), "ppu.hack.render_scanline_position",
|
||||||
"Approximate HCLOCK position to render at for scanline-based renderers",
|
"Approximate HCLOCK position to render at for scanline-based renderers",
|
||||||
|
@@ -17,6 +17,8 @@ extern struct Path {
|
|||||||
extern struct SNES {
|
extern struct SNES {
|
||||||
static integral_setting controller_port1;
|
static integral_setting controller_port1;
|
||||||
static integral_setting controller_port2;
|
static integral_setting controller_port2;
|
||||||
|
static integral_setting expansion_port;
|
||||||
|
static integral_setting region;
|
||||||
} snes;
|
} snes;
|
||||||
|
|
||||||
extern struct CPU {
|
extern struct CPU {
|
||||||
|
@@ -3,9 +3,9 @@
|
|||||||
#include "irq.cpp"
|
#include "irq.cpp"
|
||||||
#include "joypad.cpp"
|
#include "joypad.cpp"
|
||||||
|
|
||||||
uint16 sCPU::vcounter() { return status.vcounter; }
|
unsigned sCPU::dma_counter() {
|
||||||
uint16 sCPU::hcounter() { return status.hcounter; }
|
return (status.dma_counter + status.hcounter) & 7;
|
||||||
uint sCPU::dma_counter() { return (status.dma_counter + status.hcounter) & 7; }
|
}
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
* One PPU dot = 4 CPU clocks
|
* One PPU dot = 4 CPU clocks
|
||||||
@@ -28,7 +28,7 @@ uint16 sCPU::hdot() {
|
|||||||
return (status.hcounter - ((status.hcounter > 1292) << 1) - ((status.hcounter > 1310) << 1)) >> 2;
|
return (status.hcounter - ((status.hcounter > 1292) << 1) - ((status.hcounter > 1310) << 1)) >> 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sCPU::add_clocks(uint clocks) {
|
void sCPU::add_clocks(unsigned clocks) {
|
||||||
if(status.dram_refreshed == false) {
|
if(status.dram_refreshed == false) {
|
||||||
if(status.hcounter + clocks >= status.dram_refresh_position) {
|
if(status.hcounter + clocks >= status.dram_refresh_position) {
|
||||||
status.dram_refreshed = true;
|
status.dram_refreshed = true;
|
||||||
@@ -45,6 +45,7 @@ void sCPU::add_clocks(uint clocks) {
|
|||||||
status.hcounter += 2;
|
status.hcounter += 2;
|
||||||
if(status.hcounter >= status.line_clocks) scanline();
|
if(status.hcounter >= status.line_clocks) scanline();
|
||||||
poll_interrupts();
|
poll_interrupts();
|
||||||
|
snes.input.tick();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +151,7 @@ void sCPU::cycle_edge() {
|
|||||||
if(hdma_enabled_channels()) {
|
if(hdma_enabled_channels()) {
|
||||||
dma_add_clocks(8 - dma_counter()); //DMA sync
|
dma_add_clocks(8 - dma_counter()); //DMA sync
|
||||||
status.hdma_mode == 0 ? hdma_init() : hdma_run();
|
status.hdma_mode == 0 ? hdma_init() : hdma_run();
|
||||||
status.dma_state = DMA_CPUsync;
|
if(!dma_enabled_channels()) status.dma_state = DMA_CPUsync;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
uint16 vcounter();
|
alwaysinline uint16 vcounter() { return status.vcounter; }
|
||||||
uint16 hcounter();
|
alwaysinline uint16 hcounter() { return status.hcounter; }
|
||||||
uint16 hdot();
|
uint16 hdot();
|
||||||
uint dma_counter();
|
unsigned dma_counter();
|
||||||
|
|
||||||
void add_clocks(uint clocks);
|
void add_clocks(unsigned clocks);
|
||||||
void scanline();
|
void scanline();
|
||||||
void frame();
|
void frame();
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
void sDSP::brr_decode(voice_t &v) {
|
void sDSP::brr_decode(voice_t &v) {
|
||||||
//state.t_brr_byte = ram[v.brr_addr + v.brr_offset] cached from previous clock cycle
|
//state.t_brr_byte = ram[v.brr_addr + v.brr_offset] cached from previous clock cycle
|
||||||
int nybbles = (state.t_brr_byte << 8) + memory::apuram.read(uint16(v.brr_addr + v.brr_offset + 1));
|
int nybbles = (state.t_brr_byte << 8) + memory::apuram[(uint16)(v.brr_addr + v.brr_offset + 1)];
|
||||||
|
|
||||||
const int filter = (state.t_brr_header >> 2) & 3;
|
const int filter = (state.t_brr_header >> 2) & 3;
|
||||||
const int scale = (state.t_brr_header >> 4);
|
const int scale = (state.t_brr_header >> 4);
|
||||||
|
@@ -13,8 +13,8 @@ int sDSP::echo_output(bool channel) {
|
|||||||
|
|
||||||
void sDSP::echo_read(bool channel) {
|
void sDSP::echo_read(bool channel) {
|
||||||
unsigned addr = state.t_echo_ptr + channel * 2;
|
unsigned addr = state.t_echo_ptr + channel * 2;
|
||||||
uint8 lo = memory::apuram.read(uint16(addr + 0));
|
uint8 lo = memory::apuram[(uint16)(addr + 0)];
|
||||||
uint8 hi = memory::apuram.read(uint16(addr + 1));
|
uint8 hi = memory::apuram[(uint16)(addr + 1)];
|
||||||
int s = (int16)((hi << 8) + lo);
|
int s = (int16)((hi << 8) + lo);
|
||||||
state.echo_hist[channel].write(state.echo_hist_pos, s >> 1);
|
state.echo_hist[channel].write(state.echo_hist_pos, s >> 1);
|
||||||
}
|
}
|
||||||
@@ -23,8 +23,8 @@ void sDSP::echo_write(bool channel) {
|
|||||||
if(!(state.t_echo_disabled & 0x20)) {
|
if(!(state.t_echo_disabled & 0x20)) {
|
||||||
unsigned addr = state.t_echo_ptr + channel * 2;
|
unsigned addr = state.t_echo_ptr + channel * 2;
|
||||||
int s = state.t_echo_out[channel];
|
int s = state.t_echo_out[channel];
|
||||||
memory::apuram.write(uint16(addr + 0), (uint8)(s >> 0));
|
memory::apuram[(uint16)(addr + 0)] = s;
|
||||||
memory::apuram.write(uint16(addr + 1), (uint8)(s >> 8));
|
memory::apuram[(uint16)(addr + 1)] = s >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.t_echo_out[channel] = 0;
|
state.t_echo_out[channel] = 0;
|
||||||
|
@@ -24,8 +24,8 @@ void sDSP::voice_2(voice_t &v) {
|
|||||||
//read sample pointer (ignored if not needed)
|
//read sample pointer (ignored if not needed)
|
||||||
uint16 addr = state.t_dir_addr;
|
uint16 addr = state.t_dir_addr;
|
||||||
if(!v.kon_delay) addr += 2;
|
if(!v.kon_delay) addr += 2;
|
||||||
uint8 lo = memory::apuram.read(uint16(addr + 0));
|
uint8 lo = memory::apuram[(uint16)(addr + 0)];
|
||||||
uint8 hi = memory::apuram.read(uint16(addr + 1));
|
uint8 hi = memory::apuram[(uint16)(addr + 1)];
|
||||||
state.t_brr_next_addr = ((hi << 8) + lo);
|
state.t_brr_next_addr = ((hi << 8) + lo);
|
||||||
|
|
||||||
state.t_adsr0 = VREG(adsr0);
|
state.t_adsr0 = VREG(adsr0);
|
||||||
@@ -45,8 +45,8 @@ void sDSP::voice_3a(voice_t &v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sDSP::voice_3b(voice_t &v) {
|
void sDSP::voice_3b(voice_t &v) {
|
||||||
state.t_brr_byte = memory::apuram.read(uint16(v.brr_addr + v.brr_offset));
|
state.t_brr_byte = memory::apuram[(uint16)(v.brr_addr + v.brr_offset)];
|
||||||
state.t_brr_header = memory::apuram.read(uint16(v.brr_addr));
|
state.t_brr_header = memory::apuram[(uint16)(v.brr_addr)];
|
||||||
}
|
}
|
||||||
|
|
||||||
void sDSP::voice_3c(voice_t &v) {
|
void sDSP::voice_3c(voice_t &v) {
|
||||||
|
132
src/lib/bbase.h
132
src/lib/bbase.h
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
bbase : version 0.14 ~byuu (2008-04-16)
|
bbase : version 0.17 ~byuu (2008-10-19)
|
||||||
license: public domain
|
license: public domain
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ typedef uint8_t uint8;
|
|||||||
typedef uint16_t uint16;
|
typedef uint16_t uint16;
|
||||||
typedef uint32_t uint32;
|
typedef uint32_t uint32;
|
||||||
typedef uint64_t uint64;
|
typedef uint64_t uint64;
|
||||||
typedef unsigned int uint;
|
typedef unsigned uint;
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
using std::min;
|
using std::min;
|
||||||
@@ -41,7 +41,7 @@ using std::max;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
//disable libc deprecation warnings in MSVC 2k5+
|
//disable libc deprecation warnings in MSVC 2k5+
|
||||||
#pragma warning(disable:4996)
|
#pragma warning(disable:4996)
|
||||||
|
|
||||||
#define NOMINMAX
|
#define NOMINMAX
|
||||||
@@ -52,17 +52,10 @@ using std::max;
|
|||||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
#define getcwd _getcwd
|
#define getcwd _getcwd
|
||||||
#define ftruncate _chsize
|
#define ftruncate _chsize
|
||||||
#define mkdir _mkdir
|
|
||||||
#define putenv _putenv
|
#define putenv _putenv
|
||||||
#define rmdir _rmdir
|
#define rmdir _rmdir
|
||||||
#define vsnprintf _vsnprintf
|
#define vsnprintf _vsnprintf
|
||||||
#define usleep(n) Sleep(n / 1000)
|
#define usleep(n) Sleep(n / 1000)
|
||||||
|
|
||||||
static char *realpath(const char *file_name, char *resolved_name) {
|
|
||||||
return _fullpath(resolved_name, file_name, PATH_MAX);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define mkdir(path) (mkdir)(path, 0755);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
@@ -83,123 +76,4 @@ using std::max;
|
|||||||
#define alwaysinline inline
|
#define alwaysinline inline
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*****
|
|
||||||
* OS localization
|
|
||||||
*****/
|
|
||||||
|
|
||||||
//userpath(output) retrieves path to user's home folder
|
|
||||||
//output must be at least as large as PATH_MAX
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
|
||||||
static char *userpath(char *output) {
|
|
||||||
strcpy(output, "."); //failsafe
|
|
||||||
SHGetFolderPath(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, output);
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static char *userpath(char *output) {
|
|
||||||
strcpy(output, "."); //failsafe
|
|
||||||
struct passwd *userinfo = getpwuid(getuid());
|
|
||||||
if(userinfo) { strcpy(output, userinfo->pw_dir); }
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<int min, int max, typename T> inline T minmax(const T x) {
|
|
||||||
return (x < (T)min) ? (T)min : (x > (T)max) ? (T)max : x;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****
|
|
||||||
* endian wrappers
|
|
||||||
*****/
|
|
||||||
|
|
||||||
#ifndef ARCH_MSB
|
|
||||||
//little-endian: uint8[] { 0x01, 0x02, 0x03, 0x04 } == 0x04030201
|
|
||||||
#define order_lsb2(a,b) a,b
|
|
||||||
#define order_lsb3(a,b,c) a,b,c
|
|
||||||
#define order_lsb4(a,b,c,d) a,b,c,d
|
|
||||||
#define order_lsb5(a,b,c,d,e) a,b,c,d,e
|
|
||||||
#define order_lsb6(a,b,c,d,e,f) a,b,c,d,e,f
|
|
||||||
#define order_lsb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g
|
|
||||||
#define order_lsb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h
|
|
||||||
#define order_msb2(a,b) b,a
|
|
||||||
#define order_msb3(a,b,c) c,b,a
|
|
||||||
#define order_msb4(a,b,c,d) d,c,b,a
|
|
||||||
#define order_msb5(a,b,c,d,e) e,d,c,b,a
|
|
||||||
#define order_msb6(a,b,c,d,e,f) f,e,d,c,b,a
|
|
||||||
#define order_msb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a
|
|
||||||
#define order_msb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a
|
|
||||||
#else
|
|
||||||
//big-endian: uint8[] { 0x01, 0x02, 0x03, 0x04 } == 0x01020304
|
|
||||||
#define order_lsb2(a,b) b,a
|
|
||||||
#define order_lsb3(a,b,c) c,b,a
|
|
||||||
#define order_lsb4(a,b,c,d) d,c,b,a
|
|
||||||
#define order_lsb5(a,b,c,d,e) e,d,c,b,a
|
|
||||||
#define order_lsb6(a,b,c,d,e,f) f,e,d,c,b,a
|
|
||||||
#define order_lsb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a
|
|
||||||
#define order_lsb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a
|
|
||||||
#define order_msb2(a,b) a,b
|
|
||||||
#define order_msb3(a,b,c) a,b,c
|
|
||||||
#define order_msb4(a,b,c,d) a,b,c,d
|
|
||||||
#define order_msb5(a,b,c,d,e) a,b,c,d,e
|
|
||||||
#define order_msb6(a,b,c,d,e,f) a,b,c,d,e,f
|
|
||||||
#define order_msb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g
|
|
||||||
#define order_msb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*****
|
|
||||||
* libc extensions
|
|
||||||
*****/
|
|
||||||
|
|
||||||
//pseudo-random number generator
|
|
||||||
static unsigned prng() {
|
|
||||||
static unsigned n = 0;
|
|
||||||
return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint64 fget(FILE *fp, unsigned length = 1) {
|
|
||||||
uint64 data = 0;
|
|
||||||
for(unsigned i = 0; i < length; i++) {
|
|
||||||
data |= fgetc(fp) << (i << 3);
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fput(FILE *fp, uint64 data, unsigned length = 1) {
|
|
||||||
for(unsigned i = 0; i < length; i++) {
|
|
||||||
fputc(data >> (i << 3), fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool fexists(const char *fn) {
|
|
||||||
FILE *fp = fopen(fn, "rb");
|
|
||||||
if(!fp) return false;
|
|
||||||
fclose(fp);
|
|
||||||
fp = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned fsize(FILE *fp) {
|
|
||||||
if(!fp) return 0;
|
|
||||||
unsigned pos = ftell(fp);
|
|
||||||
fseek(fp, 0, SEEK_END);
|
|
||||||
unsigned size = ftell(fp);
|
|
||||||
fseek(fp, pos, SEEK_SET);
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned fsize(const char *fn) {
|
|
||||||
FILE *fp = fopen(fn, "rb");
|
|
||||||
if(!fp) return 0;
|
|
||||||
fseek(fp, 0, SEEK_END);
|
|
||||||
unsigned size = ftell(fp);
|
|
||||||
fclose(fp);
|
|
||||||
fp = 0;
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int fresize(FILE *fp, long size) {
|
|
||||||
return ftruncate(fileno(fp), size);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //ifndef BBASE_H
|
#endif //ifndef BBASE_H
|
||||||
|
@@ -1,6 +0,0 @@
|
|||||||
mingw32-g++ -c test/test.cpp -I. -I../
|
|
||||||
mingw32-g++ -c hiro.cpp -I. -I../
|
|
||||||
mingw32-g++ -c ../nall/string.cpp -I. -I../
|
|
||||||
mingw32-g++ test.o hiro.o string.o -o test_app.exe -lkernel32 -luser32 -lgdi32 -ladvapi32 -lcomctl32 -lcomdlg32
|
|
||||||
@pause
|
|
||||||
@del *.o
|
|
@@ -1,6 +0,0 @@
|
|||||||
clear
|
|
||||||
g++ -c test/test.cpp -I. -I../
|
|
||||||
g++ -c hiro.cpp `pkg-config --cflags gtk+-2.0` -I. -I../
|
|
||||||
g++ -c ../nall/string.cpp -I. -I../
|
|
||||||
g++ test.o hiro.o string.o -o test_app `pkg-config --libs gtk+-2.0` -lXtst
|
|
||||||
rm *.o
|
|
@@ -1,8 +1,8 @@
|
|||||||
void hiro_pbutton_tick(pButton *p) {
|
void hiro_pbutton_tick(pButton *p) {
|
||||||
if(p->self.on_tick) p->self.on_tick(Event(Event::Tick, 0, &p->self));
|
if(p->self.on_tick) p->self.on_tick(event_t(event_t::Tick, 0, &p->self));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pButton::create(uint style, uint width, uint height, const char *text) {
|
void pButton::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||||
button = gtk_button_new_with_label(text ? text : "");
|
button = gtk_button_new_with_label(text ? text : "");
|
||||||
set_default_font(button);
|
set_default_font(button);
|
||||||
gtk_widget_set_size_request(button, width, height);
|
gtk_widget_set_size_request(button, width, height);
|
||||||
@@ -13,6 +13,7 @@ void pButton::create(uint style, uint width, uint height, const char *text) {
|
|||||||
void pButton::set_text(const char *text) {
|
void pButton::set_text(const char *text) {
|
||||||
if(!button) return;
|
if(!button) return;
|
||||||
gtk_button_set_label(GTK_BUTTON(button), text ? text : "");
|
gtk_button_set_label(GTK_BUTTON(button), text ? text : "");
|
||||||
|
set_default_font(button);
|
||||||
}
|
}
|
||||||
|
|
||||||
pButton::pButton(Button &self_) : pFormControl(self_), self(self_) {
|
pButton::pButton(Button &self_) : pFormControl(self_), self(self_) {
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
class pButton : public pFormControl {
|
class pButton : public pFormControl {
|
||||||
public:
|
public:
|
||||||
Button &self;
|
Button &self;
|
||||||
void create(uint style, uint width, uint height, const char *text = "");
|
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||||
void set_text(const char *text = "");
|
void set_text(const char *text = "");
|
||||||
|
|
||||||
pButton(Button&);
|
pButton(Button&);
|
@@ -1,8 +1,8 @@
|
|||||||
void hiro_pcanvas_expose(pCanvas *p) {
|
void hiro_pcanvas_expose(pCanvas *p) {
|
||||||
uint32_t *f = p->fbuffer;
|
uint32_t *f = p->fbuffer;
|
||||||
uint32_t *r = p->rbuffer;
|
uint32_t *r = p->rbuffer;
|
||||||
for(uint y = p->canvas->allocation.height; y; y--) {
|
for(unsigned y = p->canvas->allocation.height; y; y--) {
|
||||||
for(uint x = p->canvas->allocation.width; x; x--) {
|
for(unsigned x = p->canvas->allocation.width; x; x--) {
|
||||||
uint32_t p = *f++;
|
uint32_t p = *f++;
|
||||||
*r++ = ((p << 16) & 0xff0000) + (p & 0x00ff00) + ((p >> 16) & 0x0000ff);
|
*r++ = ((p << 16) & 0xff0000) + (p & 0x00ff00) + ((p >> 16) & 0x0000ff);
|
||||||
}
|
}
|
||||||
@@ -14,15 +14,32 @@ void hiro_pcanvas_expose(pCanvas *p) {
|
|||||||
GDK_RGB_DITHER_NONE, (guchar*)p->rbuffer, p->bpitch);
|
GDK_RGB_DITHER_NONE, (guchar*)p->rbuffer, p->bpitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pCanvas::create(uint style, uint width, uint height) {
|
gboolean hiro_pcanvas_button_press(GtkWidget *widget, GdkEventButton *event, pCanvas *p) {
|
||||||
|
if(p->self.on_input && event->button < mouse::buttons) {
|
||||||
|
p->self.on_input(event_t(event_t::Input, (mouse::button + event->button) + (1 << 16), &p->self));
|
||||||
|
}
|
||||||
|
return false; //do not propogate the event to other handlers
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean hiro_pcanvas_button_release(GtkWidget *widget, GdkEventButton *event, pCanvas *p) {
|
||||||
|
if(p->self.on_input && event->button < mouse::buttons) {
|
||||||
|
p->self.on_input(event_t(event_t::Input, (mouse::button + event->button) + (0 << 16), &p->self));
|
||||||
|
}
|
||||||
|
return false; //do not propogate the event to other handlers
|
||||||
|
}
|
||||||
|
|
||||||
|
void pCanvas::create(unsigned style, unsigned width, unsigned height) {
|
||||||
canvas = gtk_drawing_area_new();
|
canvas = gtk_drawing_area_new();
|
||||||
resize(width, height);
|
resize(width, height);
|
||||||
GdkColor color;
|
GdkColor color;
|
||||||
color.pixel = color.red = color.green = color.blue = 0;
|
color.pixel = color.red = color.green = color.blue = 0;
|
||||||
gtk_widget_modify_bg(canvas, GTK_STATE_NORMAL, &color);
|
gtk_widget_modify_bg(canvas, GTK_STATE_NORMAL, &color);
|
||||||
gtk_widget_set_double_buffered(canvas, false);
|
gtk_widget_set_double_buffered(canvas, false);
|
||||||
|
gtk_widget_add_events(canvas, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
|
||||||
gtk_widget_show(canvas);
|
gtk_widget_show(canvas);
|
||||||
g_signal_connect_swapped(G_OBJECT(canvas), "expose_event", G_CALLBACK(hiro_pcanvas_expose), (gpointer)this);
|
g_signal_connect_swapped(G_OBJECT(canvas), "expose_event", G_CALLBACK(hiro_pcanvas_expose), (gpointer)this);
|
||||||
|
g_signal_connect(G_OBJECT(canvas), "button_press_event", G_CALLBACK(hiro_pcanvas_button_press), (gpointer)this);
|
||||||
|
g_signal_connect(G_OBJECT(canvas), "button_release_event", G_CALLBACK(hiro_pcanvas_button_release), (gpointer)this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pCanvas::redraw() {
|
void pCanvas::redraw() {
|
||||||
@@ -54,7 +71,7 @@ pCanvas::~pCanvas() {
|
|||||||
|
|
||||||
/* internal */
|
/* internal */
|
||||||
|
|
||||||
void pCanvas::resize(uint width, uint height) {
|
void pCanvas::resize(unsigned width, unsigned height) {
|
||||||
if(fbuffer) free(fbuffer);
|
if(fbuffer) free(fbuffer);
|
||||||
if(rbuffer) free(rbuffer);
|
if(rbuffer) free(rbuffer);
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
class pCanvas : public pFormControl {
|
class pCanvas : public pFormControl {
|
||||||
public:
|
public:
|
||||||
void create(uint style, uint width, uint height);
|
void create(unsigned style, unsigned width, unsigned height);
|
||||||
void redraw();
|
void redraw();
|
||||||
uint32_t* buffer();
|
uint32_t* buffer();
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ public:
|
|||||||
//GTK+ RGB drawing function draws in xBGR format, so two buffers are needed ...
|
//GTK+ RGB drawing function draws in xBGR format, so two buffers are needed ...
|
||||||
uint32_t *fbuffer; //one for the xRGB image
|
uint32_t *fbuffer; //one for the xRGB image
|
||||||
uint32_t *rbuffer; //one for the xBGR image
|
uint32_t *rbuffer; //one for the xBGR image
|
||||||
uint bpitch;
|
unsigned bpitch;
|
||||||
void resize(uint width, uint height);
|
void resize(unsigned width, unsigned height);
|
||||||
GtkWidget* gtk_handle();
|
GtkWidget* gtk_handle();
|
||||||
};
|
};
|
@@ -1,8 +1,8 @@
|
|||||||
void hiro_pcheckbox_tick(pCheckbox *p) {
|
void hiro_pcheckbox_tick(pCheckbox *p) {
|
||||||
if(!p->locked && p->self.on_tick) p->self.on_tick(Event(Event::Tick, p->checked(), &p->self));
|
if(!p->locked && p->self.on_tick) p->self.on_tick(event_t(event_t::Tick, p->checked(), &p->self));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pCheckbox::create(uint style, uint width, uint height, const char *text) {
|
void pCheckbox::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||||
checkbox = gtk_check_button_new_with_label(text ? text : "");
|
checkbox = gtk_check_button_new_with_label(text ? text : "");
|
||||||
set_default_font(checkbox);
|
set_default_font(checkbox);
|
||||||
gtk_widget_set_size_request(checkbox, width, height);
|
gtk_widget_set_size_request(checkbox, width, height);
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
class pCheckbox : public pFormControl {
|
class pCheckbox : public pFormControl {
|
||||||
public:
|
public:
|
||||||
void create(uint style, uint width, uint height, const char *text = "");
|
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||||
void set_text(const char *text = "");
|
void set_text(const char *text = "");
|
||||||
void check(bool state = true);
|
void check(bool state = true);
|
||||||
void uncheck();
|
void uncheck();
|
@@ -1,8 +1,8 @@
|
|||||||
void hiro_pcombobox_change(pCombobox *p) {
|
void hiro_pcombobox_change(pCombobox *p) {
|
||||||
if(p->self.on_change) p->self.on_change(Event(Event::Change, p->get_selection(), &p->self));
|
if(p->self.on_change) p->self.on_change(event_t(event_t::Change, p->get_selection(), &p->self));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pCombobox::create(uint style, uint width, uint height, const char *text) {
|
void pCombobox::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||||
combobox = gtk_combo_box_new_text();
|
combobox = gtk_combo_box_new_text();
|
||||||
set_default_font(combobox);
|
set_default_font(combobox);
|
||||||
gtk_widget_set_size_request(combobox, width, height);
|
gtk_widget_set_size_request(combobox, width, height);
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
class pCombobox : public pFormControl {
|
class pCombobox : public pFormControl {
|
||||||
public:
|
public:
|
||||||
void create(uint style, uint width, uint height, const char *text = "");
|
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||||
void add_item(const char *text);
|
void add_item(const char *text);
|
||||||
int get_selection();
|
int get_selection();
|
||||||
void set_selection(int index);
|
void set_selection(int index);
|
||||||
@@ -11,6 +11,6 @@ public:
|
|||||||
|
|
||||||
/* internal */
|
/* internal */
|
||||||
GtkWidget *combobox;
|
GtkWidget *combobox;
|
||||||
uint counter;
|
unsigned counter;
|
||||||
GtkWidget* gtk_handle();
|
GtkWidget* gtk_handle();
|
||||||
};
|
};
|
@@ -1,4 +1,10 @@
|
|||||||
void pEditbox::create(uint style, uint width, uint height, const char *text) {
|
void hiro_peditbox_change(pEditbox *p) {
|
||||||
|
if(p->self.on_change) {
|
||||||
|
p->self.on_change(event_t(event_t::Change, 0, &p->self));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pEditbox::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||||
multiline = bool(style & Editbox::Multiline);
|
multiline = bool(style & Editbox::Multiline);
|
||||||
|
|
||||||
if(multiline == false) {
|
if(multiline == false) {
|
||||||
@@ -7,6 +13,7 @@ void pEditbox::create(uint style, uint width, uint height, const char *text) {
|
|||||||
gtk_entry_set_text(GTK_ENTRY(editbox), text ? text : "");
|
gtk_entry_set_text(GTK_ENTRY(editbox), text ? text : "");
|
||||||
gtk_widget_set_size_request(editbox, width, height);
|
gtk_widget_set_size_request(editbox, width, height);
|
||||||
gtk_widget_show(editbox);
|
gtk_widget_show(editbox);
|
||||||
|
g_signal_connect_swapped(G_OBJECT(editbox), "changed", G_CALLBACK(hiro_peditbox_change), (gpointer)this);
|
||||||
} else {
|
} else {
|
||||||
GtkPolicyType hscroll = (style & Editbox::HorizontalScrollAlways) ? GTK_POLICY_ALWAYS :
|
GtkPolicyType hscroll = (style & Editbox::HorizontalScrollAlways) ? GTK_POLICY_ALWAYS :
|
||||||
(style & Editbox::HorizontalScrollNever) ? GTK_POLICY_NEVER :
|
(style & Editbox::HorizontalScrollNever) ? GTK_POLICY_NEVER :
|
||||||
@@ -25,6 +32,7 @@ void pEditbox::create(uint style, uint width, uint height, const char *text) {
|
|||||||
gtk_text_buffer_set_text(buffer, text ? text : "", -1);
|
gtk_text_buffer_set_text(buffer, text ? text : "", -1);
|
||||||
gtk_widget_show(editbox);
|
gtk_widget_show(editbox);
|
||||||
gtk_widget_show(scrollbox);
|
gtk_widget_show(scrollbox);
|
||||||
|
g_signal_connect_swapped(G_OBJECT(buffer), "changed", G_CALLBACK(hiro_peditbox_change), (gpointer)this);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_default_font(editbox);
|
set_default_font(editbox);
|
||||||
@@ -38,7 +46,7 @@ void pEditbox::set_text(const char *text) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint pEditbox::get_text(char *text, uint length) {
|
unsigned pEditbox::get_text(char *text, unsigned length) {
|
||||||
if(multiline == false) {
|
if(multiline == false) {
|
||||||
const char *temp = gtk_entry_get_text(GTK_ENTRY(editbox));
|
const char *temp = gtk_entry_get_text(GTK_ENTRY(editbox));
|
||||||
return strlcpy(text, temp ? temp : "", length);
|
return strlcpy(text, temp ? temp : "", length);
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
class pEditbox : public pFormControl {
|
class pEditbox : public pFormControl {
|
||||||
public:
|
public:
|
||||||
Editbox &self;
|
Editbox &self;
|
||||||
void create(uint style, uint width, uint height, const char *text = "");
|
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||||
uint get_text(char *text, uint length = -1U);
|
unsigned get_text(char *text, unsigned length = -1U);
|
||||||
void set_text(const char *text = "");
|
void set_text(const char *text = "");
|
||||||
|
|
||||||
pEditbox(Editbox&);
|
pEditbox(Editbox&);
|
@@ -1,4 +1,4 @@
|
|||||||
void pFormControl::resize(uint width, uint height) {
|
void pFormControl::resize(unsigned width, unsigned height) {
|
||||||
gtk_widget_set_size_request(gtk_handle(), width, height);
|
gtk_widget_set_size_request(gtk_handle(), width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
class pFormControl : public pWidget {
|
class pFormControl : public pWidget {
|
||||||
public:
|
public:
|
||||||
virtual void resize(uint width, uint height);
|
virtual void resize(unsigned width, unsigned height);
|
||||||
void focus();
|
void focus();
|
||||||
bool focused();
|
bool focused();
|
||||||
void enable(bool = true);
|
void enable(bool = true);
|
@@ -1,4 +1,4 @@
|
|||||||
void pFrame::create(uint style, uint width, uint height, const char *text) {
|
void pFrame::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||||
frame = gtk_frame_new(text ? text : "");
|
frame = gtk_frame_new(text ? text : "");
|
||||||
set_default_font(frame);
|
set_default_font(frame);
|
||||||
gtk_widget_set_size_request(frame, width, height);
|
gtk_widget_set_size_request(frame, width, height);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
class pFrame : public pFormControl {
|
class pFrame : public pFormControl {
|
||||||
public:
|
public:
|
||||||
Frame &self;
|
Frame &self;
|
||||||
void create(uint style, uint width, uint height, const char *text = "");
|
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||||
void set_text(const char *text = "");
|
void set_text(const char *text = "");
|
||||||
|
|
||||||
pFrame(Frame&);
|
pFrame(Frame&);
|
@@ -1,4 +1,5 @@
|
|||||||
#include "hiro.h"
|
#include "hiro.hpp"
|
||||||
|
#include "port.cpp"
|
||||||
|
|
||||||
#include <nall/algorithm.hpp>
|
#include <nall/algorithm.hpp>
|
||||||
using nall::min;
|
using nall::min;
|
||||||
@@ -40,16 +41,6 @@ static void set_default_font(GtkWidget *widget) {
|
|||||||
#include "slider.cpp"
|
#include "slider.cpp"
|
||||||
|
|
||||||
void pHiro::init() {
|
void pHiro::init() {
|
||||||
//simulate passing argc, argv to gtk_init()
|
|
||||||
int argc = 1;
|
|
||||||
char **argv;
|
|
||||||
argv = (char**)malloc(1 * sizeof(char*));
|
|
||||||
argv[0] = (char*)malloc(64 * sizeof(char));
|
|
||||||
strcpy(argv[0], "./hiro");
|
|
||||||
gtk_init(&argc, &argv);
|
|
||||||
free(argv[0]);
|
|
||||||
free(argv);
|
|
||||||
|
|
||||||
is_composited = false;
|
is_composited = false;
|
||||||
*default_path = 0;
|
*default_path = 0;
|
||||||
screen = gdk_screen_get_default();
|
screen = gdk_screen_get_default();
|
||||||
@@ -158,11 +149,11 @@ bool pHiro::file_save(Window *focus, char *filename, const char *path, const cha
|
|||||||
return strcmp(filename, ""); //return true if filename exists
|
return strcmp(filename, ""); //return true if filename exists
|
||||||
}
|
}
|
||||||
|
|
||||||
uint pHiro::screen_width() {
|
unsigned pHiro::screen_width() {
|
||||||
return gdk_screen_width();
|
return gdk_screen_width();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint pHiro::screen_height() {
|
unsigned pHiro::screen_height() {
|
||||||
return gdk_screen_height();
|
return gdk_screen_height();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,10 @@
|
|||||||
#ifndef HIRO_GTK_H
|
#ifndef HIRO_GTK_H
|
||||||
#define HIRO_GTK_H
|
#define HIRO_GTK_H
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include <gdk/gdkx.h>
|
#include <gdk/gdkx.h>
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
@@ -8,28 +12,30 @@
|
|||||||
#include <X11/extensions/dpms.h>
|
#include <X11/extensions/dpms.h>
|
||||||
#include <X11/extensions/XTest.h>
|
#include <X11/extensions/XTest.h>
|
||||||
|
|
||||||
|
extern int hiromain(int argc, const char *const argv[]);
|
||||||
|
|
||||||
namespace libhiro {
|
namespace libhiro {
|
||||||
|
|
||||||
#include "widget.h"
|
#include "widget.hpp"
|
||||||
#include "window.h"
|
#include "window.hpp"
|
||||||
#include "menucontrol.h"
|
#include "menucontrol.hpp"
|
||||||
#include "menugroup.h"
|
#include "menugroup.hpp"
|
||||||
#include "menuitem.h"
|
#include "menuitem.hpp"
|
||||||
#include "menucheckitem.h"
|
#include "menucheckitem.hpp"
|
||||||
#include "menuradioitem.h"
|
#include "menuradioitem.hpp"
|
||||||
#include "menuseparator.h"
|
#include "menuseparator.hpp"
|
||||||
#include "formcontrol.h"
|
#include "formcontrol.hpp"
|
||||||
#include "frame.h"
|
#include "frame.hpp"
|
||||||
#include "canvas.h"
|
#include "canvas.hpp"
|
||||||
#include "label.h"
|
#include "label.hpp"
|
||||||
#include "button.h"
|
#include "button.hpp"
|
||||||
#include "checkbox.h"
|
#include "checkbox.hpp"
|
||||||
#include "radiobox.h"
|
#include "radiobox.hpp"
|
||||||
#include "editbox.h"
|
#include "editbox.hpp"
|
||||||
#include "listbox.h"
|
#include "listbox.hpp"
|
||||||
#include "combobox.h"
|
#include "combobox.hpp"
|
||||||
#include "progressbar.h"
|
#include "progressbar.hpp"
|
||||||
#include "slider.h"
|
#include "slider.hpp"
|
||||||
|
|
||||||
class pHiro {
|
class pHiro {
|
||||||
public:
|
public:
|
||||||
@@ -43,8 +49,8 @@ public:
|
|||||||
bool file_open(Window *focus, char *filename, const char *path = "", const char *filter = "");
|
bool file_open(Window *focus, char *filename, const char *path = "", const char *filter = "");
|
||||||
bool file_save(Window *focus, char *filename, const char *path = "", const char *filter = "");
|
bool file_save(Window *focus, char *filename, const char *path = "", const char *filter = "");
|
||||||
|
|
||||||
uint screen_width();
|
unsigned screen_width();
|
||||||
uint screen_height();
|
unsigned screen_height();
|
||||||
|
|
||||||
void enable_screensaver();
|
void enable_screensaver();
|
||||||
void disable_screensaver();
|
void disable_screensaver();
|
||||||
@@ -62,7 +68,7 @@ public:
|
|||||||
void set_default_path(const char*);
|
void set_default_path(const char*);
|
||||||
bool is_screensaver_enabled;
|
bool is_screensaver_enabled;
|
||||||
void screensaver_tick();
|
void screensaver_tick();
|
||||||
uint16_t translate_key(uint key);
|
uint16_t translate_key(unsigned key);
|
||||||
};
|
};
|
||||||
|
|
||||||
pHiro& phiro();
|
pHiro& phiro();
|
@@ -1,4 +1,4 @@
|
|||||||
uint16_t pHiro::translate_key(uint key) {
|
uint16_t pHiro::translate_key(unsigned key) {
|
||||||
switch(key) {
|
switch(key) {
|
||||||
case GDK_Escape: return keyboard::escape;
|
case GDK_Escape: return keyboard::escape;
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
void pLabel::create(uint style, uint width, uint height, const char *text) {
|
void pLabel::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||||
label = gtk_label_new(text ? text : "");
|
label = gtk_label_new(text ? text : "");
|
||||||
set_default_font(label);
|
set_default_font(label);
|
||||||
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
|
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
class pLabel : public pFormControl {
|
class pLabel : public pFormControl {
|
||||||
public:
|
public:
|
||||||
Label &self;
|
Label &self;
|
||||||
void create(uint style, uint width, uint height, const char *text = "");
|
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||||
void set_text(const char *text = "");
|
void set_text(const char *text = "");
|
||||||
|
|
||||||
pLabel(Label&);
|
pLabel(Label&);
|
@@ -1,19 +1,27 @@
|
|||||||
void hiro_plistbox_change(pListbox *p) {
|
static void hiro_plistbox_change(pListbox *p) {
|
||||||
|
//only send message when active item changes
|
||||||
if(p->listbox_selection == p->get_selection()) return;
|
if(p->listbox_selection == p->get_selection()) return;
|
||||||
if(p->self.on_change) p->self.on_change(Event(Event::Change, p->listbox_selection = p->get_selection(), &p->self));
|
|
||||||
|
p->listbox_selection = p->get_selection();
|
||||||
|
if(p->self.on_change) {
|
||||||
|
p->self.on_change(event_t(event_t::Change, p->listbox_selection, &p->self));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void hiro_plistbox_activate(pListbox *p) {
|
static void hiro_plistbox_activate(pListbox *p) {
|
||||||
if(p->self.on_activate) p->self.on_activate(Event(Event::Activate, p->listbox_selection = p->get_selection(), &p->self));
|
p->listbox_selection = p->get_selection();
|
||||||
|
if(p->self.on_activate) {
|
||||||
|
p->self.on_activate(event_t(event_t::Activate, p->listbox_selection, &p->self));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListbox::create(uint style, uint width, uint height, const char *columns, const char *text) {
|
void pListbox::create(unsigned style, unsigned width, unsigned height, const char *columns, const char *text) {
|
||||||
bool header = style & Listbox::Header;
|
bool header = style & Listbox::Header;
|
||||||
GtkPolicyType hscroll = (style & Listbox::HorizontalScrollAlways) ? GTK_POLICY_ALWAYS :
|
GtkPolicyType hscroll = (style & Listbox::HorizontalScrollAlways) ? GTK_POLICY_ALWAYS :
|
||||||
(style & Listbox::HorizontalScrollNever) ? GTK_POLICY_NEVER :
|
(style & Listbox::HorizontalScrollNever ) ? GTK_POLICY_NEVER :
|
||||||
GTK_POLICY_AUTOMATIC;
|
GTK_POLICY_AUTOMATIC;
|
||||||
GtkPolicyType vscroll = (style & Listbox::VerticalScrollAlways) ? GTK_POLICY_ALWAYS :
|
GtkPolicyType vscroll = (style & Listbox::VerticalScrollAlways) ? GTK_POLICY_ALWAYS :
|
||||||
(style & Listbox::VerticalScrollNever) ? GTK_POLICY_NEVER :
|
(style & Listbox::VerticalScrollNever ) ? GTK_POLICY_NEVER :
|
||||||
GTK_POLICY_AUTOMATIC;
|
GTK_POLICY_AUTOMATIC;
|
||||||
|
|
||||||
scrollbox = gtk_scrolled_window_new(0, 0);
|
scrollbox = gtk_scrolled_window_new(0, 0);
|
||||||
@@ -24,7 +32,7 @@ void pListbox::create(uint style, uint width, uint height, const char *columns,
|
|||||||
split(list, "\t", columns);
|
split(list, "\t", columns);
|
||||||
|
|
||||||
GType *v = (GType*)malloc(count(list) * sizeof(GType));
|
GType *v = (GType*)malloc(count(list) * sizeof(GType));
|
||||||
for(uint i = 0; i < count(list); i++) v[i] = G_TYPE_STRING;
|
for(unsigned i = 0; i < count(list); i++) v[i] = G_TYPE_STRING;
|
||||||
store = gtk_list_store_newv(count(list), v);
|
store = gtk_list_store_newv(count(list), v);
|
||||||
free(v);
|
free(v);
|
||||||
|
|
||||||
@@ -35,9 +43,9 @@ void pListbox::create(uint style, uint width, uint height, const char *columns,
|
|||||||
gtk_widget_show(listbox);
|
gtk_widget_show(listbox);
|
||||||
gtk_widget_show(scrollbox);
|
gtk_widget_show(scrollbox);
|
||||||
|
|
||||||
//alternate colors for each listbox entry if there are multiple columns ...
|
//alternate colors for each listbox entry if there are multiple columns
|
||||||
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(listbox), count(list) >= 2 ? true : false);
|
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(listbox), count(list) >= 2 ? true : false);
|
||||||
for(uint i = 0; i < count(list); i++) {
|
for(unsigned i = 0; i < count(list); i++) {
|
||||||
renderer = gtk_cell_renderer_text_new();
|
renderer = gtk_cell_renderer_text_new();
|
||||||
column = gtk_tree_view_column_new_with_attributes(list[i], renderer, "text", i, (void*)0);
|
column = gtk_tree_view_column_new_with_attributes(list[i], renderer, "text", i, (void*)0);
|
||||||
column_list[column_list.size()] = column;
|
column_list[column_list.size()] = column;
|
||||||
@@ -46,7 +54,7 @@ void pListbox::create(uint style, uint width, uint height, const char *columns,
|
|||||||
|
|
||||||
if(text && *text) {
|
if(text && *text) {
|
||||||
split(list, "\n", text);
|
split(list, "\n", text);
|
||||||
for(uint i = 0; i < count(list); i++) add_item(list[i]);
|
for(unsigned i = 0; i < count(list); i++) add_item(list[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(listbox), header);
|
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(listbox), header);
|
||||||
@@ -62,64 +70,71 @@ void pListbox::autosize_columns() {
|
|||||||
gtk_tree_view_columns_autosize(GTK_TREE_VIEW(listbox));
|
gtk_tree_view_columns_autosize(GTK_TREE_VIEW(listbox));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListbox::set_column_width(uint column, uint width) {
|
void pListbox::set_column_width(unsigned column, unsigned width) {
|
||||||
gtk_tree_view_column_set_min_width(column_list[column], width);
|
gtk_tree_view_column_set_min_width(column_list[column], width);
|
||||||
gtk_tree_view_column_set_max_width(column_list[column], width);
|
gtk_tree_view_column_set_max_width(column_list[column], width);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListbox::add_item(const char *text) {
|
void pListbox::add_item(const char *text) {
|
||||||
lstring list;
|
lstring list;
|
||||||
split(list, "\t", text);
|
split(list, "\t", text);
|
||||||
gtk_list_store_append(store, &iter);
|
gtk_list_store_append(store, &iter);
|
||||||
for(uint i = 0; i < count(list); i++) {
|
for(unsigned i = 0; i < count(list); i++) {
|
||||||
gtk_list_store_set(store, &iter, i, list[i](), -1);
|
gtk_list_store_set(store, &iter, i, (const char*)list[i], -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListbox::set_item(uint index, const char *text) {
|
void pListbox::set_item(unsigned index, const char *text) {
|
||||||
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(listbox));
|
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(listbox));
|
||||||
for(uint i = 0; i <= index; i++) {
|
for(unsigned i = 0; i <= index; i++) {
|
||||||
i == 0 ?
|
i == 0 ?
|
||||||
gtk_tree_model_get_iter_first(model, &iter) :
|
gtk_tree_model_get_iter_first(model, &iter) :
|
||||||
gtk_tree_model_iter_next(model, &iter);
|
gtk_tree_model_iter_next(model, &iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
lstring list;
|
lstring list;
|
||||||
split(list, "\t", text);
|
split(list, "\t", text);
|
||||||
for(uint i = 0; i < count(list); i++) {
|
for(unsigned i = 0; i < count(list); i++) {
|
||||||
gtk_list_store_set(store, &iter, i, list[i](), -1);
|
gtk_list_store_set(store, &iter, i, (const char*)list[i], -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int pListbox::get_selection() {
|
int pListbox::get_selection() {
|
||||||
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(listbox));
|
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(listbox));
|
||||||
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(listbox));
|
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(listbox));
|
||||||
if(gtk_tree_model_get_iter_first(model, &iter) == false) { return -1; }
|
if(gtk_tree_model_get_iter_first(model, &iter) == false) return -1;
|
||||||
if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) { return 0; }
|
if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) return 0;
|
||||||
for(uint i = 1; i < 100000; i++) {
|
for(unsigned i = 1; i < 100000; i++) {
|
||||||
if(gtk_tree_model_iter_next(model, &iter) == false) { return -1; }
|
if(gtk_tree_model_iter_next(model, &iter) == false) return -1;
|
||||||
if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) { return i; }
|
if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) return i;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListbox::set_selection(int index) {
|
void pListbox::set_selection(int index) {
|
||||||
int current = get_selection();
|
int current = get_selection();
|
||||||
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(listbox));
|
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(listbox));
|
||||||
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(listbox));
|
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(listbox));
|
||||||
gtk_tree_selection_unselect_all(selection);
|
gtk_tree_selection_unselect_all(selection);
|
||||||
if(index < 0) { goto end; }
|
if(index < 0) return; //nothing to select?
|
||||||
if(gtk_tree_model_get_iter_first(model, &iter) == false) { goto end; }
|
|
||||||
if(index == 0) { gtk_tree_selection_select_iter(selection, &iter); goto end; }
|
if(gtk_tree_model_get_iter_first(model, &iter)) {
|
||||||
for(uint i = 1; i < 100000; i++) {
|
if(index == 0) {
|
||||||
if(gtk_tree_model_iter_next(model, &iter) == false) { goto end; }
|
gtk_tree_selection_select_iter(selection, &iter);
|
||||||
if(index == i) { gtk_tree_selection_select_iter(selection, &iter); goto end; }
|
} else {
|
||||||
|
for(unsigned i = 1; i < 100000; i++) {
|
||||||
|
if(gtk_tree_model_iter_next(model, &iter) == false) break;
|
||||||
|
if(index == i) {
|
||||||
|
gtk_tree_selection_select_iter(selection, &iter);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
end:
|
|
||||||
if(current != index) ;//{ owner->message(Message::Changed, (uintptr_t)this); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListbox::reset() {
|
void pListbox::reset() {
|
||||||
|
listbox_selection = -1;
|
||||||
gtk_list_store_clear(GTK_LIST_STORE(store));
|
gtk_list_store_clear(GTK_LIST_STORE(store));
|
||||||
gtk_tree_view_set_model(GTK_TREE_VIEW(listbox), GTK_TREE_MODEL(store));
|
gtk_tree_view_set_model(GTK_TREE_VIEW(listbox), GTK_TREE_MODEL(store));
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
class pListbox : public pFormControl {
|
class pListbox : public pFormControl {
|
||||||
public:
|
public:
|
||||||
void create(uint style, uint width, uint height, const char *columns = "", const char *text = "");
|
void create(unsigned style, unsigned width, unsigned height, const char *columns = "", const char *text = "");
|
||||||
void autosize_columns();
|
void autosize_columns();
|
||||||
void set_column_width(uint column, uint width);
|
void set_column_width(unsigned column, unsigned width);
|
||||||
void add_item(const char *text);
|
void add_item(const char *text);
|
||||||
void set_item(uint index, const char *text);
|
void set_item(unsigned index, const char *text);
|
||||||
int get_selection();
|
int get_selection();
|
||||||
void set_selection(int index);
|
void set_selection(int index);
|
||||||
void reset();
|
void reset();
|
@@ -1,5 +1,5 @@
|
|||||||
void hiro_pmenucheckitem_tick(pMenuCheckItem *p) {
|
void hiro_pmenucheckitem_tick(pMenuCheckItem *p) {
|
||||||
if(!p->locked && p->self.on_tick) p->self.on_tick(Event(Event::Tick, p->checked(), &p->self));
|
if(!p->locked && p->self.on_tick) p->self.on_tick(event_t(event_t::Tick, p->checked(), &p->self));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pMenuCheckItem::create(const char *text) {
|
void pMenuCheckItem::create(const char *text) {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
void hiro_pmenuitem_tick(pMenuItem *p) {
|
void hiro_pmenuitem_tick(pMenuItem *p) {
|
||||||
if(p->self.on_tick) p->self.on_tick(Event(Event::Tick, 0, &p->self));
|
if(p->self.on_tick) p->self.on_tick(event_t(event_t::Tick, 0, &p->self));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pMenuItem::create(const char *text) {
|
void pMenuItem::create(const char *text) {
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
void hiro_pmenuradioitem_tick(pMenuRadioItem *p) {
|
void hiro_pmenuradioitem_tick(pMenuRadioItem *p) {
|
||||||
//GTK+ sends two messages: one for the activated radio item,
|
//GTK+ sends two messages: one for the activated radio item,
|
||||||
//and one for the deactivated radio item. ignore the latter.
|
//and one for the deactivated radio item. ignore the latter.
|
||||||
if(!p->locked && p->checked() && p->self.on_tick) p->self.on_tick(Event(Event::Tick, 0, &p->self));
|
if(!p->locked && p->checked() && p->self.on_tick) p->self.on_tick(event_t(event_t::Tick, 0, &p->self));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pMenuRadioItem::create(MenuRadioItemGroup &group, const char *text) {
|
void pMenuRadioItem::create(MenuRadioItemGroup &group, const char *text) {
|
||||||
|
17
src/lib/hiro/gtk/port.cpp
Normal file
17
src/lib/hiro/gtk/port.cpp
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
char* userpath(char *output) {
|
||||||
|
struct passwd *userinfo = getpwuid(getuid());
|
||||||
|
if(userinfo) { strcpy(output, userinfo->pw_dir); }
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkdir(const char *path) {
|
||||||
|
return mkdir(path, 0755);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
gtk_init(&argc, &argv);
|
||||||
|
libhiro::hiro().init();
|
||||||
|
int result = hiromain(argc, argv);
|
||||||
|
libhiro::hiro().term();
|
||||||
|
return result;
|
||||||
|
}
|
@@ -1,15 +1,15 @@
|
|||||||
void pProgressbar::create(uint style, uint width, uint height) {
|
void pProgressbar::create(unsigned style, unsigned width, unsigned height) {
|
||||||
progressbar = gtk_progress_bar_new();
|
progressbar = gtk_progress_bar_new();
|
||||||
gtk_widget_set_size_request(progressbar, width, height);
|
gtk_widget_set_size_request(progressbar, width, height);
|
||||||
gtk_widget_show(progressbar);
|
gtk_widget_show(progressbar);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint pProgressbar::get_progress() {
|
unsigned pProgressbar::get_progress() {
|
||||||
uint progress = (uint)(gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(progressbar)) * 100.0);
|
unsigned progress = (unsigned)(gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(progressbar)) * 100.0);
|
||||||
return max(0U, min(progress, 100U));
|
return max(0U, min(progress, 100U));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pProgressbar::set_progress(uint progress) {
|
void pProgressbar::set_progress(unsigned progress) {
|
||||||
progress = max(0U, min(progress, 100U));
|
progress = max(0U, min(progress, 100U));
|
||||||
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progressbar), (double)progress / 100.0);
|
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progressbar), (double)progress / 100.0);
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
class pProgressbar : public pFormControl {
|
class pProgressbar : public pFormControl {
|
||||||
public:
|
public:
|
||||||
Progressbar &self;
|
Progressbar &self;
|
||||||
void create(uint style, uint width, uint height);
|
void create(unsigned style, unsigned width, unsigned height);
|
||||||
uint get_progress();
|
unsigned get_progress();
|
||||||
void set_progress(uint progress);
|
void set_progress(unsigned progress);
|
||||||
|
|
||||||
pProgressbar(Progressbar&);
|
pProgressbar(Progressbar&);
|
||||||
|
|
@@ -1,10 +1,10 @@
|
|||||||
void hiro_pradiobox_tick(pRadiobox *p) {
|
void hiro_pradiobox_tick(pRadiobox *p) {
|
||||||
//GTK+ sends two messages: one for the activated radiobox,
|
//GTK+ sends two messages: one for the activated radiobox,
|
||||||
//and one for the deactivated radiobox. ignore the latter.
|
//and one for the deactivated radiobox. ignore the latter.
|
||||||
if(!p->locked && p->checked() && p->self.on_tick) p->self.on_tick(Event(Event::Tick, 0, &p->self));
|
if(!p->locked && p->checked() && p->self.on_tick) p->self.on_tick(event_t(event_t::Tick, 0, &p->self));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pRadiobox::create(RadioboxGroup &group, uint style, uint width, uint height, const char *text) {
|
void pRadiobox::create(RadioboxGroup &group, unsigned style, unsigned width, unsigned height, const char *text) {
|
||||||
if(group.size() == 0 || group[0] == &self) {
|
if(group.size() == 0 || group[0] == &self) {
|
||||||
radiobox = gtk_radio_button_new_with_label(0, text ? text : "");
|
radiobox = gtk_radio_button_new_with_label(0, text ? text : "");
|
||||||
} else {
|
} else {
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
class pRadiobox : public pFormControl {
|
class pRadiobox : public pFormControl {
|
||||||
public:
|
public:
|
||||||
void create(RadioboxGroup &group, uint style, uint width, uint height, const char *text = "");
|
void create(RadioboxGroup &group, unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||||
void set_text(const char *text = "");
|
void set_text(const char *text = "");
|
||||||
void check();
|
void check();
|
||||||
bool checked();
|
bool checked();
|
@@ -1,9 +1,9 @@
|
|||||||
void hiro_pslider_change(pSlider *p) {
|
void hiro_pslider_change(pSlider *p) {
|
||||||
if(p->slider_position == p->get_position()) return;
|
if(p->slider_position == p->get_position()) return;
|
||||||
if(p->self.on_change) p->self.on_change(Event(Event::Change, p->slider_position = p->get_position(), &p->self));
|
if(p->self.on_change) p->self.on_change(event_t(event_t::Change, p->slider_position = p->get_position(), &p->self));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pSlider::create(uint style, uint width, uint height, uint length) {
|
void pSlider::create(unsigned style, unsigned width, unsigned height, unsigned length) {
|
||||||
if(length < 1) length = 1;
|
if(length < 1) length = 1;
|
||||||
if(style & Slider::Vertical) {
|
if(style & Slider::Vertical) {
|
||||||
slider = gtk_vscale_new_with_range(0, length - 1, 1);
|
slider = gtk_vscale_new_with_range(0, length - 1, 1);
|
||||||
@@ -16,11 +16,11 @@ void pSlider::create(uint style, uint width, uint height, uint length) {
|
|||||||
g_signal_connect_swapped(G_OBJECT(slider), "value-changed", G_CALLBACK(hiro_pslider_change), (gpointer)this);
|
g_signal_connect_swapped(G_OBJECT(slider), "value-changed", G_CALLBACK(hiro_pslider_change), (gpointer)this);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint pSlider::get_position() {
|
unsigned pSlider::get_position() {
|
||||||
return (uint)gtk_range_get_value(GTK_RANGE(slider));
|
return (unsigned)gtk_range_get_value(GTK_RANGE(slider));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pSlider::set_position(uint position) {
|
void pSlider::set_position(unsigned position) {
|
||||||
gtk_range_set_value(GTK_RANGE(slider), position);
|
gtk_range_set_value(GTK_RANGE(slider), position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,14 +0,0 @@
|
|||||||
class pSlider : public pFormControl {
|
|
||||||
public:
|
|
||||||
void create(uint style, uint width, uint height, uint length);
|
|
||||||
uint get_position();
|
|
||||||
void set_position(uint position);
|
|
||||||
|
|
||||||
Slider &self;
|
|
||||||
pSlider(Slider&);
|
|
||||||
|
|
||||||
/* internal */
|
|
||||||
GtkWidget *slider;
|
|
||||||
uint slider_position;
|
|
||||||
GtkWidget* gtk_handle();
|
|
||||||
};
|
|
14
src/lib/hiro/gtk/slider.hpp
Normal file
14
src/lib/hiro/gtk/slider.hpp
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
class pSlider : public pFormControl {
|
||||||
|
public:
|
||||||
|
void create(unsigned style, unsigned width, unsigned height, unsigned length);
|
||||||
|
unsigned get_position();
|
||||||
|
void set_position(unsigned position);
|
||||||
|
|
||||||
|
Slider &self;
|
||||||
|
pSlider(Slider&);
|
||||||
|
|
||||||
|
/* internal */
|
||||||
|
GtkWidget *slider;
|
||||||
|
unsigned slider_position;
|
||||||
|
GtkWidget* gtk_handle();
|
||||||
|
};
|
@@ -1,5 +1,5 @@
|
|||||||
static gint hiro_pwindow_close(pWindow *p) {
|
static gint hiro_pwindow_close(pWindow *p) {
|
||||||
uintptr_t r = p->self.on_close ? p->self.on_close(Event(Event::Close, 0, &p->self)) : true;
|
uintptr_t r = p->self.on_close ? p->self.on_close(event_t(event_t::Close, 0, &p->self)) : true;
|
||||||
return !bool(r);
|
return !bool(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,16 +25,24 @@ static gboolean hiro_pwindow_expose(pWindow *p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gint hiro_pwindow_keydown(GtkWidget *w, GdkEventKey *key, pWindow *p) {
|
static gint hiro_pwindow_keydown(GtkWidget *w, GdkEventKey *key, pWindow *p) {
|
||||||
if(p && p->self.on_keydown) p->self.on_keydown(Event(Event::KeyDown, phiro().translate_key(key->keyval), &p->self));
|
if(p && p->self.on_input) {
|
||||||
|
p->self.on_input(event_t(event_t::Input,
|
||||||
|
phiro().translate_key(key->keyval) + (1 << 16),
|
||||||
|
&p->self));
|
||||||
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint hiro_pwindow_keyup(GtkWidget *w, GdkEventKey *key, pWindow *p) {
|
static gint hiro_pwindow_keyup(GtkWidget *w, GdkEventKey *key, pWindow *p) {
|
||||||
if(p && p->self.on_keyup) p->self.on_keyup(Event(Event::KeyUp, phiro().translate_key(key->keyval), &p->self));
|
if(p && p->self.on_input) {
|
||||||
|
p->self.on_input(event_t(event_t::Input,
|
||||||
|
phiro().translate_key(key->keyval) + (0 << 16),
|
||||||
|
&p->self));
|
||||||
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWindow::create(uint style, uint width, uint height, const char *text) {
|
void pWindow::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||||
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||||
gtk_widget_set_colormap(window, phiro().colormap);
|
gtk_widget_set_colormap(window, phiro().colormap);
|
||||||
|
|
||||||
@@ -81,12 +89,12 @@ void pWindow::close() {
|
|||||||
gtk_widget_destroy(window);
|
gtk_widget_destroy(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWindow::move(uint x, uint y) {
|
void pWindow::move(unsigned x, unsigned y) {
|
||||||
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_NONE);
|
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_NONE);
|
||||||
gtk_window_move(GTK_WINDOW(window), x, y);
|
gtk_window_move(GTK_WINDOW(window), x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWindow::resize(uint width, uint height) {
|
void pWindow::resize(unsigned width, unsigned height) {
|
||||||
gtk_widget_set_size_request(formcontainer, width, height);
|
gtk_widget_set_size_request(formcontainer, width, height);
|
||||||
state.width = width;
|
state.width = width;
|
||||||
state.height = height;
|
state.height = height;
|
||||||
@@ -132,14 +140,14 @@ void pWindow::unfullscreen() {
|
|||||||
//is unreliable, as it will usually report the previous window size.
|
//is unreliable, as it will usually report the previous window size.
|
||||||
//therefore, calculate it manually by using state information.
|
//therefore, calculate it manually by using state information.
|
||||||
|
|
||||||
uint pWindow::get_width() {
|
unsigned pWindow::get_width() {
|
||||||
if(state.is_fullscreen == false) return state.width;
|
if(state.is_fullscreen == false) return state.width;
|
||||||
return gdk_screen_width();
|
return gdk_screen_width();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint pWindow::get_height() {
|
unsigned pWindow::get_height() {
|
||||||
if(state.is_fullscreen == false) return state.height;
|
if(state.is_fullscreen == false) return state.height;
|
||||||
uint height = gdk_screen_height();
|
unsigned height = gdk_screen_height();
|
||||||
|
|
||||||
//do not include menubar height in client area height
|
//do not include menubar height in client area height
|
||||||
if(menu.visible()) {
|
if(menu.visible()) {
|
||||||
@@ -198,7 +206,7 @@ void pWindow::set_text(const char *text) {
|
|||||||
gtk_window_set_title(GTK_WINDOW(window), text ? text : "");
|
gtk_window_set_title(GTK_WINDOW(window), text ? text : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWindow::attach(Window &window, uint x, uint y) {
|
void pWindow::attach(Window &window, unsigned x, unsigned y) {
|
||||||
window.p.owner = this;
|
window.p.owner = this;
|
||||||
|
|
||||||
//GTK+ does not support attaching a window to another window,
|
//GTK+ does not support attaching a window to another window,
|
||||||
@@ -216,15 +224,15 @@ void pWindow::attach(MenuGroup &menugroup) {
|
|||||||
gtk_widget_show(menubar);
|
gtk_widget_show(menubar);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWindow::attach(FormControl &formcontrol, uint x, uint y) {
|
void pWindow::attach(FormControl &formcontrol, unsigned x, unsigned y) {
|
||||||
gtk_fixed_put(GTK_FIXED(formcontainer), formcontrol.p.gtk_handle(), x, y);
|
gtk_fixed_put(GTK_FIXED(formcontainer), formcontrol.p.gtk_handle(), x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWindow::move(Window &window, uint x, uint y) {
|
void pWindow::move(Window &window, unsigned x, unsigned y) {
|
||||||
gtk_fixed_move(GTK_FIXED(formcontainer), window.p.gtk_handle(), x, y);
|
gtk_fixed_move(GTK_FIXED(formcontainer), window.p.gtk_handle(), x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWindow::move(FormControl &formcontrol, uint x, uint y) {
|
void pWindow::move(FormControl &formcontrol, unsigned x, unsigned y) {
|
||||||
gtk_fixed_move(GTK_FIXED(formcontainer), formcontrol.p.gtk_handle(), x, y);
|
gtk_fixed_move(GTK_FIXED(formcontainer), formcontrol.p.gtk_handle(), x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,24 +1,24 @@
|
|||||||
class pWindow : public pWidget {
|
class pWindow : public pWidget {
|
||||||
public:
|
public:
|
||||||
void create(uint style, uint width, uint height, const char *text = "");
|
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||||
void close();
|
void close();
|
||||||
void move(uint x, uint y);
|
void move(unsigned x, unsigned y);
|
||||||
void resize(uint width, uint height);
|
void resize(unsigned width, unsigned height);
|
||||||
void focus();
|
void focus();
|
||||||
bool focused();
|
bool focused();
|
||||||
void fullscreen();
|
void fullscreen();
|
||||||
void unfullscreen();
|
void unfullscreen();
|
||||||
uint get_width();
|
unsigned get_width();
|
||||||
uint get_height();
|
unsigned get_height();
|
||||||
void set_opacity(uint8_t opacity);
|
void set_opacity(uint8_t opacity);
|
||||||
void set_background_color(uint8_t r, uint8_t g, uint8_t b);
|
void set_background_color(uint8_t r, uint8_t g, uint8_t b);
|
||||||
void set_icon(unsigned width, unsigned height, const uint32_t *data);
|
void set_icon(unsigned width, unsigned height, const uint32_t *data);
|
||||||
void set_text(const char *text = "");
|
void set_text(const char *text = "");
|
||||||
void attach(Window &window, uint x, uint y);
|
void attach(Window &window, unsigned x, unsigned y);
|
||||||
void attach(MenuGroup &menugroup);
|
void attach(MenuGroup &menugroup);
|
||||||
void attach(FormControl &formcontrol, uint x, uint y);
|
void attach(FormControl &formcontrol, unsigned x, unsigned y);
|
||||||
void move(Window &window, uint x, uint y);
|
void move(Window &window, unsigned x, unsigned y);
|
||||||
void move(FormControl &formcontrol, uint x, uint y);
|
void move(FormControl &formcontrol, unsigned x, unsigned y);
|
||||||
|
|
||||||
class Statusbar {
|
class Statusbar {
|
||||||
public:
|
public:
|
||||||
@@ -55,9 +55,9 @@ public:
|
|||||||
GtkWidget* gtk_handle();
|
GtkWidget* gtk_handle();
|
||||||
struct {
|
struct {
|
||||||
bool is_fullscreen;
|
bool is_fullscreen;
|
||||||
uint width;
|
unsigned width;
|
||||||
uint height;
|
unsigned height;
|
||||||
uint alpha;
|
unsigned alpha;
|
||||||
} state;
|
} state;
|
||||||
|
|
||||||
void menu_show(bool = true);
|
void menu_show(bool = true);
|
@@ -1,4 +1,4 @@
|
|||||||
#include "hiro.h"
|
#include "hiro.hpp"
|
||||||
using namespace nall;
|
using namespace nall;
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
@@ -18,8 +18,8 @@ bool Hiro::pending() { return p.pending(); }
|
|||||||
bool Hiro::folder_select(Window *focus, char *filename, const char *path) { return p.folder_select(focus, filename, path); }
|
bool Hiro::folder_select(Window *focus, char *filename, const char *path) { return p.folder_select(focus, filename, path); }
|
||||||
bool Hiro::file_open(Window *focus, char *filename, const char *path, const char *filter) { return p.file_open(focus, filename, path, filter); }
|
bool Hiro::file_open(Window *focus, char *filename, const char *path, const char *filter) { return p.file_open(focus, filename, path, filter); }
|
||||||
bool Hiro::file_save(Window *focus, char *filename, const char *path, const char *filter) { return p.file_save(focus, filename, path, filter); }
|
bool Hiro::file_save(Window *focus, char *filename, const char *path, const char *filter) { return p.file_save(focus, filename, path, filter); }
|
||||||
uint Hiro::screen_width() { return p.screen_width(); }
|
unsigned Hiro::screen_width() { return p.screen_width(); }
|
||||||
uint Hiro::screen_height() { return p.screen_height(); }
|
unsigned Hiro::screen_height() { return p.screen_height(); }
|
||||||
void Hiro::enable_screensaver() { p.enable_screensaver(); }
|
void Hiro::enable_screensaver() { p.enable_screensaver(); }
|
||||||
void Hiro::disable_screensaver() { p.disable_screensaver(); }
|
void Hiro::disable_screensaver() { p.disable_screensaver(); }
|
||||||
Hiro& Hiro::handle() { static Hiro hiro; return hiro; }
|
Hiro& Hiro::handle() { static Hiro hiro; return hiro; }
|
||||||
@@ -39,25 +39,25 @@ Widget::~Widget() { delete &p; }
|
|||||||
|
|
||||||
/* Widget -> Window */
|
/* Widget -> Window */
|
||||||
|
|
||||||
void Window::create(uint style, uint width, uint height, const char *text) { p.create(style, width, height, text); }
|
void Window::create(unsigned style, unsigned width, unsigned height, const char *text) { p.create(style, width, height, text); }
|
||||||
void Window::close() { p.close(); }
|
void Window::close() { p.close(); }
|
||||||
void Window::move(uint x, uint y) { p.move(x, y); }
|
void Window::move(unsigned x, unsigned y) { p.move(x, y); }
|
||||||
void Window::resize(uint width, uint height) { p.resize(width, height); }
|
void Window::resize(unsigned width, unsigned height) { p.resize(width, height); }
|
||||||
void Window::focus() { p.focus(); }
|
void Window::focus() { p.focus(); }
|
||||||
bool Window::focused() { return p.focused(); }
|
bool Window::focused() { return p.focused(); }
|
||||||
void Window::fullscreen() { p.fullscreen(); }
|
void Window::fullscreen() { p.fullscreen(); }
|
||||||
void Window::unfullscreen() { p.unfullscreen(); }
|
void Window::unfullscreen() { p.unfullscreen(); }
|
||||||
uint Window::get_width() { return p.get_width(); }
|
unsigned Window::get_width() { return p.get_width(); }
|
||||||
uint Window::get_height() { return p.get_height(); }
|
unsigned Window::get_height() { return p.get_height(); }
|
||||||
void Window::set_opacity(uint8_t opacity) { p.set_opacity(opacity); }
|
void Window::set_opacity(uint8_t opacity) { p.set_opacity(opacity); }
|
||||||
void Window::set_background_color(uint8_t r, uint8_t g, uint8_t b) { p.set_background_color(r, g, b); }
|
void Window::set_background_color(uint8_t r, uint8_t g, uint8_t b) { p.set_background_color(r, g, b); }
|
||||||
void Window::set_icon(unsigned width, unsigned height, const uint32_t *data) { p.set_icon(width, height, data); }
|
void Window::set_icon(unsigned width, unsigned height, const uint32_t *data) { p.set_icon(width, height, data); }
|
||||||
void Window::set_text(const char *text) { p.set_text(text); }
|
void Window::set_text(const char *text) { p.set_text(text); }
|
||||||
void Window::attach(Window &window, uint x, uint y) { p.attach(window, x, y); }
|
void Window::attach(Window &window, unsigned x, unsigned y) { p.attach(window, x, y); }
|
||||||
void Window::attach(MenuGroup &menugroup) { p.attach(menugroup); }
|
void Window::attach(MenuGroup &menugroup) { p.attach(menugroup); }
|
||||||
void Window::attach(FormControl &formcontrol, uint x, uint y) { p.attach(formcontrol, x, y); }
|
void Window::attach(FormControl &formcontrol, unsigned x, unsigned y) { p.attach(formcontrol, x, y); }
|
||||||
void Window::move(Window &window, uint x, uint y) { p.move(window, x, y); }
|
void Window::move(Window &window, unsigned x, unsigned y) { p.move(window, x, y); }
|
||||||
void Window::move(FormControl &formcontrol, uint x, uint y) { p.move(formcontrol, x, y); }
|
void Window::move(FormControl &formcontrol, unsigned x, unsigned y) { p.move(formcontrol, x, y); }
|
||||||
|
|
||||||
void Window::Menubar::show(bool state) { p.menu.show(state); }
|
void Window::Menubar::show(bool state) { p.menu.show(state); }
|
||||||
void Window::Menubar::hide() { p.menu.hide(); }
|
void Window::Menubar::hide() { p.menu.hide(); }
|
||||||
@@ -139,7 +139,7 @@ MenuSeparator::MenuSeparator() :
|
|||||||
|
|
||||||
/* Widget -> FormControl */
|
/* Widget -> FormControl */
|
||||||
|
|
||||||
void FormControl::resize(uint width, uint height) { p.resize(width, height); }
|
void FormControl::resize(unsigned width, unsigned height) { p.resize(width, height); }
|
||||||
void FormControl::focus() { p.focus(); }
|
void FormControl::focus() { p.focus(); }
|
||||||
bool FormControl::focused() { return p.focused(); }
|
bool FormControl::focused() { return p.focused(); }
|
||||||
void FormControl::enable(bool state) { p.enable(state); }
|
void FormControl::enable(bool state) { p.enable(state); }
|
||||||
@@ -156,7 +156,7 @@ FormControl::FormControl(pFormControl &p_) :
|
|||||||
|
|
||||||
/* Widget -> FormControl -> Frame */
|
/* Widget -> FormControl -> Frame */
|
||||||
|
|
||||||
void Frame::create(uint style, uint width, uint height, const char *text) { p.create(style, width, height, text); }
|
void Frame::create(unsigned style, unsigned width, unsigned height, const char *text) { p.create(style, width, height, text); }
|
||||||
void Frame::set_text(const char *text) { p.set_text(text); }
|
void Frame::set_text(const char *text) { p.set_text(text); }
|
||||||
Frame::Frame() :
|
Frame::Frame() :
|
||||||
base_from_member<pFrame&>(*new pFrame(*this)),
|
base_from_member<pFrame&>(*new pFrame(*this)),
|
||||||
@@ -165,7 +165,7 @@ Frame::Frame() :
|
|||||||
|
|
||||||
/* Widget -> FormControl -> Canvas */
|
/* Widget -> FormControl -> Canvas */
|
||||||
|
|
||||||
void Canvas::create(uint style, uint width, uint height) { p.create(style, width, height); }
|
void Canvas::create(unsigned style, unsigned width, unsigned height) { p.create(style, width, height); }
|
||||||
void Canvas::redraw() { p.redraw(); }
|
void Canvas::redraw() { p.redraw(); }
|
||||||
uint32_t* Canvas::buffer() { return p.buffer(); }
|
uint32_t* Canvas::buffer() { return p.buffer(); }
|
||||||
Canvas::Canvas() :
|
Canvas::Canvas() :
|
||||||
@@ -175,7 +175,7 @@ Canvas::Canvas() :
|
|||||||
|
|
||||||
/* Widget -> FormControl -> Label */
|
/* Widget -> FormControl -> Label */
|
||||||
|
|
||||||
void Label::create(uint style, uint width, uint height, const char *text) { p.create(style, width, height, text); }
|
void Label::create(unsigned style, unsigned width, unsigned height, const char *text) { p.create(style, width, height, text); }
|
||||||
void Label::set_text(const char *text) { p.set_text(text); }
|
void Label::set_text(const char *text) { p.set_text(text); }
|
||||||
Label::Label() :
|
Label::Label() :
|
||||||
base_from_member<pLabel&>(*new pLabel(*this)),
|
base_from_member<pLabel&>(*new pLabel(*this)),
|
||||||
@@ -184,7 +184,7 @@ Label::Label() :
|
|||||||
|
|
||||||
/* Widget -> FormControl -> Button */
|
/* Widget -> FormControl -> Button */
|
||||||
|
|
||||||
void Button::create(uint style, uint width, uint height, const char *text) { p.create(style, width, height, text); }
|
void Button::create(unsigned style, unsigned width, unsigned height, const char *text) { p.create(style, width, height, text); }
|
||||||
void Button::set_text(const char *text) { p.set_text(text); }
|
void Button::set_text(const char *text) { p.set_text(text); }
|
||||||
Button::Button() :
|
Button::Button() :
|
||||||
base_from_member<pButton&>(*new pButton(*this)),
|
base_from_member<pButton&>(*new pButton(*this)),
|
||||||
@@ -193,7 +193,7 @@ Button::Button() :
|
|||||||
|
|
||||||
/* Widget -> FormControl -> Checkbox */
|
/* Widget -> FormControl -> Checkbox */
|
||||||
|
|
||||||
void Checkbox::create(uint style, uint width, uint height, const char *text) { p.create(style, width, height, text); }
|
void Checkbox::create(unsigned style, unsigned width, unsigned height, const char *text) { p.create(style, width, height, text); }
|
||||||
void Checkbox::set_text(const char *text) { p.set_text(text); }
|
void Checkbox::set_text(const char *text) { p.set_text(text); }
|
||||||
void Checkbox::check(bool state) { state ? p.check() : p.uncheck(); }
|
void Checkbox::check(bool state) { state ? p.check() : p.uncheck(); }
|
||||||
void Checkbox::uncheck() { p.uncheck(); }
|
void Checkbox::uncheck() { p.uncheck(); }
|
||||||
@@ -205,7 +205,7 @@ Checkbox::Checkbox() :
|
|||||||
|
|
||||||
/* Widget -> FormControl -> Radiobox */
|
/* Widget -> FormControl -> Radiobox */
|
||||||
|
|
||||||
void Radiobox::create(RadioboxGroup &group, uint style, uint width, uint height, const char *text) { p.create(group, style, width, height, text); }
|
void Radiobox::create(RadioboxGroup &group, unsigned style, unsigned width, unsigned height, const char *text) { p.create(group, style, width, height, text); }
|
||||||
void Radiobox::set_text(const char *text) { p.set_text(text); }
|
void Radiobox::set_text(const char *text) { p.set_text(text); }
|
||||||
void Radiobox::check() { p.check(); }
|
void Radiobox::check() { p.check(); }
|
||||||
bool Radiobox::checked() { return p.checked(); }
|
bool Radiobox::checked() { return p.checked(); }
|
||||||
@@ -216,8 +216,8 @@ Radiobox::Radiobox() :
|
|||||||
|
|
||||||
/* Widget -> FormControl -> Editbox */
|
/* Widget -> FormControl -> Editbox */
|
||||||
|
|
||||||
void Editbox::create(uint style, uint width, uint height, const char *text) { p.create(style, width, height, text); }
|
void Editbox::create(unsigned style, unsigned width, unsigned height, const char *text) { p.create(style, width, height, text); }
|
||||||
uint Editbox::get_text(char *text, uint length) { return p.get_text(text, length); }
|
unsigned Editbox::get_text(char *text, unsigned length) { return p.get_text(text, length); }
|
||||||
void Editbox::set_text(const char *text) { p.set_text(text); }
|
void Editbox::set_text(const char *text) { p.set_text(text); }
|
||||||
Editbox::Editbox() :
|
Editbox::Editbox() :
|
||||||
base_from_member<pEditbox&>(*new pEditbox(*this)),
|
base_from_member<pEditbox&>(*new pEditbox(*this)),
|
||||||
@@ -226,11 +226,11 @@ Editbox::Editbox() :
|
|||||||
|
|
||||||
/* Widget -> FormControl -> Listbox */
|
/* Widget -> FormControl -> Listbox */
|
||||||
|
|
||||||
void Listbox::create(uint style, uint width, uint height, const char *columns, const char *text) { p.create(style, width, height, columns, text); }
|
void Listbox::create(unsigned style, unsigned width, unsigned height, const char *columns, const char *text) { p.create(style, width, height, columns, text); }
|
||||||
void Listbox::autosize_columns() { p.autosize_columns(); }
|
void Listbox::autosize_columns() { p.autosize_columns(); }
|
||||||
void Listbox::set_column_width(uint column, uint width) { p.set_column_width(column, width); }
|
void Listbox::set_column_width(unsigned column, unsigned width) { p.set_column_width(column, width); }
|
||||||
void Listbox::add_item(const char *text) { p.add_item(text); }
|
void Listbox::add_item(const char *text) { p.add_item(text); }
|
||||||
void Listbox::set_item(uint index, const char *text) { p.set_item(index, text); }
|
void Listbox::set_item(unsigned index, const char *text) { p.set_item(index, text); }
|
||||||
int Listbox::get_selection() { return p.get_selection(); }
|
int Listbox::get_selection() { return p.get_selection(); }
|
||||||
void Listbox::set_selection(int index) { p.set_selection(index); }
|
void Listbox::set_selection(int index) { p.set_selection(index); }
|
||||||
void Listbox::reset() { p.reset(); }
|
void Listbox::reset() { p.reset(); }
|
||||||
@@ -241,7 +241,7 @@ Listbox::Listbox() :
|
|||||||
|
|
||||||
/* Widget -> FormControl -> Combobox */
|
/* Widget -> FormControl -> Combobox */
|
||||||
|
|
||||||
void Combobox::create(uint style, uint width, uint height, const char *text) { p.create(style, width, height, text); }
|
void Combobox::create(unsigned style, unsigned width, unsigned height, const char *text) { p.create(style, width, height, text); }
|
||||||
void Combobox::add_item(const char *text) { p.add_item(text); }
|
void Combobox::add_item(const char *text) { p.add_item(text); }
|
||||||
int Combobox::get_selection() { return p.get_selection(); }
|
int Combobox::get_selection() { return p.get_selection(); }
|
||||||
void Combobox::set_selection(int index) { p.set_selection(index); }
|
void Combobox::set_selection(int index) { p.set_selection(index); }
|
||||||
@@ -253,9 +253,9 @@ Combobox::Combobox() :
|
|||||||
|
|
||||||
/* Widget -> FormControl -> Progressbar */
|
/* Widget -> FormControl -> Progressbar */
|
||||||
|
|
||||||
void Progressbar::create(uint style, uint width, uint height) { p.create(style, width, height); }
|
void Progressbar::create(unsigned style, unsigned width, unsigned height) { p.create(style, width, height); }
|
||||||
uint Progressbar::get_progress() { return p.get_progress(); }
|
unsigned Progressbar::get_progress() { return p.get_progress(); }
|
||||||
void Progressbar::set_progress(uint progress) { p.set_progress(progress); }
|
void Progressbar::set_progress(unsigned progress) { p.set_progress(progress); }
|
||||||
Progressbar::Progressbar() :
|
Progressbar::Progressbar() :
|
||||||
base_from_member<pProgressbar&>(*new pProgressbar(*this)),
|
base_from_member<pProgressbar&>(*new pProgressbar(*this)),
|
||||||
FormControl(base_from_member<pProgressbar&>::value),
|
FormControl(base_from_member<pProgressbar&>::value),
|
||||||
@@ -263,9 +263,9 @@ Progressbar::Progressbar() :
|
|||||||
|
|
||||||
/* Widget -> FormControl -> Slider */
|
/* Widget -> FormControl -> Slider */
|
||||||
|
|
||||||
void Slider::create(uint style, uint width, uint height, uint length) { p.create(style, width, height, length); }
|
void Slider::create(unsigned style, unsigned width, unsigned height, unsigned length) { p.create(style, width, height, length); }
|
||||||
uint Slider::get_position() { return p.get_position(); }
|
unsigned Slider::get_position() { return p.get_position(); }
|
||||||
void Slider::set_position(uint position) { p.set_position(position); }
|
void Slider::set_position(unsigned position) { p.set_position(position); }
|
||||||
Slider::Slider() :
|
Slider::Slider() :
|
||||||
base_from_member<pSlider&>(*new pSlider(*this)),
|
base_from_member<pSlider&>(*new pSlider(*this)),
|
||||||
FormControl(base_from_member<pSlider&>::value),
|
FormControl(base_from_member<pSlider&>::value),
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
hiro
|
hiro
|
||||||
version: 0.005 (2008-05-25)
|
version: 0.008 (2008-10-27)
|
||||||
author: byuu
|
author: byuu
|
||||||
license: public domain
|
license: public domain
|
||||||
*/
|
*/
|
||||||
@@ -15,7 +15,10 @@
|
|||||||
#include <nall/stdint.hpp>
|
#include <nall/stdint.hpp>
|
||||||
#include <nall/string.hpp>
|
#include <nall/string.hpp>
|
||||||
#include <nall/utility.hpp>
|
#include <nall/utility.hpp>
|
||||||
typedef unsigned int uint;
|
|
||||||
|
extern char* realpath(const char*, char*);
|
||||||
|
extern char* userpath(char*);
|
||||||
|
int mkdir(const char*);
|
||||||
|
|
||||||
namespace libhiro {
|
namespace libhiro {
|
||||||
|
|
||||||
@@ -89,12 +92,11 @@ class Widget;
|
|||||||
typedef nall::array<MenuRadioItem*> MenuRadioItemGroup;
|
typedef nall::array<MenuRadioItem*> MenuRadioItemGroup;
|
||||||
typedef nall::array<Radiobox*> RadioboxGroup;
|
typedef nall::array<Radiobox*> RadioboxGroup;
|
||||||
|
|
||||||
struct Event {
|
struct event_t {
|
||||||
enum Type {
|
enum type_t {
|
||||||
Close,
|
Close,
|
||||||
Block,
|
Block,
|
||||||
KeyDown,
|
Input,
|
||||||
KeyUp,
|
|
||||||
Change,
|
Change,
|
||||||
Tick,
|
Tick,
|
||||||
Activate,
|
Activate,
|
||||||
@@ -102,7 +104,7 @@ struct Event {
|
|||||||
uintptr_t param;
|
uintptr_t param;
|
||||||
Widget *widget;
|
Widget *widget;
|
||||||
|
|
||||||
Event(Type type_, uintptr_t param_ = 0, Widget *widget_ = 0) :
|
event_t(type_t type_, uintptr_t param_ = 0, Widget *widget_ = 0) :
|
||||||
type(type_), param(param_), widget(widget_) {}
|
type(type_), param(param_), widget(widget_) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -117,8 +119,8 @@ public:
|
|||||||
bool file_open(Window *focus, char *filename, const char *path = "", const char *filter = "");
|
bool file_open(Window *focus, char *filename, const char *path = "", const char *filter = "");
|
||||||
bool file_save(Window *focus, char *filename, const char *path = "", const char *filter = "");
|
bool file_save(Window *focus, char *filename, const char *path = "", const char *filter = "");
|
||||||
|
|
||||||
uint screen_width();
|
unsigned screen_width();
|
||||||
uint screen_height();
|
unsigned screen_height();
|
||||||
|
|
||||||
void enable_screensaver();
|
void enable_screensaver();
|
||||||
void disable_screensaver();
|
void disable_screensaver();
|
||||||
@@ -182,26 +184,26 @@ public:
|
|||||||
AutoCenter = 1 << 1,
|
AutoCenter = 1 << 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
void create(uint style, uint width, uint height, const char *text = "");
|
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||||
void close();
|
void close();
|
||||||
void move(uint x, uint y);
|
void move(unsigned x, unsigned y);
|
||||||
void resize(uint width, uint height);
|
void resize(unsigned width, unsigned height);
|
||||||
void focus();
|
void focus();
|
||||||
bool focused();
|
bool focused();
|
||||||
void fullscreen();
|
void fullscreen();
|
||||||
void unfullscreen();
|
void unfullscreen();
|
||||||
uint get_width();
|
unsigned get_width();
|
||||||
uint get_height();
|
unsigned get_height();
|
||||||
void set_opacity(uint8_t opacity);
|
void set_opacity(uint8_t opacity);
|
||||||
void set_background_color(uint8_t r, uint8_t g, uint8_t b);
|
void set_background_color(uint8_t r, uint8_t g, uint8_t b);
|
||||||
void set_icon(unsigned width, unsigned height, const uint32_t *data);
|
void set_icon(unsigned width, unsigned height, const uint32_t *data);
|
||||||
void set_status_text(const char *text = "");
|
void set_status_text(const char *text = "");
|
||||||
void set_text(const char *text = "");
|
void set_text(const char *text = "");
|
||||||
void attach(Window &window, uint x, uint y);
|
void attach(Window &window, unsigned x, unsigned y);
|
||||||
void attach(MenuGroup &menugroup);
|
void attach(MenuGroup &menugroup);
|
||||||
void attach(FormControl &formcontrol, uint x, uint y);
|
void attach(FormControl &formcontrol, unsigned x, unsigned y);
|
||||||
void move(Window &window, uint x, uint y);
|
void move(Window &window, unsigned x, unsigned y);
|
||||||
void move(FormControl &formcontrol, uint x, uint y);
|
void move(FormControl &formcontrol, unsigned x, unsigned y);
|
||||||
|
|
||||||
class Menubar {
|
class Menubar {
|
||||||
public:
|
public:
|
||||||
@@ -224,10 +226,9 @@ public:
|
|||||||
Statusbar(pWindow&);
|
Statusbar(pWindow&);
|
||||||
} status;
|
} status;
|
||||||
|
|
||||||
nall::function<uintptr_t (Event)> on_close;
|
nall::function<uintptr_t (event_t)> on_close;
|
||||||
nall::function<uintptr_t (Event)> on_block;
|
nall::function<uintptr_t (event_t)> on_block;
|
||||||
nall::function<uintptr_t (Event)> on_keydown;
|
nall::function<uintptr_t (event_t)> on_input;
|
||||||
nall::function<uintptr_t (Event)> on_keyup;
|
|
||||||
|
|
||||||
Window();
|
Window();
|
||||||
|
|
||||||
@@ -268,7 +269,7 @@ public:
|
|||||||
MenuItem& create(const char *text);
|
MenuItem& create(const char *text);
|
||||||
MenuItem();
|
MenuItem();
|
||||||
|
|
||||||
nall::function<uintptr_t (Event)> on_tick;
|
nall::function<uintptr_t (event_t)> on_tick;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
pFriends;
|
pFriends;
|
||||||
@@ -283,7 +284,7 @@ public:
|
|||||||
bool checked();
|
bool checked();
|
||||||
MenuCheckItem();
|
MenuCheckItem();
|
||||||
|
|
||||||
nall::function<uintptr_t (Event)> on_tick;
|
nall::function<uintptr_t (event_t)> on_tick;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
pFriends;
|
pFriends;
|
||||||
@@ -297,7 +298,7 @@ public:
|
|||||||
bool checked();
|
bool checked();
|
||||||
MenuRadioItem();
|
MenuRadioItem();
|
||||||
|
|
||||||
nall::function<uintptr_t (Event)> on_tick;
|
nall::function<uintptr_t (event_t)> on_tick;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
pFriends;
|
pFriends;
|
||||||
@@ -316,7 +317,7 @@ private:
|
|||||||
|
|
||||||
class FormControl : private nall::base_from_member<pFormControl&>, public Widget {
|
class FormControl : private nall::base_from_member<pFormControl&>, public Widget {
|
||||||
public:
|
public:
|
||||||
void resize(uint width, uint height);
|
void resize(unsigned width, unsigned height);
|
||||||
void focus();
|
void focus();
|
||||||
bool focused();
|
bool focused();
|
||||||
void enable(bool = true);
|
void enable(bool = true);
|
||||||
@@ -335,7 +336,7 @@ private:
|
|||||||
|
|
||||||
class Frame : private nall::base_from_member<pFrame&>, public FormControl {
|
class Frame : private nall::base_from_member<pFrame&>, public FormControl {
|
||||||
public:
|
public:
|
||||||
void create(uint style, uint width, uint height, const char *text = "");
|
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||||
void set_text(const char *text = "");
|
void set_text(const char *text = "");
|
||||||
|
|
||||||
Frame();
|
Frame();
|
||||||
@@ -347,12 +348,14 @@ private:
|
|||||||
|
|
||||||
class Canvas : private nall::base_from_member<pCanvas&>, public FormControl {
|
class Canvas : private nall::base_from_member<pCanvas&>, public FormControl {
|
||||||
public:
|
public:
|
||||||
void create(uint style, uint width, uint height);
|
void create(unsigned style, unsigned width, unsigned height);
|
||||||
void redraw();
|
void redraw();
|
||||||
uint32_t* buffer();
|
uint32_t* buffer();
|
||||||
|
|
||||||
Canvas();
|
Canvas();
|
||||||
|
|
||||||
|
nall::function<uintptr_t (event_t)> on_input;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
pFriends;
|
pFriends;
|
||||||
pCanvas &p;
|
pCanvas &p;
|
||||||
@@ -360,7 +363,7 @@ private:
|
|||||||
|
|
||||||
class Label : private nall::base_from_member<pLabel&>, public FormControl {
|
class Label : private nall::base_from_member<pLabel&>, public FormControl {
|
||||||
public:
|
public:
|
||||||
void create(uint style, uint width, uint height, const char *text = "");
|
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||||
void set_text(const char *text = "");
|
void set_text(const char *text = "");
|
||||||
|
|
||||||
Label();
|
Label();
|
||||||
@@ -372,10 +375,10 @@ private:
|
|||||||
|
|
||||||
class Button : private nall::base_from_member<pButton&>, public FormControl {
|
class Button : private nall::base_from_member<pButton&>, public FormControl {
|
||||||
public:
|
public:
|
||||||
void create(uint style, uint width, uint height, const char *text = "");
|
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||||
void set_text(const char *text = "");
|
void set_text(const char *text = "");
|
||||||
|
|
||||||
nall::function<uintptr_t (Event)> on_tick;
|
nall::function<uintptr_t (event_t)> on_tick;
|
||||||
|
|
||||||
Button();
|
Button();
|
||||||
|
|
||||||
@@ -386,13 +389,13 @@ private:
|
|||||||
|
|
||||||
class Checkbox : private nall::base_from_member<pCheckbox&>, public FormControl {
|
class Checkbox : private nall::base_from_member<pCheckbox&>, public FormControl {
|
||||||
public:
|
public:
|
||||||
void create(uint style, uint width, uint height, const char *text = "");
|
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||||
void set_text(const char *text = "");
|
void set_text(const char *text = "");
|
||||||
void check(bool = true);
|
void check(bool = true);
|
||||||
void uncheck();
|
void uncheck();
|
||||||
bool checked();
|
bool checked();
|
||||||
|
|
||||||
nall::function<uintptr_t (Event)> on_tick;
|
nall::function<uintptr_t (event_t)> on_tick;
|
||||||
|
|
||||||
Checkbox();
|
Checkbox();
|
||||||
|
|
||||||
@@ -403,12 +406,12 @@ private:
|
|||||||
|
|
||||||
class Radiobox : private nall::base_from_member<pRadiobox&>, public FormControl {
|
class Radiobox : private nall::base_from_member<pRadiobox&>, public FormControl {
|
||||||
public:
|
public:
|
||||||
void create(RadioboxGroup &group, uint style, uint width, uint height, const char *text = "");
|
void create(RadioboxGroup &group, unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||||
void set_text(const char *text = "");
|
void set_text(const char *text = "");
|
||||||
void check();
|
void check();
|
||||||
bool checked();
|
bool checked();
|
||||||
|
|
||||||
nall::function<uintptr_t (Event)> on_tick;
|
nall::function<uintptr_t (event_t)> on_tick;
|
||||||
|
|
||||||
Radiobox();
|
Radiobox();
|
||||||
|
|
||||||
@@ -432,10 +435,12 @@ public:
|
|||||||
VerticalScrollNever = 1 << 6,
|
VerticalScrollNever = 1 << 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
void create(uint style, uint width, uint height, const char *text = "");
|
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||||
uint get_text(char *text, uint length = -1U);
|
unsigned get_text(char *text, unsigned length = -1U);
|
||||||
void set_text(const char *text = "");
|
void set_text(const char *text = "");
|
||||||
|
|
||||||
|
nall::function<uintptr_t (event_t)> on_change;
|
||||||
|
|
||||||
Editbox();
|
Editbox();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -457,17 +462,17 @@ public:
|
|||||||
VerticalScrollNever = 1 << 5,
|
VerticalScrollNever = 1 << 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
void create(uint style, uint width, uint height, const char *columns = "", const char *text = "");
|
void create(unsigned style, unsigned width, unsigned height, const char *columns = "", const char *text = "");
|
||||||
void autosize_columns();
|
void autosize_columns();
|
||||||
void set_column_width(uint column, uint width);
|
void set_column_width(unsigned column, unsigned width);
|
||||||
void add_item(const char *text);
|
void add_item(const char *text);
|
||||||
void set_item(uint index, const char *text);
|
void set_item(unsigned index, const char *text);
|
||||||
int get_selection();
|
int get_selection();
|
||||||
void set_selection(int index);
|
void set_selection(int index);
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
nall::function<uintptr_t (Event)> on_change;
|
nall::function<uintptr_t (event_t)> on_change;
|
||||||
nall::function<uintptr_t (Event)> on_activate;
|
nall::function<uintptr_t (event_t)> on_activate;
|
||||||
|
|
||||||
Listbox();
|
Listbox();
|
||||||
|
|
||||||
@@ -478,13 +483,13 @@ private:
|
|||||||
|
|
||||||
class Combobox : private nall::base_from_member<pCombobox&>, public FormControl {
|
class Combobox : private nall::base_from_member<pCombobox&>, public FormControl {
|
||||||
public:
|
public:
|
||||||
void create(uint style, uint width, uint height, const char *text = "");
|
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||||
void add_item(const char *text);
|
void add_item(const char *text);
|
||||||
int get_selection();
|
int get_selection();
|
||||||
void set_selection(int index);
|
void set_selection(int index);
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
nall::function<uintptr_t (Event)> on_change;
|
nall::function<uintptr_t (event_t)> on_change;
|
||||||
|
|
||||||
Combobox();
|
Combobox();
|
||||||
|
|
||||||
@@ -495,9 +500,9 @@ private:
|
|||||||
|
|
||||||
class Progressbar : private nall::base_from_member<pProgressbar&>, public FormControl {
|
class Progressbar : private nall::base_from_member<pProgressbar&>, public FormControl {
|
||||||
public:
|
public:
|
||||||
void create(uint style, uint width, uint height);
|
void create(unsigned style, unsigned width, unsigned height);
|
||||||
uint get_progress();
|
unsigned get_progress();
|
||||||
void set_progress(uint progress);
|
void set_progress(unsigned progress);
|
||||||
|
|
||||||
Progressbar();
|
Progressbar();
|
||||||
|
|
||||||
@@ -513,11 +518,11 @@ public:
|
|||||||
Vertical = 1 << 1,
|
Vertical = 1 << 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
void create(uint style, uint width, uint height, uint length);
|
void create(unsigned style, unsigned width, unsigned height, unsigned length);
|
||||||
uint get_position();
|
unsigned get_position();
|
||||||
void set_position(uint position);
|
void set_position(unsigned position);
|
||||||
|
|
||||||
nall::function<uintptr_t (Event)> on_change;
|
nall::function<uintptr_t (event_t)> on_change;
|
||||||
|
|
||||||
Slider();
|
Slider();
|
||||||
|
|
@@ -1,237 +0,0 @@
|
|||||||
#include "../hiro.h"
|
|
||||||
using namespace libhiro;
|
|
||||||
|
|
||||||
#include <nall/algorithm.hpp>
|
|
||||||
using nall::min;
|
|
||||||
using nall::max;
|
|
||||||
|
|
||||||
bool kill_ = false;
|
|
||||||
|
|
||||||
uint32_t windowicon[16 * 16] = {
|
|
||||||
0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
|
|
||||||
0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
|
|
||||||
0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
|
|
||||||
0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
|
|
||||||
0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
|
|
||||||
0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
|
|
||||||
0xff000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
|
|
||||||
0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
|
|
||||||
0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
|
|
||||||
0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
|
|
||||||
0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
|
|
||||||
0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
|
|
||||||
0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
|
|
||||||
0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
|
|
||||||
0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
|
|
||||||
0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
|
|
||||||
};
|
|
||||||
|
|
||||||
class SubWindow : public Window {
|
|
||||||
public:
|
|
||||||
Button button;
|
|
||||||
|
|
||||||
uintptr_t tick(Event) {
|
|
||||||
hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
create(0, 595, 80);
|
|
||||||
|
|
||||||
button.create(0, 595, 80, "SubWindow (click to hide)");
|
|
||||||
button.on_tick = bind(&SubWindow::tick, this);
|
|
||||||
attach(button, 0, 0);
|
|
||||||
}
|
|
||||||
} subwindow;
|
|
||||||
|
|
||||||
class MainWindow : public Window {
|
|
||||||
public:
|
|
||||||
MenuGroup menu_file;
|
|
||||||
MenuGroup menu_file_disk;
|
|
||||||
MenuItem menu_file_disk_load;
|
|
||||||
MenuItem menu_file_disk_save;
|
|
||||||
MenuSeparator menu_file_separator;
|
|
||||||
MenuItem menu_file_exit;
|
|
||||||
MenuGroup menu_help;
|
|
||||||
MenuCheckItem menu_help_check1, menu_help_check2;
|
|
||||||
MenuSeparator menu_help_separator1;
|
|
||||||
MenuRadioItem menu_help_radio1, menu_help_radio2, menu_help_radio3;
|
|
||||||
MenuSeparator menu_help_separator2;
|
|
||||||
MenuItem menu_help_about;
|
|
||||||
Label label;
|
|
||||||
Editbox editbox, editbox_multi;
|
|
||||||
Button button_ok;
|
|
||||||
Button button_exit;
|
|
||||||
Checkbox check1, check2;
|
|
||||||
Radiobox radio1, radio2;
|
|
||||||
Progressbar progress;
|
|
||||||
Combobox combobox;
|
|
||||||
Listbox listbox;
|
|
||||||
Slider hslider, vslider;
|
|
||||||
Frame frame;
|
|
||||||
Canvas canvas;
|
|
||||||
|
|
||||||
uintptr_t change(Event e) {
|
|
||||||
printf("change(%d)\n", (uint)e.param);
|
|
||||||
}
|
|
||||||
|
|
||||||
uintptr_t activate(Event e) {
|
|
||||||
printf("activate(%d)\n", (uint)e.param);
|
|
||||||
}
|
|
||||||
|
|
||||||
uintptr_t tick(Event e) {
|
|
||||||
printf("tick(%d)\n", e.param);
|
|
||||||
if(e.widget == &button_ok) {
|
|
||||||
char t[4096];
|
|
||||||
editbox.get_text(t, 4096);
|
|
||||||
printf("'%s'\n", t);
|
|
||||||
}
|
|
||||||
if(e.widget == &menu_file_disk_load) {
|
|
||||||
char t[4096] = "";
|
|
||||||
hiro().file_open(0, t, "", "Source files\t*.cpp,*.h\nAll Files\t*.*");
|
|
||||||
printf("'%s'\n", t);
|
|
||||||
}
|
|
||||||
if(e.widget == &menu_file_disk_save) {
|
|
||||||
char t[4096] = "";
|
|
||||||
hiro().file_save(0, t, "", "Source files\t*.cpp,*.h\nAll Files\t*.*");
|
|
||||||
printf("'%s'\n", t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uintptr_t keydown(Event e) {
|
|
||||||
static bool fs = false;
|
|
||||||
if(e.param == nall::keyboard::f11) {
|
|
||||||
fs = !fs;
|
|
||||||
fs ? fullscreen() : unfullscreen();
|
|
||||||
printf("%d -> %4d, %4d\n", fs, get_width(), get_height());
|
|
||||||
} else if(e.param == nall::keyboard::escape) {
|
|
||||||
menu.show(!menu.visible());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uintptr_t close(Event) {
|
|
||||||
printf("close()\n");
|
|
||||||
return kill_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setup() {
|
|
||||||
create(Window::AutoCenter, 605, 320, "hiro test application");
|
|
||||||
//set_opacity(224);
|
|
||||||
//set_background_color(0, 0, 0);
|
|
||||||
set_icon(16, 16, windowicon);
|
|
||||||
|
|
||||||
attach(menu_file.create("File"));
|
|
||||||
menu_file.attach(menu_file_disk.create("Disk"));
|
|
||||||
menu_file_disk.attach(menu_file_disk_load.create("Load ..."));
|
|
||||||
menu_file_disk.attach(menu_file_disk_save.create("Save ..."));
|
|
||||||
menu_file.attach(menu_file_separator.create());
|
|
||||||
menu_file.attach(menu_file_exit.create("Exit"));
|
|
||||||
attach(menu_help.create("Help"));
|
|
||||||
menu_help.attach(menu_help_check1.create("Check 1"));
|
|
||||||
menu_help.attach(menu_help_check2.create("Check 2"));
|
|
||||||
menu_help.attach(menu_help_separator1.create());
|
|
||||||
{ MenuRadioItemGroup group;
|
|
||||||
group.add(&menu_help_radio1);
|
|
||||||
group.add(&menu_help_radio2);
|
|
||||||
group.add(&menu_help_radio3);
|
|
||||||
menu_help.attach(menu_help_radio1.create(group, "Radio 1"));
|
|
||||||
menu_help.attach(menu_help_radio2.create(group, "Radio 2"));
|
|
||||||
menu_help.attach(menu_help_radio3.create(group, "Radio 3"));
|
|
||||||
} menu_help.attach(menu_help_separator2.create());
|
|
||||||
menu_help.attach(menu_help_about.create("About ..."));
|
|
||||||
menu_help_about.disable();
|
|
||||||
label.create(0, 200, 35, "hiro test application\n~ byuu");
|
|
||||||
editbox.create(0, 200, 25);
|
|
||||||
button_ok.create(0, 100, 30, "Ok");
|
|
||||||
button_exit.create(0, 100, 30, "Exit");
|
|
||||||
editbox_multi.create(Editbox::Multiline | Editbox::VerticalScrollAlways, 200, 95);
|
|
||||||
check1.create(0, 100, 20, "Check 1");
|
|
||||||
check2.create(0, 100, 20, "Check 2");
|
|
||||||
{ RadioboxGroup group;
|
|
||||||
group.add(&radio1);
|
|
||||||
group.add(&radio2);
|
|
||||||
radio1.create(group, 0, 100, 20, "Radio 1");
|
|
||||||
radio2.create(group, 0, 100, 20, "Radio 2");
|
|
||||||
} progress.create(0, 200, 30);
|
|
||||||
progress.set_progress(50);
|
|
||||||
combobox.create(0, 200, 30);
|
|
||||||
combobox.add_item("Option 1");
|
|
||||||
combobox.add_item("Option 2");
|
|
||||||
combobox.add_item("Option 3");
|
|
||||||
listbox.create(Listbox::Header | Listbox::VerticalScrollAlways, 200, 100, "Name\tValue");
|
|
||||||
listbox.add_item("a\ttrue");
|
|
||||||
listbox.add_item("b\tfalse");
|
|
||||||
hslider.create(Slider::Horizontal, 425, 25, 10);
|
|
||||||
vslider.create(Slider::Vertical, 25, 200, 10);
|
|
||||||
frame.create(0, 155, 225, "Canvas:");
|
|
||||||
|
|
||||||
canvas.create(0, 135, 195);
|
|
||||||
for(uint y = 0; y < 195; y++) {
|
|
||||||
uint32_t *p = canvas.buffer() + y * 135;
|
|
||||||
for(uint x = 0; x < 135; x++) {
|
|
||||||
double dx = 128.0 / 135.0 * double(x);
|
|
||||||
double dy = 128.0 / 195.0 * double(y);
|
|
||||||
uint32_t c = uint32_t(dx) + uint32_t(dy);
|
|
||||||
*p++ = (max(0U, min(c, 255U)) ^ 0xff) << 16;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
status.show();
|
|
||||||
status.set_text("Statusbar");
|
|
||||||
|
|
||||||
on_close = bind(&MainWindow::close, this);
|
|
||||||
on_keydown = bind(&MainWindow::keydown, this);
|
|
||||||
|
|
||||||
menu_file_disk_load.on_tick =
|
|
||||||
menu_file_disk_save.on_tick = bind(&MainWindow::tick, this);
|
|
||||||
menu_file_exit.on_tick = on_close;
|
|
||||||
menu_help_check1.on_tick = menu_help_check2.on_tick =
|
|
||||||
menu_help_radio1.on_tick = menu_help_radio2.on_tick =
|
|
||||||
menu_help_radio3.on_tick = bind(&MainWindow::tick, this);
|
|
||||||
menu_help_about.on_tick = bind(&MainWindow::tick, this);
|
|
||||||
button_ok.on_tick = bind(&MainWindow::tick, this);
|
|
||||||
button_exit.on_tick = bind(&MainWindow::close, this);
|
|
||||||
check1.on_tick = check2.on_tick =
|
|
||||||
radio1.on_tick = radio2.on_tick = bind(&MainWindow::tick, this);
|
|
||||||
combobox.on_change = bind(&MainWindow::change, this);
|
|
||||||
listbox.on_change = bind(&MainWindow::change, this);
|
|
||||||
listbox.on_activate = bind(&MainWindow::activate, this);
|
|
||||||
hslider.on_change = bind(&MainWindow::change, this);
|
|
||||||
vslider.on_change = bind(&MainWindow::change, this);
|
|
||||||
|
|
||||||
attach(label, 5, 5);
|
|
||||||
attach(editbox, 5, 40);
|
|
||||||
attach(button_ok, 5, 70);
|
|
||||||
attach(button_exit, 105, 70);
|
|
||||||
attach(editbox_multi, 210, 5);
|
|
||||||
attach(check1, 5, 105);
|
|
||||||
attach(check2, 105, 105);
|
|
||||||
attach(radio1, 5, 125);
|
|
||||||
attach(radio2, 105, 125);
|
|
||||||
attach(progress, 5, 145);
|
|
||||||
attach(combobox, 5, 175);
|
|
||||||
attach(listbox, 210, 105);
|
|
||||||
attach(hslider, 5, 205);
|
|
||||||
attach(vslider, 415, 5);
|
|
||||||
|
|
||||||
attach(frame, 445, 5);
|
|
||||||
attach(canvas, 455, 25);
|
|
||||||
|
|
||||||
attach(subwindow, 5, 235);
|
|
||||||
}
|
|
||||||
} window;
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
hiro().init();
|
|
||||||
hiro().disable_screensaver();
|
|
||||||
|
|
||||||
subwindow.setup();
|
|
||||||
window.setup();
|
|
||||||
window.show();
|
|
||||||
|
|
||||||
window.check1.check();
|
|
||||||
|
|
||||||
while(kill_ == false) hiro().run();
|
|
||||||
|
|
||||||
hiro().term();
|
|
||||||
return 0;
|
|
||||||
}
|
|
@@ -1,4 +1,4 @@
|
|||||||
void pButton::create(uint style, uint width, uint height, const char *text) {
|
void pButton::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||||
hwnd = CreateWindow(L"BUTTON", utf16(text), WS_CHILD | WS_TABSTOP | WS_VISIBLE,
|
hwnd = CreateWindow(L"BUTTON", utf16(text), WS_CHILD | WS_TABSTOP | WS_VISIBLE,
|
||||||
0, 0, width, height,
|
0, 0, width, height,
|
||||||
phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
class pButton : public pFormControl {
|
class pButton : public pFormControl {
|
||||||
public:
|
public:
|
||||||
Button &self;
|
Button &self;
|
||||||
void create(uint style, uint width, uint height, const char *text = "");
|
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||||
void set_text(const char *text = "");
|
void set_text(const char *text = "");
|
||||||
|
|
||||||
pButton(Button&);
|
pButton(Button&);
|
@@ -1,4 +1,4 @@
|
|||||||
void pCanvas::create(uint style, uint width, uint height) {
|
void pCanvas::create(unsigned style, unsigned width, unsigned height) {
|
||||||
hwnd = CreateWindow(L"hiro_window", L"", WS_CHILD,
|
hwnd = CreateWindow(L"hiro_window", L"", WS_CHILD,
|
||||||
0, 0, width, height,
|
0, 0, width, height,
|
||||||
phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
||||||
@@ -35,7 +35,7 @@ pCanvas::~pCanvas() {
|
|||||||
|
|
||||||
/* internal */
|
/* internal */
|
||||||
|
|
||||||
void pCanvas::resize(uint width, uint height) {
|
void pCanvas::resize(unsigned width, unsigned height) {
|
||||||
if(ibuffer) free(ibuffer);
|
if(ibuffer) free(ibuffer);
|
||||||
|
|
||||||
ipitch = width * sizeof(uint32_t);
|
ipitch = width * sizeof(uint32_t);
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
class pCanvas : public pFormControl {
|
class pCanvas : public pFormControl {
|
||||||
public:
|
public:
|
||||||
void create(uint style, uint width, uint height);
|
void create(unsigned style, unsigned width, unsigned height);
|
||||||
void redraw();
|
void redraw();
|
||||||
uint32_t* buffer();
|
uint32_t* buffer();
|
||||||
|
|
||||||
@@ -11,6 +11,6 @@ public:
|
|||||||
/* internal */
|
/* internal */
|
||||||
BITMAPINFO bmi;
|
BITMAPINFO bmi;
|
||||||
uint32_t *ibuffer;
|
uint32_t *ibuffer;
|
||||||
uint ipitch, iwidth, iheight;
|
unsigned ipitch, iwidth, iheight;
|
||||||
void resize(uint width, uint height);
|
void resize(unsigned width, unsigned height);
|
||||||
};
|
};
|
@@ -1,4 +1,4 @@
|
|||||||
void pCheckbox::create(uint style, uint width, uint height, const char *text) {
|
void pCheckbox::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||||
hwnd = CreateWindow(L"BUTTON", utf16(text), WS_CHILD | WS_TABSTOP | WS_VISIBLE | BS_CHECKBOX,
|
hwnd = CreateWindow(L"BUTTON", utf16(text), WS_CHILD | WS_TABSTOP | WS_VISIBLE | BS_CHECKBOX,
|
||||||
0, 0, width, height,
|
0, 0, width, height,
|
||||||
phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
class pCheckbox : public pFormControl {
|
class pCheckbox : public pFormControl {
|
||||||
public:
|
public:
|
||||||
void create(uint style, uint width, uint height, const char *text = "");
|
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||||
void set_text(const char *text = "");
|
void set_text(const char *text = "");
|
||||||
void check(bool state = true);
|
void check(bool state = true);
|
||||||
void uncheck();
|
void uncheck();
|
@@ -1,4 +1,4 @@
|
|||||||
void pCombobox::create(uint style, uint width, uint height, const char *text) {
|
void pCombobox::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||||
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, L"COMBOBOX", L"",
|
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, L"COMBOBOX", L"",
|
||||||
WS_CHILD | WS_TABSTOP | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS,
|
WS_CHILD | WS_TABSTOP | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS,
|
||||||
0, 0, width, 200,
|
0, 0, width, 200,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
class pCombobox : public pFormControl {
|
class pCombobox : public pFormControl {
|
||||||
public:
|
public:
|
||||||
Combobox &self;
|
Combobox &self;
|
||||||
void create(uint style, uint width, uint height, const char *text = "");
|
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||||
void add_item(const char *text);
|
void add_item(const char *text);
|
||||||
int get_selection();
|
int get_selection();
|
||||||
void set_selection(int index);
|
void set_selection(int index);
|
@@ -1,12 +1,12 @@
|
|||||||
void pEditbox::create(uint style, uint width, uint height, const char *text) {
|
void pEditbox::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||||
bool multiline = style & Editbox::Multiline;
|
bool multiline = style & Editbox::Multiline;
|
||||||
bool readonly = style & Editbox::Readonly;
|
bool readonly = style & Editbox::Readonly;
|
||||||
uint vscroll = (style & Editbox::VerticalScrollAlways) ? WS_VSCROLL :
|
unsigned vscroll = (style & Editbox::VerticalScrollAlways) ? WS_VSCROLL :
|
||||||
(style & Editbox::VerticalScrollNever) ? 0 :
|
(style & Editbox::VerticalScrollNever) ? 0 :
|
||||||
ES_AUTOVSCROLL;
|
ES_AUTOVSCROLL;
|
||||||
uint hscroll = (style & Editbox::HorizontalScrollAlways) ? WS_HSCROLL :
|
unsigned hscroll = (style & Editbox::HorizontalScrollAlways) ? WS_HSCROLL :
|
||||||
(style & Editbox::HorizontalScrollNever) ? 0 :
|
(style & Editbox::HorizontalScrollNever) ? 0 :
|
||||||
ES_AUTOHSCROLL;
|
ES_AUTOHSCROLL;
|
||||||
|
|
||||||
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, L"EDIT", L"",
|
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, L"EDIT", L"",
|
||||||
WS_CHILD | WS_VISIBLE | vscroll | hscroll |
|
WS_CHILD | WS_VISIBLE | vscroll | hscroll |
|
||||||
@@ -25,10 +25,11 @@ void pEditbox::set_text(const char *text) {
|
|||||||
SetWindowText(hwnd, utf16(temp));
|
SetWindowText(hwnd, utf16(temp));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint pEditbox::get_text(char *text, uint length) {
|
unsigned pEditbox::get_text(char *text, unsigned length) {
|
||||||
wchar_t buffer[length * 2 + 1];
|
wchar_t *buffer = new wchar_t[length + 1];
|
||||||
GetWindowText(hwnd, buffer, length * 2);
|
GetWindowText(hwnd, buffer, length);
|
||||||
string temp = (const char*)utf8(buffer);
|
string temp = (const char*)utf8(buffer);
|
||||||
|
delete[] buffer;
|
||||||
replace(temp, "\r", "");
|
replace(temp, "\r", "");
|
||||||
strlcpy(text, temp, length);
|
strlcpy(text, temp, length);
|
||||||
return strlen(text);
|
return strlen(text);
|
||||||
|
@@ -1,9 +0,0 @@
|
|||||||
class pEditbox : public pFormControl {
|
|
||||||
public:
|
|
||||||
Editbox &self;
|
|
||||||
void create(uint style, uint width, uint height, const char *text = "");
|
|
||||||
uint get_text(char *text, uint length = -1U);
|
|
||||||
void set_text(const char *text = "");
|
|
||||||
|
|
||||||
pEditbox(Editbox&);
|
|
||||||
};
|
|
9
src/lib/hiro/win/editbox.hpp
Normal file
9
src/lib/hiro/win/editbox.hpp
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
class pEditbox : public pFormControl {
|
||||||
|
public:
|
||||||
|
Editbox &self;
|
||||||
|
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||||
|
unsigned get_text(char *text, unsigned length = -1U);
|
||||||
|
void set_text(const char *text = "");
|
||||||
|
|
||||||
|
pEditbox(Editbox&);
|
||||||
|
};
|
@@ -1,4 +1,4 @@
|
|||||||
void pFormControl::resize(uint width, uint height) {
|
void pFormControl::resize(unsigned width, unsigned height) {
|
||||||
SetWindowPos(hwnd, 0, 0, 0, width, height, SWP_NOZORDER | SWP_NOMOVE);
|
SetWindowPos(hwnd, 0, 0, 0, width, height, SWP_NOZORDER | SWP_NOMOVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
class pFormControl : public pWidget {
|
class pFormControl : public pWidget {
|
||||||
public:
|
public:
|
||||||
virtual void resize(uint width, uint height);
|
virtual void resize(unsigned width, unsigned height);
|
||||||
void focus();
|
void focus();
|
||||||
bool focused();
|
bool focused();
|
||||||
void enable(bool = true);
|
void enable(bool = true);
|
@@ -1,4 +1,4 @@
|
|||||||
void pFrame::create(uint style, uint width, uint height, const char *text) {
|
void pFrame::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||||
hwnd = CreateWindow(L"BUTTON", utf16(text), WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
|
hwnd = CreateWindow(L"BUTTON", utf16(text), WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
|
||||||
0, 0, width, height,
|
0, 0, width, height,
|
||||||
phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
class pFrame : public pFormControl {
|
class pFrame : public pFormControl {
|
||||||
public:
|
public:
|
||||||
Frame &self;
|
Frame &self;
|
||||||
void create(uint style, uint width, uint height, const char *text = "");
|
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||||
void set_text(const char *text = "");
|
void set_text(const char *text = "");
|
||||||
|
|
||||||
pFrame(Frame&);
|
pFrame(Frame&);
|
@@ -1,14 +1,10 @@
|
|||||||
#include "hiro.h"
|
#include "hiro.hpp"
|
||||||
|
#include "port.cpp"
|
||||||
#include <nall/algorithm.hpp>
|
|
||||||
using nall::min;
|
|
||||||
using nall::max;
|
|
||||||
|
|
||||||
namespace libhiro {
|
namespace libhiro {
|
||||||
|
|
||||||
LRESULT CALLBACK phiro_wndproc(HWND, UINT, WPARAM, LPARAM);
|
LRESULT CALLBACK phiro_wndproc(HWND, UINT, WPARAM, LPARAM);
|
||||||
|
|
||||||
#include "utf.cpp"
|
|
||||||
#include "keymap.cpp"
|
#include "keymap.cpp"
|
||||||
#include "widget.cpp"
|
#include "widget.cpp"
|
||||||
#include "window.cpp"
|
#include "window.cpp"
|
||||||
@@ -63,10 +59,14 @@ bool pHiro::run() {
|
|||||||
MSG msg;
|
MSG msg;
|
||||||
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
|
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
|
||||||
//TODO: IsDialogMessage() does not clear keyboard buffer, but is required for tab key to work ...
|
//TODO: IsDialogMessage() does not clear keyboard buffer, but is required for tab key to work ...
|
||||||
//if(!IsDialogMessage(GetParent(msg.hwnd) ? GetParent(msg.hwnd) : msg.hwnd, &msg)) {
|
#if defined(HIRO_WIN_TABSTOP)
|
||||||
|
if(!IsDialogMessage(GetParent(msg.hwnd) ? GetParent(msg.hwnd) : msg.hwnd, &msg)) {
|
||||||
|
#endif
|
||||||
TranslateMessage(&msg);
|
TranslateMessage(&msg);
|
||||||
DispatchMessage(&msg);
|
DispatchMessage(&msg);
|
||||||
//}
|
#if defined(HIRO_WIN_TABSTOP)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return pending();
|
return pending();
|
||||||
}
|
}
|
||||||
@@ -144,7 +144,7 @@ bool pHiro::file_open(Window *focus, char *filename, const char *path, const cha
|
|||||||
ofn.lpstrInitialDir = wdir;
|
ofn.lpstrInitialDir = wdir;
|
||||||
ofn.lpstrFile = wfilename;
|
ofn.lpstrFile = wfilename;
|
||||||
ofn.nMaxFile = MAX_PATH;
|
ofn.nMaxFile = MAX_PATH;
|
||||||
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST;
|
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
||||||
ofn.lpstrDefExt = L"";
|
ofn.lpstrDefExt = L"";
|
||||||
|
|
||||||
bool result = GetOpenFileName(&ofn);
|
bool result = GetOpenFileName(&ofn);
|
||||||
@@ -192,7 +192,7 @@ bool pHiro::file_save(Window *focus, char *filename, const char *path, const cha
|
|||||||
ofn.lpstrInitialDir = wdir;
|
ofn.lpstrInitialDir = wdir;
|
||||||
ofn.lpstrFile = wfilename;
|
ofn.lpstrFile = wfilename;
|
||||||
ofn.nMaxFile = MAX_PATH;
|
ofn.nMaxFile = MAX_PATH;
|
||||||
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST;
|
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
||||||
ofn.lpstrDefExt = L"";
|
ofn.lpstrDefExt = L"";
|
||||||
|
|
||||||
bool result = GetSaveFileName(&ofn);
|
bool result = GetSaveFileName(&ofn);
|
||||||
@@ -200,11 +200,11 @@ bool pHiro::file_save(Window *focus, char *filename, const char *path, const cha
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint pHiro::screen_width() {
|
unsigned pHiro::screen_width() {
|
||||||
return GetSystemMetrics(SM_CXSCREEN);
|
return GetSystemMetrics(SM_CXSCREEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint pHiro::screen_height() {
|
unsigned pHiro::screen_height() {
|
||||||
return GetSystemMetrics(SM_CYSCREEN);
|
return GetSystemMetrics(SM_CYSCREEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,7 +230,7 @@ pHiro& phiro() {
|
|||||||
|
|
||||||
/* internal */
|
/* internal */
|
||||||
|
|
||||||
HFONT pHiro::create_font(const char *name, uint size) {
|
HFONT pHiro::create_font(const char *name, unsigned size) {
|
||||||
return CreateFont(
|
return CreateFont(
|
||||||
-(size * 96.0 / 72.0 + 0.5), //96 = DPI
|
-(size * 96.0 / 72.0 + 0.5), //96 = DPI
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
@@ -238,9 +238,9 @@ HFONT pHiro::create_font(const char *name, uint size) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget* pHiro::get_widget(uint instance) {
|
Widget* pHiro::get_widget(unsigned instance) {
|
||||||
Widget *widget = 0;
|
Widget *widget = 0;
|
||||||
for(uint i = 0; i < widget_list.size(); i++) {
|
for(unsigned i = 0; i < widget_list.size(); i++) {
|
||||||
if(widget_list[i]->p.instance != instance) continue;
|
if(widget_list[i]->p.instance != instance) continue;
|
||||||
widget = widget_list[i];
|
widget = widget_list[i];
|
||||||
break;
|
break;
|
||||||
@@ -274,26 +274,42 @@ LRESULT pHiro::wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
|||||||
case WM_CLOSE: {
|
case WM_CLOSE: {
|
||||||
if(!p || p->self.type != Widget::WindowType) break;
|
if(!p || p->self.type != Widget::WindowType) break;
|
||||||
Window &w = ((pWindow*)p)->self;
|
Window &w = ((pWindow*)p)->self;
|
||||||
if(w.on_close) return (bool)w.on_close(Event(Event::Close, 0, &w));
|
if(w.on_close) return (bool)w.on_close(event_t(event_t::Close, 0, &w));
|
||||||
return TRUE; //true = destroy window
|
return TRUE; //true = destroy window
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case WM_ENTERMENULOOP: {
|
case WM_ENTERMENULOOP: {
|
||||||
if(!p || p->self.type != Widget::WindowType) break;
|
if(!p || p->self.type != Widget::WindowType) break;
|
||||||
Window &w = ((pWindow*)p)->self;
|
Window &w = ((pWindow*)p)->self;
|
||||||
if(w.on_block) w.on_block(Event(Event::Block, 0, &w));
|
if(w.on_block) w.on_block(event_t(event_t::Block, 0, &w));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case WM_KEYDOWN: {
|
case WM_KEYDOWN: {
|
||||||
if(!p || p->self.type != Widget::WindowType) break;
|
if(!p || p->self.type != Widget::WindowType) break;
|
||||||
Window &w = ((pWindow*)p)->self;
|
Window &w = ((pWindow*)p)->self;
|
||||||
if(w.on_keydown) w.on_keydown(Event(Event::KeyDown, translate_key(wparam), &w));
|
if(w.on_input) w.on_input(event_t(event_t::Input, translate_key(wparam) + (1 << 16), &w));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case WM_KEYUP: {
|
case WM_KEYUP: {
|
||||||
if(!p || p->self.type != Widget::WindowType) break;
|
if(!p || p->self.type != Widget::WindowType) break;
|
||||||
Window &w = ((pWindow*)p)->self;
|
Window &w = ((pWindow*)p)->self;
|
||||||
if(w.on_keyup) w.on_keyup(Event(Event::KeyUp, translate_key(wparam), &w));
|
if(w.on_input) w.on_input(event_t(event_t::Input, translate_key(wparam) + (0 << 16), &w));
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case WM_LBUTTONDOWN:
|
||||||
|
case WM_RBUTTONDOWN: {
|
||||||
|
if(!p || p->self.type != Widget::CanvasType) break;
|
||||||
|
Canvas &canvas = ((pCanvas*)p)->self;
|
||||||
|
uintptr_t param = (msg == WM_LBUTTONDOWN ? mouse::button + 0 : mouse::button + 1) + (1 << 16);
|
||||||
|
if(canvas.on_input) canvas.on_input(event_t(event_t::Input, param, &canvas));
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case WM_LBUTTONUP:
|
||||||
|
case WM_RBUTTONUP: {
|
||||||
|
if(!p || p->self.type != Widget::CanvasType) break;
|
||||||
|
Canvas &canvas = ((pCanvas*)p)->self;
|
||||||
|
uintptr_t param = (msg == WM_LBUTTONUP ? mouse::button + 0 : mouse::button + 1) + (0 << 16);
|
||||||
|
if(canvas.on_input) canvas.on_input(event_t(event_t::Input, param, &canvas));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case WM_ERASEBKGND: {
|
case WM_ERASEBKGND: {
|
||||||
@@ -322,39 +338,52 @@ LRESULT pHiro::wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
|||||||
switch(widget->type) {
|
switch(widget->type) {
|
||||||
case Widget::MenuItemType: {
|
case Widget::MenuItemType: {
|
||||||
MenuItem &w = (MenuItem&)*widget;
|
MenuItem &w = (MenuItem&)*widget;
|
||||||
if(w.on_tick) w.on_tick(Event(Event::Tick, 0, &w));
|
if(w.on_tick) w.on_tick(event_t(event_t::Tick, 0, &w));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Widget::MenuCheckItemType: {
|
case Widget::MenuCheckItemType: {
|
||||||
MenuCheckItem &w = (MenuCheckItem&)*widget;
|
MenuCheckItem &w = (MenuCheckItem&)*widget;
|
||||||
w.check(!w.checked()); //invert check state
|
w.check(!w.checked()); //invert check state
|
||||||
if(w.on_tick) w.on_tick(Event(Event::Tick, w.checked(), &w));
|
if(w.on_tick) w.on_tick(event_t(event_t::Tick, w.checked(), &w));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Widget::MenuRadioItemType: {
|
case Widget::MenuRadioItemType: {
|
||||||
MenuRadioItem &w = (MenuRadioItem&)*widget;
|
MenuRadioItem &w = (MenuRadioItem&)*widget;
|
||||||
bool checked = w.checked();
|
bool checked = w.checked();
|
||||||
w.check();
|
w.check();
|
||||||
if(!checked && w.on_tick) w.on_tick(Event(Event::Tick, w.checked(), &w));
|
if(!checked && w.on_tick) w.on_tick(event_t(event_t::Tick, w.checked(), &w));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Widget::ButtonType: {
|
case Widget::ButtonType: {
|
||||||
Button &w = (Button&)*widget;
|
Button &w = (Button&)*widget;
|
||||||
if(w.on_tick) w.on_tick(Event(Event::Tick, 0, &w));
|
if(w.on_tick) w.on_tick(event_t(event_t::Tick, 0, &w));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Widget::CheckboxType: {
|
case Widget::CheckboxType: {
|
||||||
Checkbox &w = (Checkbox&)*widget;
|
Checkbox &w = (Checkbox&)*widget;
|
||||||
w.check(!w.checked()); //invert check state
|
w.check(!w.checked()); //invert check state
|
||||||
if(w.on_tick) w.on_tick(Event(Event::Tick, w.checked(), &w));
|
if(w.on_tick) w.on_tick(event_t(event_t::Tick, w.checked(), &w));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Widget::RadioboxType: {
|
case Widget::RadioboxType: {
|
||||||
Radiobox &w = (Radiobox&)*widget;
|
Radiobox &w = (Radiobox&)*widget;
|
||||||
bool checked = w.checked();
|
bool checked = w.checked();
|
||||||
w.check();
|
w.check();
|
||||||
if(!checked && w.on_tick) w.on_tick(Event(Event::Tick, w.checked(), &w));
|
if(!checked && w.on_tick) w.on_tick(event_t(event_t::Tick, w.checked(), &w));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case Widget::EditboxType: {
|
||||||
|
Editbox &editbox = (Editbox&)*widget;
|
||||||
|
if(HIWORD(wparam) == EN_CHANGE) {
|
||||||
|
if(editbox.on_change) editbox.on_change(event_t(event_t::Change, 0, &editbox));
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
case Widget::ComboboxType: {
|
case Widget::ComboboxType: {
|
||||||
Combobox &combobox = (Combobox&)*widget;
|
Combobox &combobox = (Combobox&)*widget;
|
||||||
if(HIWORD(wparam) == CBN_SELCHANGE) {
|
if(HIWORD(wparam) == CBN_SELCHANGE) {
|
||||||
if(combobox.p.combobox_selection == combobox.get_selection()) break;
|
if(combobox.p.combobox_selection == combobox.get_selection()) break;
|
||||||
if(combobox.on_change) combobox.on_change(Event(Event::Change, combobox.p.combobox_selection = combobox.get_selection(), &combobox));
|
if(combobox.on_change) combobox.on_change(event_t(event_t::Change, combobox.p.combobox_selection = combobox.get_selection(), &combobox));
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
@@ -369,7 +398,7 @@ LRESULT pHiro::wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
|||||||
case Widget::SliderType: {
|
case Widget::SliderType: {
|
||||||
Slider &slider = (Slider&)*widget;
|
Slider &slider = (Slider&)*widget;
|
||||||
if(slider.p.slider_position == slider.get_position()) break;
|
if(slider.p.slider_position == slider.get_position()) break;
|
||||||
if(slider.on_change) slider.on_change(Event(Event::Change, slider.p.slider_position = slider.get_position(), &slider));
|
if(slider.on_change) slider.on_change(event_t(event_t::Change, slider.p.slider_position = slider.get_position(), &slider));
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@@ -381,14 +410,29 @@ LRESULT pHiro::wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
|||||||
switch(widget->type) {
|
switch(widget->type) {
|
||||||
case Widget::ListboxType: {
|
case Widget::ListboxType: {
|
||||||
Listbox &listbox = (Listbox&)*widget;
|
Listbox &listbox = (Listbox&)*widget;
|
||||||
if(((LPNMHDR)lparam)->code == LVN_ITEMCHANGED
|
LPNMHDR nmhdr = (LPNMHDR)lparam;
|
||||||
&& ((LPNMLISTVIEW)lparam)->uChanged & LVIF_STATE
|
LPNMLISTVIEW nmlistview = (LPNMLISTVIEW)lparam;
|
||||||
&& ListView_GetItemState(listbox.p.hwnd, ((LPNMLISTVIEW)lparam)->iItem, LVIS_FOCUSED)
|
|
||||||
&& ListView_GetItemState(listbox.p.hwnd, ((LPNMLISTVIEW)lparam)->iItem, LVIS_SELECTED)
|
if(nmhdr->code == LVN_ITEMCHANGED && (nmlistview->uChanged & LVIF_STATE)) {
|
||||||
) {
|
//LVN_ITEMCHANGED is sent whenever an item gains or loses either focus or selection;
|
||||||
if(listbox.on_change) listbox.on_change(Event(Event::Change, listbox.get_selection(), &listbox));
|
//it does not send a special message to indicate that no items are focused or selected.
|
||||||
} else if(((LPNMHDR)lparam)->code == LVN_ITEMACTIVATE) {
|
//it will send two messages when a different item gains selection -- the first to remove
|
||||||
if(listbox.on_activate) listbox.on_activate(Event(Event::Activate, listbox.get_selection(), &listbox));
|
//focus from the old item, the second to set selection to the new item.
|
||||||
|
//hiro sends only one message whenever an item changed (eg gained selection),
|
||||||
|
//including for deselection of all items. below code adapts win32 model to hiro model.
|
||||||
|
//(focused means an item has a dotted outline box around it, but is not highlighted.)
|
||||||
|
//(selected means an item is highlighted.)
|
||||||
|
if((nmlistview->uOldState & LVIS_FOCUSED) && !(nmlistview->uNewState & LVIS_FOCUSED)) {
|
||||||
|
listbox.p.lostfocus = true;
|
||||||
|
} else {
|
||||||
|
if((!(nmlistview->uOldState & LVIS_SELECTED) && (nmlistview->uNewState & LVIS_SELECTED))
|
||||||
|
|| (listbox.p.lostfocus == false && listbox.get_selection() == -1)) {
|
||||||
|
if(listbox.on_change) listbox.on_change(event_t(event_t::Change, listbox.get_selection(), &listbox));
|
||||||
|
}
|
||||||
|
listbox.p.lostfocus = false;
|
||||||
|
}
|
||||||
|
} else if(nmhdr->code == LVN_ITEMACTIVATE) {
|
||||||
|
if(listbox.on_activate) listbox.on_activate(event_t(event_t::Activate, listbox.get_selection(), &listbox));
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
@@ -5,39 +5,53 @@
|
|||||||
#undef _WIN32_WINNT
|
#undef _WIN32_WINNT
|
||||||
#undef _WIN32_IE
|
#undef _WIN32_IE
|
||||||
#undef NOMINMAX
|
#undef NOMINMAX
|
||||||
|
#undef _NO_OLDNAMES
|
||||||
|
|
||||||
#define WINVER 0x0501
|
#define WINVER 0x0501
|
||||||
#define _WIN32_WINNT 0x0501
|
#define _WIN32_WINNT 0x0501
|
||||||
#define _WIN32_IE 0x0600
|
#define _WIN32_IE 0x0600
|
||||||
#define NOMINMAX
|
#define NOMINMAX
|
||||||
|
#define _NO_OLDNAMES
|
||||||
|
|
||||||
#define UNICODE
|
#define UNICODE
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <commctrl.h>
|
#include <commctrl.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <direct.h>
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
|
|
||||||
|
#include <nall/algorithm.hpp>
|
||||||
|
using nall::min;
|
||||||
|
using nall::max;
|
||||||
|
|
||||||
|
#include <nall/utf8.hpp>
|
||||||
|
using nall::utf8;
|
||||||
|
using nall::utf16;
|
||||||
|
|
||||||
|
extern int hiromain(int argc, const char *const argv[]);
|
||||||
|
|
||||||
namespace libhiro {
|
namespace libhiro {
|
||||||
|
|
||||||
#include "widget.h"
|
#include "widget.hpp"
|
||||||
#include "window.h"
|
#include "window.hpp"
|
||||||
#include "menucontrol.h"
|
#include "menucontrol.hpp"
|
||||||
#include "menugroup.h"
|
#include "menugroup.hpp"
|
||||||
#include "menuitem.h"
|
#include "menuitem.hpp"
|
||||||
#include "menucheckitem.h"
|
#include "menucheckitem.hpp"
|
||||||
#include "menuradioitem.h"
|
#include "menuradioitem.hpp"
|
||||||
#include "menuseparator.h"
|
#include "menuseparator.hpp"
|
||||||
#include "formcontrol.h"
|
#include "formcontrol.hpp"
|
||||||
#include "frame.h"
|
#include "frame.hpp"
|
||||||
#include "canvas.h"
|
#include "canvas.hpp"
|
||||||
#include "label.h"
|
#include "label.hpp"
|
||||||
#include "button.h"
|
#include "button.hpp"
|
||||||
#include "checkbox.h"
|
#include "checkbox.hpp"
|
||||||
#include "radiobox.h"
|
#include "radiobox.hpp"
|
||||||
#include "editbox.h"
|
#include "editbox.hpp"
|
||||||
#include "listbox.h"
|
#include "listbox.hpp"
|
||||||
#include "combobox.h"
|
#include "combobox.hpp"
|
||||||
#include "progressbar.h"
|
#include "progressbar.hpp"
|
||||||
#include "slider.h"
|
#include "slider.hpp"
|
||||||
|
|
||||||
class pHiro {
|
class pHiro {
|
||||||
public:
|
public:
|
||||||
@@ -51,8 +65,8 @@ public:
|
|||||||
bool file_open(Window *focus, char *filename, const char *path = "", const char *filter = "");
|
bool file_open(Window *focus, char *filename, const char *path = "", const char *filter = "");
|
||||||
bool file_save(Window *focus, char *filename, const char *path = "", const char *filter = "");
|
bool file_save(Window *focus, char *filename, const char *path = "", const char *filter = "");
|
||||||
|
|
||||||
uint screen_width();
|
unsigned screen_width();
|
||||||
uint screen_height();
|
unsigned screen_height();
|
||||||
|
|
||||||
void enable_screensaver();
|
void enable_screensaver();
|
||||||
void disable_screensaver();
|
void disable_screensaver();
|
||||||
@@ -66,12 +80,12 @@ public:
|
|||||||
HWND default_hwnd; //default parent window for all windowless controls
|
HWND default_hwnd; //default parent window for all windowless controls
|
||||||
HFONT default_font; //default font for all controls
|
HFONT default_font; //default font for all controls
|
||||||
HBRUSH black_brush; //used for Canvas background
|
HBRUSH black_brush; //used for Canvas background
|
||||||
HFONT create_font(const char *name, uint size);
|
HFONT create_font(const char *name, unsigned size);
|
||||||
|
|
||||||
array<Widget*> widget_list;
|
array<Widget*> widget_list;
|
||||||
Widget* get_widget(uint instance);
|
Widget* get_widget(unsigned instance);
|
||||||
LRESULT wndproc(HWND, UINT, WPARAM, LPARAM);
|
LRESULT wndproc(HWND, UINT, WPARAM, LPARAM);
|
||||||
uint16_t translate_key(uint key);
|
uint16_t translate_key(unsigned key);
|
||||||
};
|
};
|
||||||
|
|
||||||
pHiro& phiro();
|
pHiro& phiro();
|
@@ -1,4 +1,4 @@
|
|||||||
uint16_t pHiro::translate_key(uint key) {
|
uint16_t pHiro::translate_key(unsigned key) {
|
||||||
switch(key) {
|
switch(key) {
|
||||||
case VK_ESCAPE: return keyboard::escape;
|
case VK_ESCAPE: return keyboard::escape;
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
void pLabel::create(uint style, uint width, uint height, const char *text) {
|
void pLabel::create(unsigned style, unsigned width, unsigned height, const char *text) {
|
||||||
hwnd = CreateWindow(L"STATIC", utf16(text), WS_CHILD | WS_VISIBLE,
|
hwnd = CreateWindow(L"STATIC", utf16(text), WS_CHILD | WS_VISIBLE,
|
||||||
0, 0, width, height,
|
0, 0, width, height,
|
||||||
phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
class pLabel : public pFormControl {
|
class pLabel : public pFormControl {
|
||||||
public:
|
public:
|
||||||
Label &self;
|
Label &self;
|
||||||
void create(uint style, uint width, uint height, const char *text = "");
|
void create(unsigned style, unsigned width, unsigned height, const char *text = "");
|
||||||
void set_text(const char *text = "");
|
void set_text(const char *text = "");
|
||||||
|
|
||||||
pLabel(Label&);
|
pLabel(Label&);
|
@@ -1,4 +1,4 @@
|
|||||||
void pListbox::create(uint style, uint width, uint height, const char *columns, const char *text) {
|
void pListbox::create(unsigned style, unsigned width, unsigned height, const char *columns, const char *text) {
|
||||||
bool header = style & Listbox::Header;
|
bool header = style & Listbox::Header;
|
||||||
unsigned hscroll = (style & Listbox::HorizontalScrollAlways) ? WS_HSCROLL :
|
unsigned hscroll = (style & Listbox::HorizontalScrollAlways) ? WS_HSCROLL :
|
||||||
(style & Listbox::HorizontalScrollNever) ? 0 :
|
(style & Listbox::HorizontalScrollNever) ? 0 :
|
||||||
@@ -41,7 +41,7 @@ void pListbox::autosize_columns() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListbox::set_column_width(uint column, uint width) {
|
void pListbox::set_column_width(unsigned column, unsigned width) {
|
||||||
ListView_SetColumnWidth(hwnd, column, width);
|
ListView_SetColumnWidth(hwnd, column, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ void pListbox::add_item(const char *text) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListbox::set_item(uint index, const char *text) {
|
void pListbox::set_item(unsigned index, const char *text) {
|
||||||
lstring list;
|
lstring list;
|
||||||
split(list, "\t", text ? text : "");
|
split(list, "\t", text ? text : "");
|
||||||
for(unsigned i = 0; i < count(list); i++) {
|
for(unsigned i = 0; i < count(list); i++) {
|
||||||
@@ -94,4 +94,5 @@ void pListbox::reset() {
|
|||||||
|
|
||||||
pListbox::pListbox(Listbox &self_) : pFormControl(self_), self(self_) {
|
pListbox::pListbox(Listbox &self_) : pFormControl(self_), self(self_) {
|
||||||
column_count = 0;
|
column_count = 0;
|
||||||
|
lostfocus = false; //used for message parsing
|
||||||
}
|
}
|
||||||
|
@@ -1,17 +0,0 @@
|
|||||||
class pListbox : public pFormControl {
|
|
||||||
public:
|
|
||||||
Listbox &self;
|
|
||||||
void create(uint style, uint width, uint height, const char *columns = "", const char *text = "");
|
|
||||||
void autosize_columns();
|
|
||||||
void set_column_width(uint column, uint width);
|
|
||||||
void add_item(const char *text);
|
|
||||||
void set_item(uint index, const char *text);
|
|
||||||
int get_selection();
|
|
||||||
void set_selection(int index);
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
pListbox(Listbox&);
|
|
||||||
|
|
||||||
/* internal */
|
|
||||||
uint column_count;
|
|
||||||
};
|
|
18
src/lib/hiro/win/listbox.hpp
Normal file
18
src/lib/hiro/win/listbox.hpp
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
class pListbox : public pFormControl {
|
||||||
|
public:
|
||||||
|
Listbox &self;
|
||||||
|
void create(unsigned style, unsigned width, unsigned height, const char *columns = "", const char *text = "");
|
||||||
|
void autosize_columns();
|
||||||
|
void set_column_width(unsigned column, unsigned width);
|
||||||
|
void add_item(const char *text);
|
||||||
|
void set_item(unsigned index, const char *text);
|
||||||
|
int get_selection();
|
||||||
|
void set_selection(int index);
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
pListbox(Listbox&);
|
||||||
|
|
||||||
|
/* internal */
|
||||||
|
unsigned column_count;
|
||||||
|
bool lostfocus;
|
||||||
|
};
|
@@ -19,5 +19,22 @@ bool pMenuCheckItem::checked() {
|
|||||||
return info.fState & MFS_CHECKED;
|
return info.fState & MFS_CHECKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pMenuCheckItem::enable(bool state) {
|
||||||
|
EnableMenuItem(parent, instance, MF_BYCOMMAND | (state ? MF_ENABLED : MF_GRAYED));
|
||||||
|
}
|
||||||
|
|
||||||
|
void pMenuCheckItem::disable() {
|
||||||
|
enable(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pMenuCheckItem::enabled() {
|
||||||
|
MENUITEMINFO info;
|
||||||
|
memset(&info, 0, sizeof info);
|
||||||
|
info.cbSize = sizeof info;
|
||||||
|
info.fMask = MIIM_STATE;
|
||||||
|
GetMenuItemInfo(parent, instance, false, &info);
|
||||||
|
return info.fState & MFS_ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
pMenuCheckItem::pMenuCheckItem(MenuCheckItem &self_) : pMenuControl(self_), self(self_) {
|
pMenuCheckItem::pMenuCheckItem(MenuCheckItem &self_) : pMenuControl(self_), self(self_) {
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,10 @@ public:
|
|||||||
void uncheck();
|
void uncheck();
|
||||||
bool checked();
|
bool checked();
|
||||||
|
|
||||||
|
void enable(bool = true);
|
||||||
|
void disable();
|
||||||
|
bool enabled();
|
||||||
|
|
||||||
MenuCheckItem &self;
|
MenuCheckItem &self;
|
||||||
pMenuCheckItem(MenuCheckItem&);
|
pMenuCheckItem(MenuCheckItem&);
|
||||||
};
|
};
|
@@ -1,18 +1,11 @@
|
|||||||
void pMenuControl::enable(bool state) {
|
void pMenuControl::enable(bool) {
|
||||||
EnableMenuItem(parent, instance, MF_BYCOMMAND | (state ? MF_ENABLED : MF_GRAYED));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pMenuControl::disable() {
|
void pMenuControl::disable() {
|
||||||
enable(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pMenuControl::enabled() {
|
bool pMenuControl::enabled() {
|
||||||
MENUITEMINFO info;
|
return true;
|
||||||
memset(&info, 0, sizeof info);
|
|
||||||
info.cbSize = sizeof info;
|
|
||||||
info.fMask = MIIM_STATE;
|
|
||||||
GetMenuItemInfo(parent, instance, false, &info);
|
|
||||||
return info.fState & MFS_ENABLED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pMenuControl::pMenuControl(MenuControl &self_) : pWidget(self_), self(self_) {
|
pMenuControl::pMenuControl(MenuControl &self_) : pWidget(self_), self(self_) {
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
class pMenuControl : public pWidget {
|
class pMenuControl : public pWidget {
|
||||||
public:
|
public:
|
||||||
void enable(bool = true);
|
virtual void enable(bool = true);
|
||||||
void disable();
|
virtual void disable();
|
||||||
bool enabled();
|
virtual bool enabled();
|
||||||
|
|
||||||
MenuControl &self;
|
MenuControl &self;
|
||||||
pMenuControl(MenuControl&);
|
pMenuControl(MenuControl&);
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user