mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-10-01 00:26:46 +02:00
Compare commits
31 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
0114e10ede | ||
|
8c591ce44a | ||
|
e2cc164f70 | ||
|
d09e54149b | ||
|
8e4f1be189 | ||
|
f529a84fd1 | ||
|
567d415290 | ||
|
435a194ccd | ||
|
df9de289b9 | ||
|
dd83559786 | ||
|
100ef3a271 | ||
|
bccc5b5a12 | ||
|
acee547da9 | ||
|
b1b146fd7d | ||
|
53e913e225 | ||
|
0cf16ce784 | ||
|
ce38d577ef | ||
|
0a87b99370 | ||
|
82d5761705 | ||
|
9133129209 | ||
|
7d83cde40a | ||
|
bbc77a6cf2 | ||
|
ebb9367c68 | ||
|
96fe8f760d | ||
|
8abd1b2dfe | ||
|
f6efcbe6fd | ||
|
36859ea52c | ||
|
64589148d4 | ||
|
89ae1101ee | ||
|
340d86845a | ||
|
b895f29bed |
10
license.txt
10
license.txt
@@ -53,21 +53,19 @@ information in the header. The lack of such a header indicates said file falls
|
|||||||
under the bsnes license.
|
under the bsnes license.
|
||||||
|
|
||||||
HQ2x filter, author: MaxST, license: LGPL
|
HQ2x filter, author: MaxST, license: LGPL
|
||||||
JMA decompressor, author: NSRT Team, license: GPL (*)
|
JMA decompressor, author: NSRT Team, license: GPL*
|
||||||
NTSC filter, author: blargg, license: LGPL
|
NTSC filter, author: blargg, license: LGPL
|
||||||
zlib decompressor, license: zlib license
|
zlib decompressor, license: zlib license
|
||||||
|
|
||||||
(*) bsnes has received an exemption from the copyright holder to use this work.
|
(* bsnes has received an exemption from the copyright holder to use this work.)
|
||||||
|
|
||||||
The software also includes works which have been released to the public domain,
|
The software also includes works which have been released to the public domain,
|
||||||
which are not bound to any licensing agreements. Below is a complete list of all
|
which are not bound to any licensing agreements. Below is a complete list of all
|
||||||
such software.
|
such software.
|
||||||
|
|
||||||
libco, author: byuu
|
libco, author: byuu
|
||||||
libui, author: byuu
|
S-DD1 decompressor, author: Andreas Naive
|
||||||
OBC-1 emu, author: byuu
|
SPC7110 decompressor, author: neviksti
|
||||||
S-DD1 emu, author: Andreas Naive
|
|
||||||
S-RTC emu, author: byuu
|
|
||||||
|
|
||||||
Any software listed above as exemptions may be relicensed individually from
|
Any software listed above as exemptions may be relicensed individually from
|
||||||
bsnes under their respective terms. However, no bsnes licensed portions can be
|
bsnes under their respective terms. However, no bsnes licensed portions can be
|
||||||
|
81
readme.txt
81
readme.txt
@@ -1,10 +1,11 @@
|
|||||||
bsnes
|
bsnes
|
||||||
Version: 0.031
|
Version: 0.036
|
||||||
Author: byuu
|
Author: byuu
|
||||||
|
|
||||||
--------
|
========
|
||||||
General:
|
General:
|
||||||
--------
|
========
|
||||||
|
|
||||||
bsnes is a Super Nintendo / Super Famicom emulator that began on
|
bsnes is a Super Nintendo / Super Famicom emulator that began on
|
||||||
October 14th, 2004.
|
October 14th, 2004.
|
||||||
|
|
||||||
@@ -13,11 +14,37 @@ http://byuu.org/
|
|||||||
|
|
||||||
Please see license.txt for important licensing information.
|
Please see license.txt for important licensing information.
|
||||||
|
|
||||||
------------------
|
==============
|
||||||
Known Limitations:
|
Configuration:
|
||||||
------------------
|
==============
|
||||||
|
|
||||||
|
bsnes has two configuration files: bsnes.cfg, for program settings; and
|
||||||
|
locale.cfg, for localization.
|
||||||
|
|
||||||
|
For each file, bsnes will start by looking inside the same folder where the
|
||||||
|
bsnes executable is located. If said file is not found, it will then check your
|
||||||
|
user profile folder. On Windows, this is located at "%APPDATA%/.bsnes". On all
|
||||||
|
other operating systems, this is located at "~/.bsnes". If said file is still
|
||||||
|
not found, it will automatically be created in your user profile folder.
|
||||||
|
|
||||||
|
If you wish to use bsnes in single-user mode, be sure that both files exist
|
||||||
|
inside the same folder as the bsnes executable. If they do not, you can simply
|
||||||
|
create new blank files and bsnes will use them in the future.
|
||||||
|
|
||||||
|
If you wish to use bsnes in multi-user mode, simply delete these two files from
|
||||||
|
the bsnes executable directory if they exist.
|
||||||
|
|
||||||
|
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
|
||||||
|
mode.
|
||||||
|
|
||||||
|
====================
|
||||||
|
Known Limitation(s):
|
||||||
|
====================
|
||||||
|
|
||||||
S-CPU
|
S-CPU
|
||||||
- Multiply / divide register delays not implemented
|
- Multiply / divide register delays not implemented
|
||||||
|
- "Glitch" when reading joypad registers during auto polling not implemented
|
||||||
|
|
||||||
S-PPU
|
S-PPU
|
||||||
- Uses scanline-based renderer. This is very inaccurate, but few (if any)
|
- Uses scanline-based renderer. This is very inaccurate, but few (if any)
|
||||||
@@ -33,9 +60,20 @@ 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:
|
||||||
---------------------
|
=====================
|
||||||
|
|
||||||
SA-1
|
SA-1
|
||||||
Coprocessor used in many popular games, including:
|
Coprocessor used in many popular games, including:
|
||||||
- Dragon Ball Z Hyper Dimension
|
- Dragon Ball Z Hyper Dimension
|
||||||
@@ -52,26 +90,27 @@ Coprocessor used in many popular games, including:
|
|||||||
- Star Fox 2 (unreleased beta)
|
- Star Fox 2 (unreleased beta)
|
||||||
- Super Mario World 2: Yoshi's Island
|
- Super Mario World 2: Yoshi's Island
|
||||||
|
|
||||||
SPC7110
|
|
||||||
Coprocessor used only by the following games:
|
|
||||||
- Far East of Eden Zero
|
|
||||||
- Far East of Eden Zero: Shounen Jump no Shou
|
|
||||||
- Momotarou Densetsu Happy
|
|
||||||
- Super Power League 4
|
|
||||||
|
|
||||||
ST-011
|
ST-011
|
||||||
SETA DSP used only by Quick-move Shogi Match with Nidan Rank-holder Morita
|
SETA DSP used by Quick-move Shogi Match with Nidan Rank-holder Morita
|
||||||
|
|
||||||
ST-018
|
ST-018
|
||||||
SETA RISC CPU used only by Quick-move Shogi Match with Nidan Rank-holder Morita 2
|
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:
|
Unsupported Controller(s):
|
||||||
------------------------
|
==========================
|
||||||
|
|
||||||
Mouse
|
Mouse
|
||||||
Super Scope
|
Super Scope
|
||||||
Justifier
|
Justifier
|
||||||
Multitap (4-port and 5-port)
|
|
||||||
|
=============
|
||||||
|
Contributors:
|
||||||
|
=============
|
||||||
|
|
||||||
|
Andreas Naive, anomie, blargg, DMV27, FitzRoy, GIGO, Jonas Quinn, kode54, krom,
|
||||||
|
mudlord, Nach, neviksti, Overload, RedDwarf, Richard Bannister, tetsuo55, TRAC,
|
||||||
|
zones
|
||||||
|
30
src/Makefile
30
src/Makefile
@@ -11,7 +11,7 @@ ifneq ($(findstring gcc,$(compiler)),) # GCC family
|
|||||||
cpp = $(subst cc,++,$(compiler)) $(flags)
|
cpp = $(subst cc,++,$(compiler)) $(flags)
|
||||||
obj = o
|
obj = o
|
||||||
rule = -c $< -o $@
|
rule = -c $< -o $@
|
||||||
link =
|
link = -s
|
||||||
mkbin = -o$1
|
mkbin = -o$1
|
||||||
mkdef = -D$1
|
mkdef = -D$1
|
||||||
mklib = -l$1
|
mklib = -l$1
|
||||||
@@ -34,7 +34,7 @@ endif
|
|||||||
##########
|
##########
|
||||||
|
|
||||||
ifeq ($(platform),x) # X11
|
ifeq ($(platform),x) # X11
|
||||||
ruby = video.glx video.xv video.sdl audio.openal audio.oss audio.ao input.sdl input.x
|
ruby = video.glx video.xv video.sdl audio.openal audio.oss audio.alsa audio.ao input.sdl input.x
|
||||||
link += `pkg-config --libs gtk+-2.0`
|
link += `pkg-config --libs gtk+-2.0`
|
||||||
link += $(call mklib,Xtst)
|
link += $(call mklib,Xtst)
|
||||||
delete = rm -f $1
|
delete = rm -f $1
|
||||||
@@ -66,6 +66,7 @@ link += $(if $(findstring video.directdraw,$(ruby)),$(call mklib,ddraw))
|
|||||||
link += $(if $(findstring video.glx,$(ruby)),$(call mklib,GL))
|
link += $(if $(findstring video.glx,$(ruby)),$(call mklib,GL))
|
||||||
link += $(if $(findstring video.wgl,$(ruby)),$(call mklib,opengl32))
|
link += $(if $(findstring video.wgl,$(ruby)),$(call mklib,opengl32))
|
||||||
link += $(if $(findstring video.xv,$(ruby)),$(call mklib,Xv))
|
link += $(if $(findstring video.xv,$(ruby)),$(call mklib,Xv))
|
||||||
|
link += $(if $(findstring audio.alsa,$(ruby)),$(call mklib,asound))
|
||||||
link += $(if $(findstring audio.ao,$(ruby)),$(call mklib,ao))
|
link += $(if $(findstring audio.ao,$(ruby)),$(call mklib,ao))
|
||||||
link += $(if $(findstring audio.directsound,$(ruby)),$(call mklib,dsound))
|
link += $(if $(findstring audio.directsound,$(ruby)),$(call mklib,dsound))
|
||||||
link += $(if $(findstring audio.openal,$(ruby)),$(if $(call streq,$(platform),x),$(call mklib,openal),$(call mklib,openal32)))
|
link += $(if $(findstring audio.openal,$(ruby)),$(if $(call streq,$(platform),x),$(call mklib,openal),$(call mklib,openal32)))
|
||||||
@@ -78,7 +79,7 @@ link += $(if $(findstring input.sdl,$(ruby)),`sdl-config --libs`)
|
|||||||
|
|
||||||
objects = main libco hiro ruby libfilter string reader cart cheat \
|
objects = main libco hiro ruby libfilter string reader cart cheat \
|
||||||
memory smemory cpu scpu smp ssmp sdsp ppu bppu snes \
|
memory smemory cpu scpu smp ssmp sdsp ppu bppu snes \
|
||||||
bsx srtc sdd1 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st010
|
bsx srtc sdd1 spc7110 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st010
|
||||||
|
|
||||||
ifeq ($(enable_gzip),true)
|
ifeq ($(enable_gzip),true)
|
||||||
objects += adler32 compress crc32 deflate gzio inffast inflate inftrees ioapi trees unzip zip zutil
|
objects += adler32 compress crc32 deflate gzio inffast inflate inftrees ioapi trees unzip zip zutil
|
||||||
@@ -132,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`))
|
||||||
@@ -195,16 +196,17 @@ obj/snes.$(obj): snes/snes.cpp snes/* snes/scheduler/* snes/video/* snes/audio/*
|
|||||||
### special chips ###
|
### special chips ###
|
||||||
#####################
|
#####################
|
||||||
|
|
||||||
obj/bsx.$(obj) : chip/bsx/bsx.cpp chip/bsx/*
|
obj/bsx.$(obj) : chip/bsx/bsx.cpp chip/bsx/*
|
||||||
obj/srtc.$(obj) : chip/srtc/srtc.cpp chip/srtc/*
|
obj/srtc.$(obj) : chip/srtc/srtc.cpp chip/srtc/*
|
||||||
obj/sdd1.$(obj) : chip/sdd1/sdd1.cpp chip/sdd1/*
|
obj/sdd1.$(obj) : chip/sdd1/sdd1.cpp chip/sdd1/*
|
||||||
obj/cx4.$(obj) : chip/cx4/cx4.cpp chip/cx4/*
|
obj/spc7110.$(obj): chip/spc7110/spc7110.cpp chip/spc7110/*
|
||||||
obj/dsp1.$(obj) : chip/dsp1/dsp1.cpp chip/dsp1/*
|
obj/cx4.$(obj) : chip/cx4/cx4.cpp chip/cx4/*
|
||||||
obj/dsp2.$(obj) : chip/dsp2/dsp2.cpp chip/dsp2/*
|
obj/dsp1.$(obj) : chip/dsp1/dsp1.cpp chip/dsp1/*
|
||||||
obj/dsp3.$(obj) : chip/dsp3/dsp3.cpp chip/dsp3/*
|
obj/dsp2.$(obj) : chip/dsp2/dsp2.cpp chip/dsp2/*
|
||||||
obj/dsp4.$(obj) : chip/dsp4/dsp4.cpp chip/dsp4/*
|
obj/dsp3.$(obj) : chip/dsp3/dsp3.cpp chip/dsp3/*
|
||||||
obj/obc1.$(obj) : chip/obc1/obc1.cpp chip/obc1/*
|
obj/dsp4.$(obj) : chip/dsp4/dsp4.cpp chip/dsp4/*
|
||||||
obj/st010.$(obj): chip/st010/st010.cpp chip/st010/*
|
obj/obc1.$(obj) : chip/obc1/obc1.cpp chip/obc1/*
|
||||||
|
obj/st010.$(obj) : chip/st010/st010.cpp chip/st010/*
|
||||||
|
|
||||||
############
|
############
|
||||||
### zlib ###
|
### zlib ###
|
||||||
|
22
src/base.h
22
src/base.h
@@ -1,4 +1,4 @@
|
|||||||
#define BSNES_VERSION "0.031"
|
#define BSNES_VERSION "0.036"
|
||||||
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
||||||
|
|
||||||
#define BUSCORE sBus
|
#define BUSCORE sBus
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
#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/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>
|
||||||
@@ -39,18 +40,11 @@ using namespace nall;
|
|||||||
//platform-specific global functions
|
//platform-specific global functions
|
||||||
void alert(const char*, ...);
|
void alert(const char*, ...);
|
||||||
void dprintf(const char*, ...);
|
void dprintf(const char*, ...);
|
||||||
void dprintf(uint, const char*, ...);
|
|
||||||
|
|
||||||
namespace source {
|
|
||||||
enum {
|
|
||||||
none = 0,
|
|
||||||
debug,
|
|
||||||
cpu,
|
|
||||||
ppu,
|
|
||||||
smp,
|
|
||||||
dsp,
|
|
||||||
bus,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
#include "interface.h"
|
#include "interface.h"
|
||||||
|
|
||||||
|
//helper: disable access to FILE, when possible (GZIP / JMA require it)
|
||||||
|
//reason: Windows fopen() does not support UTF-8 filenames; use nall::file instead.
|
||||||
|
#if !defined(GZIP_SUPPORT) && !defined(JMA_SUPPORT)
|
||||||
|
#define FILE FILE_deprecated
|
||||||
|
#endif
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
#include "cart_header.cpp"
|
#include "cart_header.cpp"
|
||||||
|
|
||||||
namespace memory {
|
namespace memory {
|
||||||
MappedRAM cartrom, cartram;
|
MappedRAM cartrom, cartram, cartrtc;
|
||||||
MappedRAM bscram;
|
MappedRAM bscram;
|
||||||
MappedRAM stArom, stAram;
|
MappedRAM stArom, stAram;
|
||||||
MappedRAM stBrom, stBram;
|
MappedRAM stBrom, stBram;
|
||||||
@@ -27,43 +27,44 @@ 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(CartridgeType cart_type) {
|
||||||
cart.rom = cart.ram = 0;
|
cart.rom = cart.ram = cart.rtc = 0;
|
||||||
bs.ram = 0;
|
bs.ram = 0;
|
||||||
stA.rom = stA.ram = 0;
|
stA.rom = stA.ram = 0;
|
||||||
stB.rom = stB.ram = 0;
|
stB.rom = stB.ram = 0;
|
||||||
|
|
||||||
cart.rom_size = cart.ram_size = 0;
|
cart.rom_size = cart.ram_size = cart.rtc_size = 0;
|
||||||
bs.ram_size = 0;
|
bs.ram_size = 0;
|
||||||
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.type = cart_type;
|
||||||
|
info.patched = false;
|
||||||
|
|
||||||
info.bsxbase = false;
|
info.bsxbase = false;
|
||||||
info.bsxcart = false;
|
info.bsxcart = false;
|
||||||
info.bsxflash = false;
|
info.bsxflash = false;
|
||||||
info.st = false;
|
info.st = false;
|
||||||
|
|
||||||
info.superfx = false;
|
info.superfx = false;
|
||||||
info.sa1 = false;
|
info.sa1 = false;
|
||||||
info.spc7110 = false;
|
info.srtc = false;
|
||||||
info.srtc = false;
|
info.sdd1 = false;
|
||||||
info.sdd1 = false;
|
info.spc7110 = false;
|
||||||
info.cx4 = false;
|
info.spc7110rtc = false;
|
||||||
info.dsp1 = false;
|
info.cx4 = false;
|
||||||
info.dsp2 = false;
|
info.dsp1 = false;
|
||||||
info.dsp3 = false;
|
info.dsp2 = false;
|
||||||
info.dsp4 = false;
|
info.dsp3 = false;
|
||||||
info.obc1 = false;
|
info.dsp4 = false;
|
||||||
info.st010 = false;
|
info.obc1 = false;
|
||||||
info.st011 = false;
|
info.st010 = false;
|
||||||
info.st018 = false;
|
info.st011 = false;
|
||||||
|
info.st018 = false;
|
||||||
|
|
||||||
info.dsp1_mapper = DSP1Unmapped;
|
info.dsp1_mapper = DSP1Unmapped;
|
||||||
|
|
||||||
info.header_index = 0xffc0;
|
info.header_index = 0xffc0;
|
||||||
info.mapper = LoROM;
|
info.mapper = LoROM;
|
||||||
info.name[0] = 0;
|
|
||||||
info.region = NTSC;
|
info.region = NTSC;
|
||||||
|
|
||||||
info.rom_size = 0;
|
info.rom_size = 0;
|
||||||
@@ -73,6 +74,7 @@ void Cartridge::load_begin(CartridgeType cart_type) {
|
|||||||
void Cartridge::load_end() {
|
void Cartridge::load_end() {
|
||||||
memory::cartrom.map(cart.rom, cart.rom_size);
|
memory::cartrom.map(cart.rom, cart.rom_size);
|
||||||
memory::cartram.map(cart.ram, cart.ram_size);
|
memory::cartram.map(cart.ram, cart.ram_size);
|
||||||
|
memory::cartrtc.map(cart.rtc, cart.rtc_size);
|
||||||
memory::bscram.map(bs.ram, bs.ram_size);
|
memory::bscram.map(bs.ram, bs.ram_size);
|
||||||
memory::stArom.map(stA.rom, stA.rom_size);
|
memory::stArom.map(stA.rom, stA.rom_size);
|
||||||
memory::stAram.map(stA.ram, stA.ram_size);
|
memory::stAram.map(stA.ram, stA.ram_size);
|
||||||
@@ -87,7 +89,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);
|
||||||
}
|
}
|
||||||
@@ -102,24 +104,25 @@ bool Cartridge::unload() {
|
|||||||
bus.unload_cart();
|
bus.unload_cart();
|
||||||
|
|
||||||
switch(info.type) {
|
switch(info.type) {
|
||||||
case CartridgeNormal: unload_cart_normal(); break;
|
case CartridgeNormal: unload_cart_normal(); break;
|
||||||
case CartridgeBSX: unload_cart_bsx(); break;
|
case CartridgeBSX: unload_cart_bsx(); break;
|
||||||
case CartridgeBSC: unload_cart_bsc(); break;
|
case CartridgeBSC: unload_cart_bsc(); break;
|
||||||
case CartridgeSufamiTurbo: unload_cart_st(); break;
|
case CartridgeSufamiTurbo: unload_cart_st(); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
safe_free(cart.rom);
|
if(cart.rom) { delete[] cart.rom; cart.rom = 0; }
|
||||||
safe_free(cart.ram);
|
if(cart.ram) { delete[] cart.ram; cart.ram = 0; }
|
||||||
safe_free(bs.ram);
|
if(cart.rtc) { delete[] cart.rtc; cart.rtc = 0; }
|
||||||
safe_free(stA.rom);
|
if(bs.ram) { delete[] bs.ram; bs.ram = 0; }
|
||||||
safe_free(stA.ram);
|
if(stA.rom) { delete[] stA.rom; stA.rom = 0; }
|
||||||
safe_free(stB.rom);
|
if(stA.ram) { delete[] stA.ram; stA.ram = 0; }
|
||||||
safe_free(stB.ram);
|
if(stB.rom) { delete[] stB.rom; stB.rom = 0; }
|
||||||
|
if(stB.ram) { delete[] stB.ram; stB.ram = 0; }
|
||||||
|
|
||||||
char fn[PATH_MAX];
|
char fn[PATH_MAX];
|
||||||
strcpy(fn, cart.fn);
|
strcpy(fn, cart.fn);
|
||||||
modify_extension(fn, "cht");
|
modify_extension(fn, "cht");
|
||||||
if(cheat.count() > 0 || fexists(get_cheat_filename(cart.fn, "cht"))) {
|
if(cheat.count() > 0 || file::exists(get_cheat_filename(cart.fn, "cht"))) {
|
||||||
cheat.save(cheatfn);
|
cheat.save(cheatfn);
|
||||||
cheat.clear();
|
cheat.clear();
|
||||||
}
|
}
|
||||||
|
@@ -18,8 +18,7 @@ public:
|
|||||||
VERSION = 0x1b,
|
VERSION = 0x1b,
|
||||||
ICKSUM = 0x1c,
|
ICKSUM = 0x1c,
|
||||||
CKSUM = 0x1e,
|
CKSUM = 0x1e,
|
||||||
RESL = 0x3c,
|
RESETV = 0x3c,
|
||||||
RESH = 0x3d,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Region {
|
enum Region {
|
||||||
@@ -32,6 +31,7 @@ public:
|
|||||||
HiROM,
|
HiROM,
|
||||||
ExLoROM,
|
ExLoROM,
|
||||||
ExHiROM,
|
ExHiROM,
|
||||||
|
SPC7110ROM,
|
||||||
BSXROM,
|
BSXROM,
|
||||||
BSCLoROM,
|
BSCLoROM,
|
||||||
BSCHiROM,
|
BSCHiROM,
|
||||||
@@ -48,8 +48,8 @@ public:
|
|||||||
struct {
|
struct {
|
||||||
bool loaded;
|
bool loaded;
|
||||||
char fn[PATH_MAX];
|
char fn[PATH_MAX];
|
||||||
uint8 *rom, *ram;
|
uint8 *rom, *ram, *rtc;
|
||||||
uint rom_size, ram_size;
|
uint rom_size, ram_size, rtc_size;
|
||||||
} cart;
|
} cart;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
@@ -69,7 +69,7 @@ public:
|
|||||||
|
|
||||||
uint32 crc32;
|
uint32 crc32;
|
||||||
char filename[PATH_MAX * 4];
|
char filename[PATH_MAX * 4];
|
||||||
char name[128];
|
bool patched;
|
||||||
|
|
||||||
Region region;
|
Region region;
|
||||||
MemoryMapper mapper;
|
MemoryMapper mapper;
|
||||||
@@ -85,6 +85,7 @@ public:
|
|||||||
bool srtc;
|
bool srtc;
|
||||||
bool sdd1;
|
bool sdd1;
|
||||||
bool spc7110;
|
bool spc7110;
|
||||||
|
bool spc7110rtc;
|
||||||
bool cx4;
|
bool cx4;
|
||||||
bool dsp1;
|
bool dsp1;
|
||||||
bool dsp2;
|
bool dsp2;
|
||||||
@@ -118,6 +119,7 @@ public:
|
|||||||
void load_end();
|
void load_end();
|
||||||
bool unload();
|
bool unload();
|
||||||
|
|
||||||
|
unsigned score_header(unsigned);
|
||||||
void find_header();
|
void find_header();
|
||||||
void read_header();
|
void read_header();
|
||||||
void read_extended_header();
|
void read_extended_header();
|
||||||
@@ -142,12 +144,13 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
char patchfn[PATH_MAX];
|
char patchfn[PATH_MAX];
|
||||||
char savefn[PATH_MAX];
|
char savefn[PATH_MAX];
|
||||||
|
char rtcfn[PATH_MAX];
|
||||||
char cheatfn[PATH_MAX];
|
char cheatfn[PATH_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace memory {
|
namespace memory {
|
||||||
extern MappedRAM cartrom, cartram;
|
extern MappedRAM cartrom, cartram, cartrtc;
|
||||||
extern MappedRAM bscram;
|
extern MappedRAM bscram;
|
||||||
extern MappedRAM stArom, stAram;
|
extern MappedRAM stArom, stAram;
|
||||||
extern MappedRAM stBrom, stBram;
|
extern MappedRAM stBrom, stBram;
|
||||||
|
@@ -14,7 +14,7 @@ void Cartridge::load_cart_bsc(const char *base, const char *slot) {
|
|||||||
|
|
||||||
if(load_file(get_patch_filename(cart.fn, "ups"), data, size, CompressionInspect) == true) {
|
if(load_file(get_patch_filename(cart.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||||
apply_patch(data, size, cart.rom, cart.rom_size);
|
apply_patch(data, size, cart.rom, cart.rom_size);
|
||||||
if(data) { free(data); data = 0; }
|
delete[] data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(*bs.fn) {
|
if(*bs.fn) {
|
||||||
@@ -23,7 +23,7 @@ void Cartridge::load_cart_bsc(const char *base, const char *slot) {
|
|||||||
bs.ram = data, bs.ram_size = size;
|
bs.ram = data, bs.ram_size = size;
|
||||||
if(load_file(get_patch_filename(bs.fn, "ups"), data, size, CompressionInspect) == true) {
|
if(load_file(get_patch_filename(bs.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||||
apply_patch(data, size, bs.ram, bs.ram_size);
|
apply_patch(data, size, bs.ram, bs.ram_size);
|
||||||
if(data) { free(data); data = 0; }
|
delete[] data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -35,12 +35,12 @@ void Cartridge::load_cart_bsc(const char *base, const char *slot) {
|
|||||||
info.region = NTSC;
|
info.region = NTSC;
|
||||||
|
|
||||||
if(info.ram_size > 0) {
|
if(info.ram_size > 0) {
|
||||||
cart.ram = (uint8*)malloc(cart.ram_size = info.ram_size);
|
cart.ram = new uint8_t[cart.ram_size = info.ram_size];
|
||||||
memset(cart.ram, 0xff, cart.ram_size);
|
memset(cart.ram, 0xff, cart.ram_size);
|
||||||
|
|
||||||
if(load_file(get_save_filename(cart.fn, "srm"), data, size, CompressionNone) == true) {
|
if(load_file(get_save_filename(cart.fn, "srm"), data, size, CompressionNone) == true) {
|
||||||
memcpy(cart.ram, data, min(size, cart.ram_size));
|
memcpy(cart.ram, data, min(size, cart.ram_size));
|
||||||
safe_free(data);
|
delete[] data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -20,7 +20,7 @@ void Cartridge::load_cart_bsx(const char *base, const char *slot) {
|
|||||||
|
|
||||||
if(load_file(get_patch_filename(cart.fn, "ups"), data, size, CompressionInspect) == true) {
|
if(load_file(get_patch_filename(cart.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||||
apply_patch(data, size, cart.rom, cart.rom_size);
|
apply_patch(data, size, cart.rom, cart.rom_size);
|
||||||
if(data) { free(data); data = 0; }
|
delete[] data;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(bsxcart.sram.handle (), 0x00, bsxcart.sram.size ());
|
memset(bsxcart.sram.handle (), 0x00, bsxcart.sram.size ());
|
||||||
@@ -28,12 +28,12 @@ void Cartridge::load_cart_bsx(const char *base, const char *slot) {
|
|||||||
|
|
||||||
if(load_file(get_save_filename(cart.fn, "srm"), data, size, CompressionNone) == true) {
|
if(load_file(get_save_filename(cart.fn, "srm"), data, size, CompressionNone) == true) {
|
||||||
memcpy(bsxcart.sram.handle (), data, min(bsxcart.sram.size (), size));
|
memcpy(bsxcart.sram.handle (), data, min(bsxcart.sram.size (), size));
|
||||||
safe_free(data);
|
delete[] data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(load_file(get_save_filename(cart.fn, "psr"), data, size, CompressionNone) == true) {
|
if(load_file(get_save_filename(cart.fn, "psr"), data, size, CompressionNone) == true) {
|
||||||
memcpy(bsxcart.psram.handle(), data, min(bsxcart.psram.size(), size));
|
memcpy(bsxcart.psram.handle(), data, min(bsxcart.psram.size(), size));
|
||||||
safe_free(data);
|
delete[] data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(*bs.fn) {
|
if(*bs.fn) {
|
||||||
@@ -42,7 +42,7 @@ void Cartridge::load_cart_bsx(const char *base, const char *slot) {
|
|||||||
bs.ram = data, bs.ram_size = size;
|
bs.ram = data, bs.ram_size = size;
|
||||||
if(load_file(get_patch_filename(bs.fn, "ups"), data, size, CompressionInspect) == true) {
|
if(load_file(get_patch_filename(bs.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||||
apply_patch(data, size, bs.ram, bs.ram_size);
|
apply_patch(data, size, bs.ram, bs.ram_size);
|
||||||
if(data) { free(data); data = 0; }
|
delete[] data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,27 +1,27 @@
|
|||||||
#ifdef CART_CPP
|
#ifdef CART_CPP
|
||||||
|
|
||||||
#include "../reader/filereader.h"
|
#include "../reader/filereader.h"
|
||||||
|
|
||||||
#if defined(GZIP_SUPPORT)
|
#if defined(GZIP_SUPPORT)
|
||||||
#include "../reader/gzreader.h"
|
#include "../reader/gzreader.h"
|
||||||
#include "../reader/zipreader.h"
|
#include "../reader/zipreader.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(JMA_SUPPORT)
|
#if defined(JMA_SUPPORT)
|
||||||
#include "../reader/jmareader.h"
|
#include "../reader/jmareader.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char* Cartridge::modify_extension(char *filename, const char *extension) {
|
char* Cartridge::modify_extension(char *filename, const char *extension) {
|
||||||
int i;
|
int i;
|
||||||
for(i = strlen(filename); i >= 0; i--) {
|
for(i = strlen(filename); i >= 0; i--) {
|
||||||
if(filename[i] == '.') break;
|
if(filename[i] == '.') break;
|
||||||
if(filename[i] == '/') break;
|
if(filename[i] == '/') break;
|
||||||
if(filename[i] == '\\') break;
|
if(filename[i] == '\\') break;
|
||||||
}
|
}
|
||||||
if(i > 0 && filename[i] == '.') filename[i] = 0;
|
if(i > 0 && filename[i] == '.') filename[i] = 0;
|
||||||
strcat(filename, ".");
|
strcat(filename, ".");
|
||||||
strcat(filename, extension);
|
strcat(filename, extension);
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
//remove directory information and file extension ("/foo/bar.ext" -> "bar")
|
//remove directory information and file extension ("/foo/bar.ext" -> "bar")
|
||||||
@@ -47,36 +47,38 @@ 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) {
|
}
|
||||||
strcpy(filename, source);
|
|
||||||
for(char *p = filename; *p; p++) { if(*p == '\\') *p = '/'; }
|
char* Cartridge::get_path_filename(char *filename, const char *path, const char *source, const char *extension) {
|
||||||
|
strcpy(filename, source);
|
||||||
|
for(char *p = filename; *p; p++) { if(*p == '\\') *p = '/'; }
|
||||||
modify_extension(filename, extension);
|
modify_extension(filename, extension);
|
||||||
|
|
||||||
//override path with user-specified folder, if one was defined
|
//override path with user-specified folder, if one was defined
|
||||||
if(*path) {
|
if(*path) {
|
||||||
lstring part;
|
lstring part;
|
||||||
split(part, "/", filename);
|
split(part, "/", filename);
|
||||||
string fn = path;
|
string fn = path;
|
||||||
if(strend(fn, "/") == false) strcat(fn, "/");
|
if(strend(fn, "/") == false) strcat(fn, "/");
|
||||||
strcat(fn, part[count(part) - 1]);
|
strcat(fn, part[count(part) - 1]);
|
||||||
strcpy(filename, fn);
|
strcpy(filename, fn);
|
||||||
|
|
||||||
//resolve relative path, if found
|
//resolve relative path, if found
|
||||||
if(strbegin(fn, "./") == true) {
|
if(strbegin(fn, "./") == true) {
|
||||||
ltrim(fn, "./");
|
ltrim(fn, "./");
|
||||||
strcpy(filename, config::path.base);
|
strcpy(filename, config::path.base);
|
||||||
strcat(filename, fn);
|
strcat(filename, fn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* Cartridge::get_patch_filename(const char *source, const char *extension) {
|
char* Cartridge::get_patch_filename(const char *source, const char *extension) {
|
||||||
return get_path_filename(patchfn, config::path.patch, source, extension);
|
return get_path_filename(patchfn, config::path.patch, source, extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
char* Cartridge::get_save_filename(const char *source, const char *extension) {
|
char* Cartridge::get_save_filename(const char *source, const char *extension) {
|
||||||
return get_path_filename(savefn, config::path.save, source, extension);
|
return get_path_filename(savefn, config::path.save, source, extension);
|
||||||
@@ -85,63 +87,65 @@ char* Cartridge::get_save_filename(const char *source, const char *extension) {
|
|||||||
char* Cartridge::get_cheat_filename(const char *source, const char *extension) {
|
char* Cartridge::get_cheat_filename(const char *source, const char *extension) {
|
||||||
return get_path_filename(cheatfn, config::path.cheat, source, extension);
|
return get_path_filename(cheatfn, config::path.cheat, source, 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) {
|
||||||
dprintf("* Loading \"%s\" ...", fn);
|
if(file::exists(fn) == false) return false;
|
||||||
|
|
||||||
if(fexists(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);
|
||||||
if(compression == CompressionAuto) filetype = Reader::detect(fn, config::file.autodetect_type);
|
if(compression == CompressionAuto) filetype = Reader::detect(fn, config::file.autodetect_type);
|
||||||
|
|
||||||
switch(filetype) {
|
switch(filetype) {
|
||||||
default:
|
default:
|
||||||
dprintf("* Warning: filetype detected as unsupported compression type.");
|
dprintf("* Warning: filetype detected as unsupported compression type.");
|
||||||
dprintf("* Will attempt to load as uncompressed file -- may fail.");
|
dprintf("* Will attempt to load as uncompressed file -- may fail.");
|
||||||
case Reader::Normal: {
|
case Reader::Normal: {
|
||||||
FileReader ff(fn);
|
FileReader ff(fn);
|
||||||
if(!ff.ready()) {
|
if(!ff.ready()) {
|
||||||
alert("Error loading image file (%s)!", fn);
|
alert("Error loading image file (%s)!", fn);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
size = ff.size();
|
size = ff.size();
|
||||||
data = ff.read();
|
data = ff.read();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
#ifdef GZIP_SUPPORT
|
#ifdef GZIP_SUPPORT
|
||||||
case Reader::GZIP: {
|
case Reader::GZIP: {
|
||||||
GZReader gf(fn);
|
GZReader gf(fn);
|
||||||
if(!gf.ready()) {
|
if(!gf.ready()) {
|
||||||
alert("Error loading image file (%s)!", fn);
|
alert("Error loading image file (%s)!", fn);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
size = gf.size();
|
size = gf.size();
|
||||||
data = gf.read();
|
data = gf.read();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Reader::ZIP: {
|
case Reader::ZIP: {
|
||||||
ZipReader zf(fn);
|
ZipReader zf(fn);
|
||||||
size = zf.size();
|
if(!zf.ready()) {
|
||||||
data = zf.read();
|
alert("Error loading image file (%s)!", fn);
|
||||||
} break;
|
return false;
|
||||||
#endif
|
}
|
||||||
|
size = zf.size();
|
||||||
#ifdef JMA_SUPPORT
|
data = zf.read();
|
||||||
case Reader::JMA: {
|
} break;
|
||||||
try {
|
#endif
|
||||||
JMAReader jf(fn);
|
|
||||||
size = jf.size();
|
#ifdef JMA_SUPPORT
|
||||||
data = jf.read();
|
case Reader::JMA: {
|
||||||
} catch(JMA::jma_errors jma_error) {
|
try {
|
||||||
alert("Error loading image file (%s)!", fn);
|
JMAReader jf(fn);
|
||||||
return false;
|
size = jf.size();
|
||||||
}
|
data = jf.read();
|
||||||
} break;
|
} catch(JMA::jma_errors jma_error) {
|
||||||
#endif
|
alert("Error loading image file (%s)!", fn);
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
return true;
|
} break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Cartridge::apply_patch(const uint8_t *pdata, const unsigned psize, uint8_t *&data, unsigned &size) {
|
bool Cartridge::apply_patch(const uint8_t *pdata, const unsigned psize, uint8_t *&data, unsigned &size) {
|
||||||
@@ -157,22 +161,23 @@ 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) {
|
||||||
free(data);
|
delete[] data;
|
||||||
data = (uint8_t*)malloc(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) {
|
|
||||||
FileWriter ff(fn);
|
bool Cartridge::save_file(const char *fn, uint8 *data, uint size) {
|
||||||
if(!ff.ready())return false;
|
file fp;
|
||||||
ff.write(data, size);
|
if(!fp.open(fn, file::mode_write)) return false;
|
||||||
return true;
|
fp.write(data, size);
|
||||||
}
|
fp.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif //ifdef CART_CPP
|
#endif //ifdef CART_CPP
|
||||||
|
@@ -5,6 +5,7 @@ void Cartridge::read_header() {
|
|||||||
uint index = info.header_index;
|
uint index = info.header_index;
|
||||||
uint8 mapper = rom[index + MAPPER];
|
uint8 mapper = rom[index + MAPPER];
|
||||||
uint8 rom_type = rom[index + ROM_TYPE];
|
uint8 rom_type = rom[index + ROM_TYPE];
|
||||||
|
uint8 rom_size = rom[index + ROM_SIZE];
|
||||||
uint8 company = rom[index + COMPANY];
|
uint8 company = rom[index + COMPANY];
|
||||||
uint8 region = rom[index + REGION] & 0x7f;
|
uint8 region = rom[index + REGION] & 0x7f;
|
||||||
|
|
||||||
@@ -52,8 +53,9 @@ void Cartridge::read_header() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(mapper == 0x3a && (rom_type == 0xf5 || rom_type == 0xf9)) {
|
if(mapper == 0x3a && (rom_type == 0xf5 || rom_type == 0xf9)) {
|
||||||
//rom_type: 0xf5 = no S-RTC, 0xf9 = S-RTC
|
|
||||||
info.spc7110 = true;
|
info.spc7110 = true;
|
||||||
|
info.spc7110rtc = (rom_type == 0xf9);
|
||||||
|
info.mapper = SPC7110ROM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mapper == 0x20 && rom_type == 0xf3) {
|
if(mapper == 0x20 && rom_type == 0xf3) {
|
||||||
@@ -98,13 +100,14 @@ void Cartridge::read_header() {
|
|||||||
info.obc1 = true;
|
info.obc1 = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mapper == 0x30 && rom_type == 0xf6) {
|
if(mapper == 0x30 && rom_type == 0xf6 && rom_size >= 10) {
|
||||||
//TODO: both ST010 and ST011 share the same mapper + rom_type.
|
|
||||||
//need way to determine which is which.
|
|
||||||
//for now, default to supported ST010.
|
|
||||||
info.st010 = true;
|
info.st010 = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(mapper == 0x30 && rom_type == 0xf6 && rom_size < 10) {
|
||||||
|
info.st011 = true;
|
||||||
|
}
|
||||||
|
|
||||||
if(mapper == 0x30 && rom_type == 0xf5) {
|
if(mapper == 0x30 && rom_type == 0xf5) {
|
||||||
info.st018 = true;
|
info.st018 = true;
|
||||||
}
|
}
|
||||||
@@ -117,70 +120,95 @@ void Cartridge::read_header() {
|
|||||||
|
|
||||||
//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);
|
unsigned Cartridge::score_header(unsigned addr) {
|
||||||
info.name[21] = 0;
|
if(cart.rom_size < addr + 64) return 0; //image too small to contain header at this location?
|
||||||
trim(info.name);
|
uint8 *rom = cart.rom;
|
||||||
|
int score = 0;
|
||||||
|
|
||||||
//convert undisplayable characters (half-width katakana, etc) to '?' characters
|
uint16 resetvector = rom[addr + RESETV] | (rom[addr + RESETV + 1] << 8);
|
||||||
for(int i = 0; i < 21; i++) {
|
uint16 checksum = rom[addr + CKSUM] | (rom[addr + CKSUM + 1] << 8);
|
||||||
if(info.name[i] & 0x80) info.name[i] = '?';
|
uint16 ichecksum = rom[addr + ICKSUM] | (rom[addr + ICKSUM + 1] << 8);
|
||||||
}
|
|
||||||
|
|
||||||
//always display something
|
uint8 resetop = rom[(addr & ~0x7fff) | (resetvector & 0x7fff)]; //first opcode executed upon reset
|
||||||
if(!info.name[0]) strcpy(info.name, "(untitled)");
|
uint8 mapper = rom[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(rom[addr + COMPANY] == 0x33) score += 2; //0x33 indicates extended header
|
||||||
|
if(rom[addr + ROM_TYPE] < 0x08) score++;
|
||||||
|
if(rom[addr + ROM_SIZE] < 0x10) score++;
|
||||||
|
if(rom[addr + RAM_SIZE] < 0x08) score++;
|
||||||
|
if(rom[addr + REGION] < 14) score++;
|
||||||
|
|
||||||
|
if(score < 0) score = 0;
|
||||||
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cartridge::find_header() {
|
void Cartridge::find_header() {
|
||||||
int32 score_lo = 0, score_hi = 0, score_ex = 0;
|
unsigned score_lo = score_header(0x007fc0);
|
||||||
uint8_t *rom = cart.rom;
|
unsigned score_hi = score_header(0x00ffc0);
|
||||||
|
unsigned score_ex = score_header(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 += 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(score_lo >= score_hi && score_lo >= score_ex) {
|
if(score_lo >= score_hi && score_lo >= score_ex) {
|
||||||
info.header_index = 0x007fc0;
|
info.header_index = 0x007fc0;
|
||||||
|
@@ -12,17 +12,18 @@ void Cartridge::load_cart_normal(const char *filename) {
|
|||||||
|
|
||||||
//load ROM data, ignore 512-byte header if detected
|
//load ROM data, ignore 512-byte header if detected
|
||||||
if((size & 0x7fff) != 512) {
|
if((size & 0x7fff) != 512) {
|
||||||
cart.rom = (uint8*)malloc(cart.rom_size = size);
|
cart.rom = new uint8_t[cart.rom_size = size];
|
||||||
memcpy(cart.rom, data, size);
|
memcpy(cart.rom, data, size);
|
||||||
} else {
|
} else {
|
||||||
cart.rom = (uint8*)malloc(cart.rom_size = size - 512);
|
cart.rom = new uint8_t[cart.rom_size = size - 512];
|
||||||
memcpy(cart.rom, data + 512, size - 512);
|
memcpy(cart.rom, data + 512, size - 512);
|
||||||
}
|
}
|
||||||
safe_free(data);
|
delete[] data;
|
||||||
|
|
||||||
if(load_file(get_patch_filename(cart.fn, "ups"), data, size, CompressionInspect) == true) {
|
if(load_file(get_patch_filename(cart.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||||
apply_patch(data, size, cart.rom, cart.rom_size);
|
apply_patch(data, size, cart.rom, cart.rom_size);
|
||||||
if(data) { free(data); data = 0; }
|
delete[] data;
|
||||||
|
info.patched = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
info.crc32 = crc32_calculate(cart.rom, cart.rom_size);
|
info.crc32 = crc32_calculate(cart.rom, cart.rom_size);
|
||||||
@@ -31,12 +32,20 @@ void Cartridge::load_cart_normal(const char *filename) {
|
|||||||
read_header();
|
read_header();
|
||||||
|
|
||||||
if(info.ram_size > 0) {
|
if(info.ram_size > 0) {
|
||||||
cart.ram = (uint8*)malloc(cart.ram_size = info.ram_size);
|
cart.ram = new uint8_t[cart.ram_size = info.ram_size];
|
||||||
memset(cart.ram, 0xff, cart.ram_size);
|
memset(cart.ram, 0xff, cart.ram_size);
|
||||||
|
|
||||||
if(load_file(get_save_filename(cart.fn, "srm"), data, size, CompressionNone) == true) {
|
if(load_file(get_save_filename(cart.fn, "srm"), data, size, CompressionNone) == true) {
|
||||||
memcpy(cart.ram, data, min(size, cart.ram_size));
|
memcpy(cart.ram, data, min(size, cart.ram_size));
|
||||||
safe_free(data);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,6 +58,7 @@ void Cartridge::load_cart_normal(const char *filename) {
|
|||||||
|
|
||||||
void Cartridge::unload_cart_normal() {
|
void Cartridge::unload_cart_normal() {
|
||||||
if(cart.ram) save_file(get_save_filename(cart.fn, "srm"), cart.ram, cart.ram_size);
|
if(cart.ram) save_file(get_save_filename(cart.fn, "srm"), cart.ram, cart.ram_size);
|
||||||
|
if(cart.rtc) save_file(get_save_filename(cart.fn, "rtc"), cart.rtc, cart.rtc_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //ifdef CART_CPP
|
#endif //ifdef CART_CPP
|
||||||
|
@@ -15,51 +15,51 @@ void Cartridge::load_cart_st(const char *base, const char *slotA, const char *sl
|
|||||||
uint8_t *data = 0;
|
uint8_t *data = 0;
|
||||||
unsigned size;
|
unsigned size;
|
||||||
if(load_file(cart.fn, data, size, CompressionAuto) == true) {
|
if(load_file(cart.fn, data, size, CompressionAuto) == true) {
|
||||||
cart.rom = (uint8*)malloc(cart.rom_size = 0x040000);
|
cart.rom = new(zeromemory) uint8_t[cart.rom_size = 0x040000];
|
||||||
memcpy(cart.rom, data, min(size, cart.rom_size));
|
memcpy(cart.rom, data, min(size, cart.rom_size));
|
||||||
safe_free(data);
|
delete[] data;
|
||||||
if(load_file(get_patch_filename(cart.fn, "ups"), data, size, CompressionInspect) == true) {
|
if(load_file(get_patch_filename(cart.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||||
apply_patch(data, size, cart.rom, cart.rom_size);
|
apply_patch(data, size, cart.rom, cart.rom_size);
|
||||||
if(data) { free(data); data = 0; }
|
delete[] data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(*stA.fn) {
|
if(*stA.fn) {
|
||||||
if(load_file(stA.fn, data, size, CompressionAuto) == true) {
|
if(load_file(stA.fn, data, size, CompressionAuto) == true) {
|
||||||
stA.rom = (uint8*)malloc(stA.rom_size = 0x100000);
|
stA.rom = new(zeromemory) uint8_t[stA.rom_size = 0x100000];
|
||||||
memcpy(stA.rom, data, min(size, stA.rom_size));
|
memcpy(stA.rom, data, min(size, stA.rom_size));
|
||||||
safe_free(data);
|
delete[] data;
|
||||||
if(load_file(get_patch_filename(stA.fn, "ups"), data, size, CompressionInspect) == true) {
|
if(load_file(get_patch_filename(stA.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||||
apply_patch(data, size, stA.rom, stA.rom_size);
|
apply_patch(data, size, stA.rom, stA.rom_size);
|
||||||
if(data) { free(data); data = 0; }
|
delete[] data;
|
||||||
}
|
}
|
||||||
|
|
||||||
stA.ram = (uint8*)malloc(stA.ram_size = 0x020000);
|
stA.ram = new uint8_t[stA.ram_size = 0x020000];
|
||||||
memset(stA.ram, 0xff, stA.ram_size);
|
memset(stA.ram, 0xff, stA.ram_size);
|
||||||
|
|
||||||
if(load_file(get_save_filename(stA.fn, "srm"), data, size, CompressionNone) == true) {
|
if(load_file(get_save_filename(stA.fn, "srm"), data, size, CompressionNone) == true) {
|
||||||
memcpy(stA.ram, data, min(size, 0x020000U));
|
memcpy(stA.ram, data, min(size, 0x020000U));
|
||||||
safe_free(data);
|
delete[] data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(*stB.fn) {
|
if(*stB.fn) {
|
||||||
if(load_file(stB.fn, data, size, CompressionAuto) == true) {
|
if(load_file(stB.fn, data, size, CompressionAuto) == true) {
|
||||||
stB.rom = (uint8*)malloc(stB.rom_size = 0x100000);
|
stB.rom = new(zeromemory) uint8_t[stB.rom_size = 0x100000];
|
||||||
memcpy(stB.rom, data, min(size, stB.rom_size));
|
memcpy(stB.rom, data, min(size, stB.rom_size));
|
||||||
safe_free(data);
|
delete[] data;
|
||||||
if(load_file(get_patch_filename(stB.fn, "ups"), data, size, CompressionInspect) == true) {
|
if(load_file(get_patch_filename(stB.fn, "ups"), data, size, CompressionInspect) == true) {
|
||||||
apply_patch(data, size, stB.rom, stB.rom_size);
|
apply_patch(data, size, stB.rom, stB.rom_size);
|
||||||
if(data) { free(data); data = 0; }
|
delete[] data;
|
||||||
}
|
}
|
||||||
|
|
||||||
stB.ram = (uint8*)malloc(stB.ram_size = 0x020000);
|
stB.ram = new uint8_t[stB.ram_size = 0x020000];
|
||||||
memset(stB.ram, 0xff, stB.ram_size);
|
memset(stB.ram, 0xff, stB.ram_size);
|
||||||
|
|
||||||
if(load_file(get_save_filename(stB.fn, "srm"), data, size, CompressionNone) == true) {
|
if(load_file(get_save_filename(stB.fn, "srm"), data, size, CompressionNone) == true) {
|
||||||
memcpy(stB.ram, data, min(size, 0x020000U));
|
memcpy(stB.ram, data, min(size, 0x020000U));
|
||||||
safe_free(data);
|
delete[] data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -147,7 +147,7 @@ bool Cheat::read(uint32 addr, uint8 &data) {
|
|||||||
* update_cheat_status() will scan to see if any codes are
|
* update_cheat_status() will scan to see if any codes are
|
||||||
* enabled. if any are, make sure the cheat system is on.
|
* enabled. if any are, make sure the cheat system is on.
|
||||||
* otherwise, turn cheat system off to speed up emulation.
|
* otherwise, turn cheat system off to speed up emulation.
|
||||||
*****/
|
*****/
|
||||||
|
|
||||||
void Cheat::update_cheat_status() {
|
void Cheat::update_cheat_status() {
|
||||||
for(unsigned i = 0; i < cheat_count; i++) {
|
for(unsigned i = 0; i < cheat_count; i++) {
|
||||||
@@ -295,15 +295,15 @@ bool Cheat::load(const char *fn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Cheat::save(const char *fn) {
|
bool Cheat::save(const char *fn) {
|
||||||
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 < cheat_count; i++) {
|
||||||
fprintf(fp, "%9s = %8s, \"%s\"\r\n",
|
fp.print(string()
|
||||||
index[i].code,
|
<< index[i].code << " = "
|
||||||
index[i].enabled ? "enabled" : "disabled",
|
<< (index[i].enabled ? "enabled" : "disabled") << ", \""
|
||||||
index[i].desc);
|
<< index[i].desc << "\"\r\n");
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fp.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -20,7 +20,7 @@ void BSXCart::reset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BSXCart::update_memory_map() {
|
void BSXCart::update_memory_map() {
|
||||||
Memory &cart = (regs.r[0x01] & 0x80) == 0x00 ? (Memory&)bsxflash : (Memory&)psram;
|
Memory &cart = (regs.r[0x01] & 0x80) == 0x00 ? (Memory&)bsxflash : (Memory&)psram;
|
||||||
|
|
||||||
if((regs.r[0x02] & 0x80) == 0x00) { //LoROM mapping
|
if((regs.r[0x02] & 0x80) == 0x00) { //LoROM mapping
|
||||||
bus.map(Bus::MapLinear, 0x00, 0x7d, 0x8000, 0xffff, cart);
|
bus.map(Bus::MapLinear, 0x00, 0x7d, 0x8000, 0xffff, cart);
|
||||||
@@ -59,7 +59,7 @@ Memory &cart = (regs.r[0x01] & 0x80) == 0x00 ? (Memory&)bsxflash : (Memory&)psra
|
|||||||
|
|
||||||
uint8 BSXCart::mmio_read(uint addr) {
|
uint8 BSXCart::mmio_read(uint addr) {
|
||||||
if((addr & 0xf0ffff) == 0x005000) { //$[00-0f]:5000 MMIO
|
if((addr & 0xf0ffff) == 0x005000) { //$[00-0f]:5000 MMIO
|
||||||
uint8 n = (addr >> 16) & 15;
|
uint8 n = (addr >> 16) & 15;
|
||||||
return regs.r[n];
|
return regs.r[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ uint8 BSXCart::mmio_read(uint addr) {
|
|||||||
|
|
||||||
void BSXCart::mmio_write(uint addr, uint8 data) {
|
void BSXCart::mmio_write(uint addr, uint8 data) {
|
||||||
if((addr & 0xf0ffff) == 0x005000) { //$[00-0f]:5000 MMIO
|
if((addr & 0xf0ffff) == 0x005000) { //$[00-0f]:5000 MMIO
|
||||||
uint8 n = (addr >> 16) & 15;
|
uint8 n = (addr >> 16) & 15;
|
||||||
regs.r[n] = data;
|
regs.r[n] = data;
|
||||||
if(n == 0x0e && data & 0x80) update_memory_map();
|
if(n == 0x0e && data & 0x80) update_memory_map();
|
||||||
return;
|
return;
|
||||||
@@ -84,16 +84,16 @@ void BSXCart::mmio_write(uint addr, uint8 data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BSXCart::BSXCart() {
|
BSXCart::BSXCart() {
|
||||||
sram_data = (uint8*)malloc( 32 * 1024);
|
sram_data = new uint8_t[ 32 * 1024];
|
||||||
psram_data = (uint8*)malloc(512 * 1024);
|
psram_data = new uint8_t[512 * 1024];
|
||||||
|
|
||||||
sram.map (sram_data, 32 * 1024);
|
sram.map (sram_data, 32 * 1024);
|
||||||
psram.map(psram_data, 512 * 1024);
|
psram.map(psram_data, 512 * 1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
BSXCart::~BSXCart() {
|
BSXCart::~BSXCart() {
|
||||||
safe_free(sram_data);
|
delete[] sram_data;
|
||||||
safe_free(psram_data);
|
delete[] psram_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //ifdef BSX_CPP
|
#endif //ifdef BSX_CPP
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
#include "bsx/bsx.h"
|
#include "bsx/bsx.h"
|
||||||
#include "srtc/srtc.h"
|
#include "srtc/srtc.h"
|
||||||
#include "sdd1/sdd1.h"
|
#include "sdd1/sdd1.h"
|
||||||
|
#include "spc7110/spc7110.h"
|
||||||
#include "cx4/cx4.h"
|
#include "cx4/cx4.h"
|
||||||
#include "dsp1/dsp1.h"
|
#include "dsp1/dsp1.h"
|
||||||
#include "dsp2/dsp2.h"
|
#include "dsp2/dsp2.h"
|
||||||
|
511
src/chip/spc7110/decomp.cpp
Normal file
511
src/chip/spc7110/decomp.cpp
Normal file
@@ -0,0 +1,511 @@
|
|||||||
|
#ifdef SPC7110_CPP
|
||||||
|
|
||||||
|
uint8 SPC7110Decomp::read() {
|
||||||
|
if(decomp_buffer_length == 0) {
|
||||||
|
//decompress at least (decomp_buffer_size / 2) bytes to the buffer
|
||||||
|
switch(decomp_mode) {
|
||||||
|
case 0: mode0(false); break;
|
||||||
|
case 1: mode1(false); break;
|
||||||
|
case 2: mode2(false); break;
|
||||||
|
default: return 0x00;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 data = decomp_buffer[decomp_buffer_rdoffset++];
|
||||||
|
decomp_buffer_rdoffset &= decomp_buffer_size - 1;
|
||||||
|
decomp_buffer_length--;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPC7110Decomp::write(uint8 data) {
|
||||||
|
decomp_buffer[decomp_buffer_wroffset++] = data;
|
||||||
|
decomp_buffer_wroffset &= decomp_buffer_size - 1;
|
||||||
|
decomp_buffer_length++;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 SPC7110Decomp::dataread() {
|
||||||
|
unsigned size = memory::cartrom.size() - 0x100000;
|
||||||
|
while(decomp_offset >= size) decomp_offset -= size;
|
||||||
|
return memory::cartrom.read(0x100000 + decomp_offset++);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPC7110Decomp::init(unsigned mode, unsigned offset, unsigned index) {
|
||||||
|
decomp_mode = mode;
|
||||||
|
decomp_offset = offset;
|
||||||
|
|
||||||
|
decomp_buffer_rdoffset = 0;
|
||||||
|
decomp_buffer_wroffset = 0;
|
||||||
|
decomp_buffer_length = 0;
|
||||||
|
|
||||||
|
//reset context states
|
||||||
|
for(unsigned i = 0; i < 32; i++) {
|
||||||
|
context[i].index = 0;
|
||||||
|
context[i].invert = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(decomp_mode) {
|
||||||
|
case 0: mode0(true); break;
|
||||||
|
case 1: mode1(true); break;
|
||||||
|
case 2: mode2(true); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//decompress up to requested output data index
|
||||||
|
while(index--) read();
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
void SPC7110Decomp::mode0(bool init) {
|
||||||
|
static uint8 val, in, span;
|
||||||
|
static int out, inverts, lps, in_count;
|
||||||
|
|
||||||
|
if(init == true) {
|
||||||
|
out = inverts = lps = 0;
|
||||||
|
span = 0xff;
|
||||||
|
val = dataread();
|
||||||
|
in = dataread();
|
||||||
|
in_count = 8;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(decomp_buffer_length < (decomp_buffer_size >> 1)) {
|
||||||
|
for(unsigned bit = 0; bit < 8; bit++) {
|
||||||
|
//get context
|
||||||
|
uint8 mask = (1 << (bit & 3)) - 1;
|
||||||
|
uint8 con = mask + ((inverts & mask) ^ (lps & mask));
|
||||||
|
if(bit > 3) con += 15;
|
||||||
|
|
||||||
|
//get prob and mps
|
||||||
|
unsigned prob = probability(con);
|
||||||
|
unsigned mps = (((out >> 15) & 1) ^ context[con].invert);
|
||||||
|
|
||||||
|
//get bit
|
||||||
|
unsigned flag_lps;
|
||||||
|
if(val <= span - prob) { //mps
|
||||||
|
span = span - prob;
|
||||||
|
out = (out << 1) + mps;
|
||||||
|
flag_lps = 0;
|
||||||
|
} else { //lps
|
||||||
|
val = val - (span - (prob - 1));
|
||||||
|
span = prob - 1;
|
||||||
|
out = (out << 1) + 1 - mps;
|
||||||
|
flag_lps = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//renormalize
|
||||||
|
unsigned shift = 0;
|
||||||
|
while(span < 0x7f) {
|
||||||
|
shift++;
|
||||||
|
|
||||||
|
span = (span << 1) + 1;
|
||||||
|
val = (val << 1) + (in >> 7);
|
||||||
|
|
||||||
|
in <<= 1;
|
||||||
|
if(--in_count == 0) {
|
||||||
|
in = dataread();
|
||||||
|
in_count = 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//update processing info
|
||||||
|
lps = (lps << 1) + flag_lps;
|
||||||
|
inverts = (inverts << 1) + context[con].invert;
|
||||||
|
|
||||||
|
//update context state
|
||||||
|
if(flag_lps & toggle_invert(con)) context[con].invert ^= 1;
|
||||||
|
if(flag_lps) context[con].index = next_lps(con);
|
||||||
|
else if(shift) context[con].index = next_mps(con);
|
||||||
|
}
|
||||||
|
|
||||||
|
//save byte
|
||||||
|
write(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPC7110Decomp::mode1(bool init) {
|
||||||
|
static int pixelorder[4], realorder[4];
|
||||||
|
static uint8 in, val, span;
|
||||||
|
static int out, inverts, lps, in_count;
|
||||||
|
|
||||||
|
if(init == true) {
|
||||||
|
for(unsigned i = 0; i < 4; i++) pixelorder[i] = i;
|
||||||
|
out = inverts = lps = 0;
|
||||||
|
span = 0xff;
|
||||||
|
val = dataread();
|
||||||
|
in = dataread();
|
||||||
|
in_count = 8;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(decomp_buffer_length < (decomp_buffer_size >> 1)) {
|
||||||
|
for(unsigned pixel = 0; pixel < 8; pixel++) {
|
||||||
|
//get first symbol context
|
||||||
|
unsigned a = ((out >> (1 * 2)) & 3);
|
||||||
|
unsigned b = ((out >> (7 * 2)) & 3);
|
||||||
|
unsigned c = ((out >> (8 * 2)) & 3);
|
||||||
|
unsigned con = (a == b) ? (b != c) : (b == c) ? 2 : 4 - (a == c);
|
||||||
|
|
||||||
|
//update pixel order
|
||||||
|
unsigned m, n;
|
||||||
|
for(m = 0; m < 4; m++) if(pixelorder[m] == a) break;
|
||||||
|
for(n = m; n > 0; n--) pixelorder[n] = pixelorder[n - 1];
|
||||||
|
pixelorder[0] = a;
|
||||||
|
|
||||||
|
//calculate the real pixel order
|
||||||
|
for(m = 0; m < 4; m++) realorder[m] = pixelorder[m];
|
||||||
|
|
||||||
|
//rotate reference pixel c value to top
|
||||||
|
for(m = 0; m < 4; m++) if(realorder[m] == c) break;
|
||||||
|
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
||||||
|
realorder[0] = c;
|
||||||
|
|
||||||
|
//rotate reference pixel b value to top
|
||||||
|
for(m = 0; m < 4; m++) if(realorder[m] == b) break;
|
||||||
|
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
||||||
|
realorder[0] = b;
|
||||||
|
|
||||||
|
//rotate reference pixel a value to top
|
||||||
|
for(m = 0; m < 4; m++) if(realorder[m] == a) break;
|
||||||
|
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
||||||
|
realorder[0] = a;
|
||||||
|
|
||||||
|
//get 2 symbols
|
||||||
|
for(unsigned bit = 0; bit < 2; bit++) {
|
||||||
|
//get prob
|
||||||
|
unsigned prob = probability(con);
|
||||||
|
|
||||||
|
//get symbol
|
||||||
|
unsigned flag_lps;
|
||||||
|
if(val <= span - prob) { //mps
|
||||||
|
span = span - prob;
|
||||||
|
flag_lps = 0;
|
||||||
|
} else { //lps
|
||||||
|
val = val - (span - (prob - 1));
|
||||||
|
span = prob - 1;
|
||||||
|
flag_lps = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//renormalize
|
||||||
|
unsigned shift = 0;
|
||||||
|
while(span < 0x7f) {
|
||||||
|
shift++;
|
||||||
|
|
||||||
|
span = (span << 1) + 1;
|
||||||
|
val = (val << 1) + (in >> 7);
|
||||||
|
|
||||||
|
in <<= 1;
|
||||||
|
if(--in_count == 0) {
|
||||||
|
in = dataread();
|
||||||
|
in_count = 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//update processing info
|
||||||
|
lps = (lps << 1) + flag_lps;
|
||||||
|
inverts = (inverts << 1) + context[con].invert;
|
||||||
|
|
||||||
|
//update context state
|
||||||
|
if(flag_lps & toggle_invert(con)) context[con].invert ^= 1;
|
||||||
|
if(flag_lps) context[con].index = next_lps(con);
|
||||||
|
else if(shift) context[con].index = next_mps(con);
|
||||||
|
|
||||||
|
//get next context
|
||||||
|
con = 5 + (con << 1) + ((lps ^ inverts) & 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//get pixel
|
||||||
|
b = realorder[(lps ^ inverts) & 3];
|
||||||
|
out = (out << 2) + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
//turn pixel data into bitplanes
|
||||||
|
unsigned data = morton_2x8(out);
|
||||||
|
write(data >> 8);
|
||||||
|
write(data >> 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPC7110Decomp::mode2(bool init) {
|
||||||
|
static int pixelorder[16], realorder[16];
|
||||||
|
static uint8 bitplanebuffer[16], buffer_index;
|
||||||
|
static uint8 in, val, span;
|
||||||
|
static int out0, out1, inverts, lps, in_count;
|
||||||
|
|
||||||
|
if(init == true) {
|
||||||
|
for(unsigned i = 0; i < 16; i++) pixelorder[i] = i;
|
||||||
|
buffer_index = 0;
|
||||||
|
out0 = out1 = inverts = lps = 0;
|
||||||
|
span = 0xff;
|
||||||
|
val = dataread();
|
||||||
|
in = dataread();
|
||||||
|
in_count = 8;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(decomp_buffer_length < (decomp_buffer_size >> 1)) {
|
||||||
|
for(unsigned pixel = 0; pixel < 8; pixel++) {
|
||||||
|
//get first symbol context
|
||||||
|
unsigned a = ((out0 >> (0 * 4)) & 15);
|
||||||
|
unsigned b = ((out0 >> (7 * 4)) & 15);
|
||||||
|
unsigned c = ((out1 >> (0 * 4)) & 15);
|
||||||
|
unsigned con = 0;
|
||||||
|
unsigned refcon = (a == b) ? (b != c) : (b == c) ? 2 : 4 - (a == c);
|
||||||
|
|
||||||
|
//update pixel order
|
||||||
|
unsigned m, n;
|
||||||
|
for(m = 0; m < 16; m++) if(pixelorder[m] == a) break;
|
||||||
|
for(n = m; n > 0; n--) pixelorder[n] = pixelorder[n - 1];
|
||||||
|
pixelorder[0] = a;
|
||||||
|
|
||||||
|
//calculate the real pixel order
|
||||||
|
for(m = 0; m < 16; m++) realorder[m] = pixelorder[m];
|
||||||
|
|
||||||
|
//rotate reference pixel c value to top
|
||||||
|
for(m = 0; m < 16; m++) if(realorder[m] == c) break;
|
||||||
|
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
||||||
|
realorder[0] = c;
|
||||||
|
|
||||||
|
//rotate reference pixel b value to top
|
||||||
|
for(m = 0; m < 16; m++) if(realorder[m] == b) break;
|
||||||
|
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
||||||
|
realorder[0] = b;
|
||||||
|
|
||||||
|
//rotate reference pixel a value to top
|
||||||
|
for(m = 0; m < 16; m++) if(realorder[m] == a) break;
|
||||||
|
for(n = m; n > 0; n--) realorder[n] = realorder[n - 1];
|
||||||
|
realorder[0] = a;
|
||||||
|
|
||||||
|
//get 4 symbols
|
||||||
|
for(unsigned bit = 0; bit < 4; bit++) {
|
||||||
|
//get prob
|
||||||
|
unsigned prob = probability(con);
|
||||||
|
|
||||||
|
//get symbol
|
||||||
|
unsigned flag_lps;
|
||||||
|
if(val <= span - prob) { //mps
|
||||||
|
span = span - prob;
|
||||||
|
flag_lps = 0;
|
||||||
|
} else { //lps
|
||||||
|
val = val - (span - (prob - 1));
|
||||||
|
span = prob - 1;
|
||||||
|
flag_lps = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//renormalize
|
||||||
|
unsigned shift = 0;
|
||||||
|
while(span < 0x7f) {
|
||||||
|
shift++;
|
||||||
|
|
||||||
|
span = (span << 1) + 1;
|
||||||
|
val = (val << 1) + (in >> 7);
|
||||||
|
|
||||||
|
in <<= 1;
|
||||||
|
if(--in_count == 0) {
|
||||||
|
in = dataread();
|
||||||
|
in_count = 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//update processing info
|
||||||
|
lps = (lps << 1) + flag_lps;
|
||||||
|
unsigned invertbit = context[con].invert;
|
||||||
|
inverts = (inverts << 1) + invertbit;
|
||||||
|
|
||||||
|
//update context state
|
||||||
|
if(flag_lps & toggle_invert(con)) context[con].invert ^= 1;
|
||||||
|
if(flag_lps) context[con].index = next_lps(con);
|
||||||
|
else if(shift) context[con].index = next_mps(con);
|
||||||
|
|
||||||
|
//get next context
|
||||||
|
con = mode2_context_table[con][flag_lps ^ invertbit] + (con == 1 ? refcon : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//get pixel
|
||||||
|
b = realorder[(lps ^ inverts) & 0x0f];
|
||||||
|
out1 = (out1 << 4) + ((out0 >> 28) & 0x0f);
|
||||||
|
out0 = (out0 << 4) + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
//convert pixel data into bitplanes
|
||||||
|
unsigned data = morton_4x8(out0);
|
||||||
|
write(data >> 24);
|
||||||
|
write(data >> 16);
|
||||||
|
bitplanebuffer[buffer_index++] = data >> 8;
|
||||||
|
bitplanebuffer[buffer_index++] = data >> 0;
|
||||||
|
|
||||||
|
if(buffer_index == 16) {
|
||||||
|
for(unsigned i = 0; i < 16; i++) write(bitplanebuffer[i]);
|
||||||
|
buffer_index = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
const uint8 SPC7110Decomp::evolution_table[53][4] = {
|
||||||
|
//{ prob, nextlps, nextmps, toggle invert },
|
||||||
|
|
||||||
|
{ 0x5a, 1, 1, 1 },
|
||||||
|
{ 0x25, 6, 2, 0 },
|
||||||
|
{ 0x11, 8, 3, 0 },
|
||||||
|
{ 0x08, 10, 4, 0 },
|
||||||
|
{ 0x03, 12, 5, 0 },
|
||||||
|
{ 0x01, 15, 5, 0 },
|
||||||
|
|
||||||
|
{ 0x5a, 7, 7, 1 },
|
||||||
|
{ 0x3f, 19, 8, 0 },
|
||||||
|
{ 0x2c, 21, 9, 0 },
|
||||||
|
{ 0x20, 22, 10, 0 },
|
||||||
|
{ 0x17, 23, 11, 0 },
|
||||||
|
{ 0x11, 25, 12, 0 },
|
||||||
|
{ 0x0c, 26, 13, 0 },
|
||||||
|
{ 0x09, 28, 14, 0 },
|
||||||
|
{ 0x07, 29, 15, 0 },
|
||||||
|
{ 0x05, 31, 16, 0 },
|
||||||
|
{ 0x04, 32, 17, 0 },
|
||||||
|
{ 0x03, 34, 18, 0 },
|
||||||
|
{ 0x02, 35, 5, 0 },
|
||||||
|
|
||||||
|
{ 0x5a, 20, 20, 1 },
|
||||||
|
{ 0x48, 39, 21, 0 },
|
||||||
|
{ 0x3a, 40, 22, 0 },
|
||||||
|
{ 0x2e, 42, 23, 0 },
|
||||||
|
{ 0x26, 44, 24, 0 },
|
||||||
|
{ 0x1f, 45, 25, 0 },
|
||||||
|
{ 0x19, 46, 26, 0 },
|
||||||
|
{ 0x15, 25, 27, 0 },
|
||||||
|
{ 0x11, 26, 28, 0 },
|
||||||
|
{ 0x0e, 26, 29, 0 },
|
||||||
|
{ 0x0b, 27, 30, 0 },
|
||||||
|
{ 0x09, 28, 31, 0 },
|
||||||
|
{ 0x08, 29, 32, 0 },
|
||||||
|
{ 0x07, 30, 33, 0 },
|
||||||
|
{ 0x05, 31, 34, 0 },
|
||||||
|
{ 0x04, 33, 35, 0 },
|
||||||
|
{ 0x04, 33, 36, 0 },
|
||||||
|
{ 0x03, 34, 37, 0 },
|
||||||
|
{ 0x02, 35, 38, 0 },
|
||||||
|
{ 0x02, 36, 5, 0 },
|
||||||
|
|
||||||
|
{ 0x58, 39, 40, 1 },
|
||||||
|
{ 0x4d, 47, 41, 0 },
|
||||||
|
{ 0x43, 48, 42, 0 },
|
||||||
|
{ 0x3b, 49, 43, 0 },
|
||||||
|
{ 0x34, 50, 44, 0 },
|
||||||
|
{ 0x2e, 51, 45, 0 },
|
||||||
|
{ 0x29, 44, 46, 0 },
|
||||||
|
{ 0x25, 45, 24, 0 },
|
||||||
|
|
||||||
|
{ 0x56, 47, 48, 1 },
|
||||||
|
{ 0x4f, 47, 49, 0 },
|
||||||
|
{ 0x47, 48, 50, 0 },
|
||||||
|
{ 0x41, 49, 51, 0 },
|
||||||
|
{ 0x3c, 50, 52, 0 },
|
||||||
|
{ 0x37, 51, 43, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8 SPC7110Decomp::mode2_context_table[32][2] = {
|
||||||
|
//{ next 0, next 1 },
|
||||||
|
|
||||||
|
{ 1, 2 },
|
||||||
|
|
||||||
|
{ 3, 8 },
|
||||||
|
{ 13, 14 },
|
||||||
|
|
||||||
|
{ 15, 16 },
|
||||||
|
{ 17, 18 },
|
||||||
|
{ 19, 20 },
|
||||||
|
{ 21, 22 },
|
||||||
|
{ 23, 24 },
|
||||||
|
{ 25, 26 },
|
||||||
|
{ 25, 26 },
|
||||||
|
{ 25, 26 },
|
||||||
|
{ 25, 26 },
|
||||||
|
{ 25, 26 },
|
||||||
|
{ 27, 28 },
|
||||||
|
{ 29, 30 },
|
||||||
|
|
||||||
|
{ 31, 31 },
|
||||||
|
{ 31, 31 },
|
||||||
|
{ 31, 31 },
|
||||||
|
{ 31, 31 },
|
||||||
|
{ 31, 31 },
|
||||||
|
{ 31, 31 },
|
||||||
|
{ 31, 31 },
|
||||||
|
{ 31, 31 },
|
||||||
|
{ 31, 31 },
|
||||||
|
{ 31, 31 },
|
||||||
|
{ 31, 31 },
|
||||||
|
{ 31, 31 },
|
||||||
|
{ 31, 31 },
|
||||||
|
{ 31, 31 },
|
||||||
|
{ 31, 31 },
|
||||||
|
{ 31, 31 },
|
||||||
|
|
||||||
|
{ 31, 31 },
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8 SPC7110Decomp::probability (unsigned n) { return evolution_table[context[n].index][0]; }
|
||||||
|
uint8 SPC7110Decomp::next_lps (unsigned n) { return evolution_table[context[n].index][1]; }
|
||||||
|
uint8 SPC7110Decomp::next_mps (unsigned n) { return evolution_table[context[n].index][2]; }
|
||||||
|
bool SPC7110Decomp::toggle_invert(unsigned n) { return evolution_table[context[n].index][3]; }
|
||||||
|
|
||||||
|
unsigned SPC7110Decomp::morton_2x8(unsigned data) {
|
||||||
|
//reverse morton lookup: de-interleave two 8-bit values
|
||||||
|
//15, 13, 11, 9, 7, 5, 3, 1 -> 15- 8
|
||||||
|
//14, 12, 10, 8, 6, 4, 2, 0 -> 7- 0
|
||||||
|
return morton16[0][(data >> 0) & 255] + morton16[1][(data >> 8) & 255];
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned SPC7110Decomp::morton_4x8(unsigned data) {
|
||||||
|
//reverse morton lookup: de-interleave four 8-bit values
|
||||||
|
//31, 27, 23, 19, 15, 11, 7, 3 -> 31-24
|
||||||
|
//30, 26, 22, 18, 14, 10, 6, 2 -> 23-16
|
||||||
|
//29, 25, 21, 17, 13, 9, 5, 1 -> 15- 8
|
||||||
|
//28, 24, 20, 16, 12, 8, 4, 0 -> 7- 0
|
||||||
|
return morton32[0][(data >> 0) & 255] + morton32[1][(data >> 8) & 255]
|
||||||
|
+ morton32[2][(data >> 16) & 255] + morton32[3][(data >> 24) & 255];
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
void SPC7110Decomp::reset() {
|
||||||
|
//mode 3 is invalid; this is treated as a special case to always return 0x00
|
||||||
|
//set to mode 3 so that reading decomp port before starting first decomp will return 0x00
|
||||||
|
decomp_mode = 3;
|
||||||
|
|
||||||
|
decomp_buffer_rdoffset = 0;
|
||||||
|
decomp_buffer_wroffset = 0;
|
||||||
|
decomp_buffer_length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPC7110Decomp::SPC7110Decomp() {
|
||||||
|
decomp_buffer = new uint8_t[decomp_buffer_size];
|
||||||
|
reset();
|
||||||
|
|
||||||
|
//initialize reverse morton lookup tables
|
||||||
|
for(unsigned i = 0; i < 256; i++) {
|
||||||
|
#define map(x, y) (((i >> x) & 1) << y)
|
||||||
|
//2x8-bit
|
||||||
|
morton16[1][i] = map(7, 15) + map(6, 7) + map(5, 14) + map(4, 6)
|
||||||
|
+ map(3, 13) + map(2, 5) + map(1, 12) + map(0, 4);
|
||||||
|
morton16[0][i] = map(7, 11) + map(6, 3) + map(5, 10) + map(4, 2)
|
||||||
|
+ map(3, 9) + map(2, 1) + map(1, 8) + map(0, 0);
|
||||||
|
//4x8-bit
|
||||||
|
morton32[3][i] = map(7, 31) + map(6, 23) + map(5, 15) + map(4, 7)
|
||||||
|
+ map(3, 30) + map(2, 22) + map(1, 14) + map(0, 6);
|
||||||
|
morton32[2][i] = map(7, 29) + map(6, 21) + map(5, 13) + map(4, 5)
|
||||||
|
+ map(3, 28) + map(2, 20) + map(1, 12) + map(0, 4);
|
||||||
|
morton32[1][i] = map(7, 27) + map(6, 19) + map(5, 11) + map(4, 3)
|
||||||
|
+ map(3, 26) + map(2, 18) + map(1, 10) + map(0, 2);
|
||||||
|
morton32[0][i] = map(7, 25) + map(6, 17) + map(5, 9) + map(4, 1)
|
||||||
|
+ map(3, 24) + map(2, 16) + map(1, 8) + map(0, 0);
|
||||||
|
#undef map
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SPC7110Decomp::~SPC7110Decomp() {
|
||||||
|
delete[] decomp_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
45
src/chip/spc7110/decomp.h
Normal file
45
src/chip/spc7110/decomp.h
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
class SPC7110Decomp {
|
||||||
|
public:
|
||||||
|
uint8 read();
|
||||||
|
void init(unsigned mode, unsigned offset, unsigned index);
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
SPC7110Decomp();
|
||||||
|
~SPC7110Decomp();
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned decomp_mode;
|
||||||
|
unsigned decomp_offset;
|
||||||
|
|
||||||
|
//read() will spool chunks half the size of decomp_buffer_size
|
||||||
|
enum { decomp_buffer_size = 64 }; //must be >= 64, and must be a power of two
|
||||||
|
uint8 *decomp_buffer;
|
||||||
|
unsigned decomp_buffer_rdoffset;
|
||||||
|
unsigned decomp_buffer_wroffset;
|
||||||
|
unsigned decomp_buffer_length;
|
||||||
|
|
||||||
|
void write(uint8 data);
|
||||||
|
uint8 dataread();
|
||||||
|
|
||||||
|
void mode0(bool init);
|
||||||
|
void mode1(bool init);
|
||||||
|
void mode2(bool init);
|
||||||
|
|
||||||
|
static const uint8 evolution_table[53][4];
|
||||||
|
static const uint8 mode2_context_table[32][2];
|
||||||
|
|
||||||
|
struct ContextState {
|
||||||
|
uint8 index;
|
||||||
|
uint8 invert;
|
||||||
|
} context[32];
|
||||||
|
|
||||||
|
uint8 probability(unsigned n);
|
||||||
|
uint8 next_lps(unsigned n);
|
||||||
|
uint8 next_mps(unsigned n);
|
||||||
|
bool toggle_invert(unsigned n);
|
||||||
|
|
||||||
|
unsigned morton16[2][256];
|
||||||
|
unsigned morton32[4][256];
|
||||||
|
unsigned morton_2x8(unsigned data);
|
||||||
|
unsigned morton_4x8(unsigned data);
|
||||||
|
};
|
658
src/chip/spc7110/spc7110.cpp
Normal file
658
src/chip/spc7110/spc7110.cpp
Normal file
@@ -0,0 +1,658 @@
|
|||||||
|
#include "../../base.h"
|
||||||
|
#define SPC7110_CPP
|
||||||
|
|
||||||
|
#include "decomp.cpp"
|
||||||
|
|
||||||
|
const unsigned SPC7110::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||||
|
|
||||||
|
void SPC7110::init() {}
|
||||||
|
|
||||||
|
void SPC7110::enable() {
|
||||||
|
uint16_t limit = (cartridge.info.spc7110rtc ? 0x4842 : 0x483f);
|
||||||
|
for(uint16_t i = 0x4800; i <= limit; i++) memory::mmio.map(i, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPC7110::power() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPC7110::reset() {
|
||||||
|
r4801 = 0x00;
|
||||||
|
r4802 = 0x00;
|
||||||
|
r4803 = 0x00;
|
||||||
|
r4804 = 0x00;
|
||||||
|
r4805 = 0x00;
|
||||||
|
r4806 = 0x00;
|
||||||
|
r4807 = 0x00;
|
||||||
|
r4808 = 0x00;
|
||||||
|
r4809 = 0x00;
|
||||||
|
r480a = 0x00;
|
||||||
|
r480b = 0x00;
|
||||||
|
r480c = 0x00;
|
||||||
|
|
||||||
|
decomp.reset();
|
||||||
|
|
||||||
|
r4811 = 0x00;
|
||||||
|
r4812 = 0x00;
|
||||||
|
r4813 = 0x00;
|
||||||
|
r4814 = 0x00;
|
||||||
|
r4815 = 0x00;
|
||||||
|
r4816 = 0x00;
|
||||||
|
r4817 = 0x00;
|
||||||
|
r4818 = 0x00;
|
||||||
|
|
||||||
|
r481x = 0x00;
|
||||||
|
r4814_latch = false;
|
||||||
|
r4815_latch = false;
|
||||||
|
|
||||||
|
r4820 = 0x00;
|
||||||
|
r4821 = 0x00;
|
||||||
|
r4822 = 0x00;
|
||||||
|
r4823 = 0x00;
|
||||||
|
r4824 = 0x00;
|
||||||
|
r4825 = 0x00;
|
||||||
|
r4826 = 0x00;
|
||||||
|
r4827 = 0x00;
|
||||||
|
r4828 = 0x00;
|
||||||
|
r4829 = 0x00;
|
||||||
|
r482a = 0x00;
|
||||||
|
r482b = 0x00;
|
||||||
|
r482c = 0x00;
|
||||||
|
r482d = 0x00;
|
||||||
|
r482e = 0x00;
|
||||||
|
r482f = 0x00;
|
||||||
|
|
||||||
|
r4830 = 0x00;
|
||||||
|
mmio_write(0x4831, 0);
|
||||||
|
mmio_write(0x4832, 1);
|
||||||
|
mmio_write(0x4833, 2);
|
||||||
|
r4834 = 0x00;
|
||||||
|
|
||||||
|
r4840 = 0x00;
|
||||||
|
r4841 = 0x00;
|
||||||
|
r4842 = 0x00;
|
||||||
|
|
||||||
|
if(cartridge.info.spc7110rtc) {
|
||||||
|
rtc_state = RTCS_Inactive;
|
||||||
|
rtc_mode = RTCM_Linear;
|
||||||
|
rtc_index = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned SPC7110::datarom_addr(unsigned addr) {
|
||||||
|
unsigned size = memory::cartrom.size() - 0x100000;
|
||||||
|
while(addr >= size) addr -= size;
|
||||||
|
return addr + 0x100000;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned SPC7110::data_pointer() { return r4811 + (r4812 << 8) + (r4813 << 16); }
|
||||||
|
unsigned SPC7110::data_adjust() { return r4814 + (r4815 << 8); }
|
||||||
|
unsigned SPC7110::data_increment() { return r4816 + (r4817 << 8); }
|
||||||
|
void SPC7110::set_data_pointer(unsigned addr) { r4811 = addr; r4812 = addr >> 8; r4813 = addr >> 16; }
|
||||||
|
void SPC7110::set_data_adjust(unsigned addr) { r4814 = addr; r4815 = addr >> 8; }
|
||||||
|
|
||||||
|
void SPC7110::update_time(int offset) {
|
||||||
|
time_t rtc_time;
|
||||||
|
rtc_time = memory::cartrtc.read(16);
|
||||||
|
rtc_time |= memory::cartrtc.read(17) << 8;
|
||||||
|
rtc_time |= memory::cartrtc.read(18) << 16;
|
||||||
|
rtc_time |= memory::cartrtc.read(19) << 24;
|
||||||
|
|
||||||
|
bool update = true;
|
||||||
|
if(memory::cartrtc.read(13) & 1) update = false; //do not update if CR0 timer disable flag is set
|
||||||
|
if(memory::cartrtc.read(15) & 3) update = false; //do not update if CR2 timer disable flags are set
|
||||||
|
|
||||||
|
time_t current_time = time(0) - offset;
|
||||||
|
if(update && current_time > rtc_time) {
|
||||||
|
unsigned second = memory::cartrtc.read( 0) + memory::cartrtc.read( 1) * 10;
|
||||||
|
unsigned minute = memory::cartrtc.read( 2) + memory::cartrtc.read( 3) * 10;
|
||||||
|
unsigned hour = memory::cartrtc.read( 4) + memory::cartrtc.read( 5) * 10;
|
||||||
|
unsigned day = memory::cartrtc.read( 6) + memory::cartrtc.read( 7) * 10;
|
||||||
|
unsigned month = memory::cartrtc.read( 8) + memory::cartrtc.read( 9) * 10;
|
||||||
|
unsigned year = memory::cartrtc.read(10) + memory::cartrtc.read(11) * 10;
|
||||||
|
unsigned weekday = memory::cartrtc.read(12);
|
||||||
|
|
||||||
|
day--;
|
||||||
|
month--;
|
||||||
|
year += (year >= 90) ? 1900 : 2000; //range = 1990-2089
|
||||||
|
|
||||||
|
second += (unsigned)(current_time - rtc_time);
|
||||||
|
while(second >= 60) {
|
||||||
|
second -= 60;
|
||||||
|
|
||||||
|
minute++;
|
||||||
|
if(minute < 60) continue;
|
||||||
|
minute = 0;
|
||||||
|
|
||||||
|
hour++;
|
||||||
|
if(hour < 24) continue;
|
||||||
|
hour = 0;
|
||||||
|
|
||||||
|
day++;
|
||||||
|
weekday = (weekday + 1) % 7;
|
||||||
|
unsigned days = months[month % 12];
|
||||||
|
if(days == 28) {
|
||||||
|
bool leapyear = false;
|
||||||
|
if((year % 4) == 0) {
|
||||||
|
leapyear = true;
|
||||||
|
if((year % 100) == 0 && (year % 400) != 0) leapyear = false;
|
||||||
|
}
|
||||||
|
if(leapyear) days++;
|
||||||
|
}
|
||||||
|
if(day < days) continue;
|
||||||
|
day = 0;
|
||||||
|
|
||||||
|
month++;
|
||||||
|
if(month < 12) continue;
|
||||||
|
month = 0;
|
||||||
|
|
||||||
|
year++;
|
||||||
|
}
|
||||||
|
|
||||||
|
day++;
|
||||||
|
month++;
|
||||||
|
year %= 100;
|
||||||
|
|
||||||
|
memory::cartrtc.write( 0, second % 10);
|
||||||
|
memory::cartrtc.write( 1, second / 10);
|
||||||
|
memory::cartrtc.write( 2, minute % 10);
|
||||||
|
memory::cartrtc.write( 3, minute / 10);
|
||||||
|
memory::cartrtc.write( 4, hour % 10);
|
||||||
|
memory::cartrtc.write( 5, hour / 10);
|
||||||
|
memory::cartrtc.write( 6, day % 10);
|
||||||
|
memory::cartrtc.write( 7, day / 10);
|
||||||
|
memory::cartrtc.write( 8, month % 10);
|
||||||
|
memory::cartrtc.write( 9, month / 10);
|
||||||
|
memory::cartrtc.write(10, year % 10);
|
||||||
|
memory::cartrtc.write(11, (year / 10) % 10);
|
||||||
|
memory::cartrtc.write(12, weekday % 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
memory::cartrtc.write(16, current_time);
|
||||||
|
memory::cartrtc.write(17, current_time >> 8);
|
||||||
|
memory::cartrtc.write(18, current_time >> 16);
|
||||||
|
memory::cartrtc.write(19, current_time >> 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 SPC7110::mmio_read(uint addr) {
|
||||||
|
addr &= 0xffff;
|
||||||
|
|
||||||
|
switch(addr) {
|
||||||
|
//==================
|
||||||
|
//decompression unit
|
||||||
|
//==================
|
||||||
|
|
||||||
|
case 0x4800: {
|
||||||
|
uint16 counter = (r4809 + (r480a << 8));
|
||||||
|
counter--;
|
||||||
|
r4809 = counter;
|
||||||
|
r480a = counter >> 8;
|
||||||
|
return decomp.read();
|
||||||
|
}
|
||||||
|
case 0x4801: return r4801;
|
||||||
|
case 0x4802: return r4802;
|
||||||
|
case 0x4803: return r4803;
|
||||||
|
case 0x4804: return r4804;
|
||||||
|
case 0x4805: return r4805;
|
||||||
|
case 0x4806: return r4806;
|
||||||
|
case 0x4807: return r4807;
|
||||||
|
case 0x4808: return r4808;
|
||||||
|
case 0x4809: return r4809;
|
||||||
|
case 0x480a: return r480a;
|
||||||
|
case 0x480b: return r480b;
|
||||||
|
case 0x480c: {
|
||||||
|
uint8 status = r480c;
|
||||||
|
r480c &= 0x7f;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============
|
||||||
|
//data port unit
|
||||||
|
//==============
|
||||||
|
|
||||||
|
case 0x4810: {
|
||||||
|
if(r481x != 0x07) return 0x00;
|
||||||
|
|
||||||
|
unsigned addr = data_pointer();
|
||||||
|
unsigned adjust = data_adjust();
|
||||||
|
if(r4818 & 8) adjust = (int16)adjust; //16-bit sign extend
|
||||||
|
|
||||||
|
unsigned adjustaddr = addr;
|
||||||
|
if(r4818 & 2) {
|
||||||
|
adjustaddr += adjust;
|
||||||
|
set_data_adjust(adjust + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 data = memory::cartrom.read(datarom_addr(adjustaddr));
|
||||||
|
if(!(r4818 & 2)) {
|
||||||
|
unsigned increment = (r4818 & 1) ? data_increment() : 1;
|
||||||
|
if(r4818 & 4) increment = (int16)increment; //16-bit sign extend
|
||||||
|
|
||||||
|
if((r4818 & 16) == 0) {
|
||||||
|
set_data_pointer(addr + increment);
|
||||||
|
} else {
|
||||||
|
set_data_adjust(adjust + increment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
case 0x4811: return r4811;
|
||||||
|
case 0x4812: return r4812;
|
||||||
|
case 0x4813: return r4813;
|
||||||
|
case 0x4814: return r4814;
|
||||||
|
case 0x4815: return r4815;
|
||||||
|
case 0x4816: return r4816;
|
||||||
|
case 0x4817: return r4817;
|
||||||
|
case 0x4818: return r4818;
|
||||||
|
case 0x481a: {
|
||||||
|
if(r481x != 0x07) return 0x00;
|
||||||
|
|
||||||
|
unsigned addr = data_pointer();
|
||||||
|
unsigned adjust = data_adjust();
|
||||||
|
if(r4818 & 8) adjust = (int16)adjust; //16-bit sign extend
|
||||||
|
|
||||||
|
uint8 data = memory::cartrom.read(datarom_addr(addr + adjust));
|
||||||
|
if((r4818 & 0x60) == 0x60) {
|
||||||
|
if((r4818 & 16) == 0) {
|
||||||
|
set_data_pointer(addr + adjust);
|
||||||
|
} else {
|
||||||
|
set_data_adjust(adjust + adjust);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=========
|
||||||
|
//math unit
|
||||||
|
//=========
|
||||||
|
|
||||||
|
case 0x4820: return r4820;
|
||||||
|
case 0x4821: return r4821;
|
||||||
|
case 0x4822: return r4822;
|
||||||
|
case 0x4823: return r4823;
|
||||||
|
case 0x4824: return r4824;
|
||||||
|
case 0x4825: return r4825;
|
||||||
|
case 0x4826: return r4826;
|
||||||
|
case 0x4827: return r4827;
|
||||||
|
case 0x4828: return r4828;
|
||||||
|
case 0x4829: return r4829;
|
||||||
|
case 0x482a: return r482a;
|
||||||
|
case 0x482b: return r482b;
|
||||||
|
case 0x482c: return r482c;
|
||||||
|
case 0x482d: return r482d;
|
||||||
|
case 0x482e: return r482e;
|
||||||
|
case 0x482f: {
|
||||||
|
uint8 status = r482f;
|
||||||
|
r482f &= 0x7f;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===================
|
||||||
|
//memory mapping unit
|
||||||
|
//===================
|
||||||
|
|
||||||
|
case 0x4830: return r4830;
|
||||||
|
case 0x4831: return r4831;
|
||||||
|
case 0x4832: return r4832;
|
||||||
|
case 0x4833: return r4833;
|
||||||
|
case 0x4834: return r4834;
|
||||||
|
|
||||||
|
//====================
|
||||||
|
//real-time clock unit
|
||||||
|
//====================
|
||||||
|
|
||||||
|
case 0x4840: return r4840;
|
||||||
|
case 0x4841: {
|
||||||
|
if(rtc_state == RTCS_Inactive || rtc_state == RTCS_ModeSelect) return 0x00;
|
||||||
|
|
||||||
|
r4842 = 0x80;
|
||||||
|
uint8 data = memory::cartrtc.read(rtc_index);
|
||||||
|
rtc_index = (rtc_index + 1) & 15;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
case 0x4842: {
|
||||||
|
uint8 status = r4842;
|
||||||
|
r4842 &= 0x7f;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cpu.regs.mdr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPC7110::mmio_write(uint addr, uint8 data) {
|
||||||
|
addr &= 0xffff;
|
||||||
|
|
||||||
|
switch(addr) {
|
||||||
|
//==================
|
||||||
|
//decompression unit
|
||||||
|
//==================
|
||||||
|
|
||||||
|
case 0x4801: r4801 = data; break;
|
||||||
|
case 0x4802: r4802 = data; break;
|
||||||
|
case 0x4803: r4803 = data; break;
|
||||||
|
case 0x4804: r4804 = data; break;
|
||||||
|
case 0x4805: r4805 = data; break;
|
||||||
|
case 0x4806: {
|
||||||
|
r4806 = data;
|
||||||
|
|
||||||
|
unsigned table = (r4801 + (r4802 << 8) + (r4803 << 16));
|
||||||
|
unsigned index = (r4804 << 2);
|
||||||
|
unsigned length = (r4809 + (r480a << 8));
|
||||||
|
unsigned addr = datarom_addr(table + index);
|
||||||
|
unsigned mode = (memory::cartrom.read(addr + 0));
|
||||||
|
unsigned offset = (memory::cartrom.read(addr + 1) << 16)
|
||||||
|
+ (memory::cartrom.read(addr + 2) << 8)
|
||||||
|
+ (memory::cartrom.read(addr + 3) << 0);
|
||||||
|
|
||||||
|
decomp.init(mode, offset, (r4805 + (r4806 << 8)) << mode);
|
||||||
|
r480c = 0x80;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x4807: r4807 = data; break;
|
||||||
|
case 0x4808: r4808 = data; break;
|
||||||
|
case 0x4809: r4809 = data; break;
|
||||||
|
case 0x480a: r480a = data; break;
|
||||||
|
case 0x480b: r480b = data; break;
|
||||||
|
|
||||||
|
//==============
|
||||||
|
//data port unit
|
||||||
|
//==============
|
||||||
|
|
||||||
|
case 0x4811: r4811 = data; r481x |= 0x01; break;
|
||||||
|
case 0x4812: r4812 = data; r481x |= 0x02; break;
|
||||||
|
case 0x4813: r4813 = data; r481x |= 0x04; break;
|
||||||
|
case 0x4814: {
|
||||||
|
r4814 = data;
|
||||||
|
r4814_latch = true;
|
||||||
|
if(!r4815_latch) break;
|
||||||
|
if(!(r4818 & 2)) break;
|
||||||
|
if(r4818 & 0x10) break;
|
||||||
|
|
||||||
|
if((r4818 & 0x60) == 0x20) {
|
||||||
|
unsigned increment = data_adjust() & 0xff;
|
||||||
|
if(r4818 & 8) increment = (int8)increment; //8-bit sign extend
|
||||||
|
set_data_pointer(data_pointer() + increment);
|
||||||
|
} else if((r4818 & 0x60) == 0x40) {
|
||||||
|
unsigned increment = data_adjust();
|
||||||
|
if(r4818 & 8) increment = (int16)increment; //16-bit sign extend
|
||||||
|
set_data_pointer(data_pointer() + increment);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case 0x4815: {
|
||||||
|
r4815 = data;
|
||||||
|
r4815_latch = true;
|
||||||
|
if(!r4814_latch) break;
|
||||||
|
if(!(r4818 & 2)) break;
|
||||||
|
if(r4818 & 0x10) break;
|
||||||
|
|
||||||
|
if((r4818 & 0x60) == 0x20) {
|
||||||
|
unsigned increment = data_adjust() & 0xff;
|
||||||
|
if(r4818 & 8) increment = (int8)increment; //8-bit sign extend
|
||||||
|
set_data_pointer(data_pointer() + increment);
|
||||||
|
} else if((r4818 & 0x60) == 0x40) {
|
||||||
|
unsigned increment = data_adjust();
|
||||||
|
if(r4818 & 8) increment = (int16)increment; //16-bit sign extend
|
||||||
|
set_data_pointer(data_pointer() + increment);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
case 0x4816: r4816 = data; break;
|
||||||
|
case 0x4817: r4817 = data; break;
|
||||||
|
case 0x4818: {
|
||||||
|
if(r481x != 0x07) break;
|
||||||
|
|
||||||
|
r4818 = data;
|
||||||
|
r4814_latch = r4815_latch = false;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
//=========
|
||||||
|
//math unit
|
||||||
|
//=========
|
||||||
|
|
||||||
|
case 0x4820: r4820 = data; break;
|
||||||
|
case 0x4821: r4821 = data; break;
|
||||||
|
case 0x4822: r4822 = data; break;
|
||||||
|
case 0x4823: r4823 = data; break;
|
||||||
|
case 0x4824: r4824 = data; break;
|
||||||
|
case 0x4825: {
|
||||||
|
r4825 = data;
|
||||||
|
|
||||||
|
if(r482e & 1) {
|
||||||
|
//signed 16-bit x 16-bit multiplication
|
||||||
|
int16 r0 = (int16)(r4824 + (r4825 << 8));
|
||||||
|
int16 r1 = (int16)(r4820 + (r4821 << 8));
|
||||||
|
|
||||||
|
signed result = r0 * r1;
|
||||||
|
r4828 = result;
|
||||||
|
r4829 = result >> 8;
|
||||||
|
r482a = result >> 16;
|
||||||
|
r482b = result >> 24;
|
||||||
|
} else {
|
||||||
|
//unsigned 16-bit x 16-bit multiplication
|
||||||
|
uint16 r0 = (uint16)(r4824 + (r4825 << 8));
|
||||||
|
uint16 r1 = (uint16)(r4820 + (r4821 << 8));
|
||||||
|
|
||||||
|
unsigned result = r0 * r1;
|
||||||
|
r4828 = result;
|
||||||
|
r4829 = result >> 8;
|
||||||
|
r482a = result >> 16;
|
||||||
|
r482b = result >> 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
r482f = 0x80;
|
||||||
|
} break;
|
||||||
|
case 0x4826: r4826 = data; break;
|
||||||
|
case 0x4827: {
|
||||||
|
r4827 = data;
|
||||||
|
|
||||||
|
if(r482e & 1) {
|
||||||
|
//signed 32-bit x 16-bit division
|
||||||
|
int32 dividend = (int32)(r4820 + (r4821 << 8) + (r4822 << 16) + (r4823 << 24));
|
||||||
|
int16 divisor = (int16)(r4826 + (r4827 << 8));
|
||||||
|
|
||||||
|
int32 quotient;
|
||||||
|
int16 remainder;
|
||||||
|
|
||||||
|
if(divisor) {
|
||||||
|
quotient = (int32)(dividend / divisor);
|
||||||
|
remainder = (int32)(dividend % divisor);
|
||||||
|
} else {
|
||||||
|
//illegal division by zero
|
||||||
|
quotient = 0;
|
||||||
|
remainder = dividend & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
r4828 = quotient;
|
||||||
|
r4829 = quotient >> 8;
|
||||||
|
r482a = quotient >> 16;
|
||||||
|
r482b = quotient >> 24;
|
||||||
|
|
||||||
|
r482c = remainder;
|
||||||
|
r482d = remainder >> 8;
|
||||||
|
} else {
|
||||||
|
//unsigned 32-bit x 16-bit division
|
||||||
|
uint32 dividend = (uint32)(r4820 + (r4821 << 8) + (r4822 << 16) + (r4823 << 24));
|
||||||
|
uint16 divisor = (uint16)(r4826 + (r4827 << 8));
|
||||||
|
|
||||||
|
uint32 quotient;
|
||||||
|
uint16 remainder;
|
||||||
|
|
||||||
|
if(divisor) {
|
||||||
|
quotient = (uint32)(dividend / divisor);
|
||||||
|
remainder = (uint16)(dividend % divisor);
|
||||||
|
} else {
|
||||||
|
//illegal division by zero
|
||||||
|
quotient = 0;
|
||||||
|
remainder = dividend & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
r4828 = quotient;
|
||||||
|
r4829 = quotient >> 8;
|
||||||
|
r482a = quotient >> 16;
|
||||||
|
r482b = quotient >> 24;
|
||||||
|
|
||||||
|
r482c = remainder;
|
||||||
|
r482d = remainder >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
r482f = 0x80;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x482e: {
|
||||||
|
//reset math unit
|
||||||
|
r4820 = r4821 = r4822 = r4823 = 0;
|
||||||
|
r4824 = r4825 = r4826 = r4827 = 0;
|
||||||
|
r4828 = r4829 = r482a = r482b = 0;
|
||||||
|
r482c = r482d = 0;
|
||||||
|
|
||||||
|
r482e = data;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
//===================
|
||||||
|
//memory mapping unit
|
||||||
|
//===================
|
||||||
|
|
||||||
|
case 0x4830: r4830 = data; break;
|
||||||
|
|
||||||
|
case 0x4831: {
|
||||||
|
r4831 = data;
|
||||||
|
dx_offset = datarom_addr((data & 7) * 0x100000);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x4832: {
|
||||||
|
r4832 = data;
|
||||||
|
ex_offset = datarom_addr((data & 7) * 0x100000);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x4833: {
|
||||||
|
r4833 = data;
|
||||||
|
fx_offset = datarom_addr((data & 7) * 0x100000);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x4834: r4834 = data; break;
|
||||||
|
|
||||||
|
//====================
|
||||||
|
//real-time clock unit
|
||||||
|
//====================
|
||||||
|
|
||||||
|
case 0x4840: {
|
||||||
|
r4840 = data;
|
||||||
|
if(!(r4840 & 1)) {
|
||||||
|
//disable RTC
|
||||||
|
rtc_state = RTCS_Inactive;
|
||||||
|
update_time();
|
||||||
|
} else {
|
||||||
|
//enable RTC
|
||||||
|
r4842 = 0x80;
|
||||||
|
rtc_state = RTCS_ModeSelect;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case 0x4841: {
|
||||||
|
r4841 = data;
|
||||||
|
|
||||||
|
switch(rtc_state) {
|
||||||
|
case RTCS_ModeSelect: {
|
||||||
|
if(data == RTCM_Linear || data == RTCM_Indexed) {
|
||||||
|
r4842 = 0x80;
|
||||||
|
rtc_state = RTCS_IndexSelect;
|
||||||
|
rtc_mode = (RTC_Mode)data;
|
||||||
|
rtc_index = 0;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case RTCS_IndexSelect: {
|
||||||
|
r4842 = 0x80;
|
||||||
|
rtc_index = data & 15;
|
||||||
|
if(rtc_mode == RTCM_Linear) rtc_state = RTCS_Write;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case RTCS_Write: {
|
||||||
|
r4842 = 0x80;
|
||||||
|
|
||||||
|
//control register 0
|
||||||
|
if(rtc_index == 13) {
|
||||||
|
//increment second counter
|
||||||
|
if(data & 2) update_time(+1);
|
||||||
|
|
||||||
|
//round minute counter
|
||||||
|
if(data & 8) {
|
||||||
|
update_time();
|
||||||
|
|
||||||
|
unsigned second = memory::cartrtc.read( 0) + memory::cartrtc.read( 1) * 10;
|
||||||
|
//clear seconds
|
||||||
|
memory::cartrtc.write(0, 0);
|
||||||
|
memory::cartrtc.write(1, 0);
|
||||||
|
|
||||||
|
if(second >= 30) update_time(+60);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//control register 2
|
||||||
|
if(rtc_index == 15) {
|
||||||
|
//disable timer and clear second counter
|
||||||
|
if((data & 1) && !(memory::cartrtc.read(15) & 1)) {
|
||||||
|
update_time();
|
||||||
|
|
||||||
|
//clear seconds
|
||||||
|
memory::cartrtc.write(0, 0);
|
||||||
|
memory::cartrtc.write(1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//disable timer
|
||||||
|
if((data & 2) && !(memory::cartrtc.read(15) & 2)) {
|
||||||
|
update_time();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memory::cartrtc.write(rtc_index, data & 15);
|
||||||
|
rtc_index = (rtc_index + 1) & 15;
|
||||||
|
} break;
|
||||||
|
} //switch(rtc_state)
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 SPC7110::read(uint addr) {
|
||||||
|
//$[00-0f|80-8f]:[8000-ffff], $[c0-cf]:[0000-ffff] mapped directly to memory::cartrom
|
||||||
|
|
||||||
|
if((addr & 0xffe000) == 0x006000 || (addr & 0xffe000) == 0x306000) {
|
||||||
|
//$[00|30]:[6000-7fff]
|
||||||
|
return memory::cartram.read(addr & 0x1fff);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((addr & 0xff0000) == 0x500000) {
|
||||||
|
//$[50]:[0000-ffff]
|
||||||
|
return mmio_read(0x4800);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((addr & 0xf00000) == 0xd00000) {
|
||||||
|
//$[d0-df]:[0000-ffff]
|
||||||
|
return memory::cartrom.read(dx_offset + (addr & 0x0fffff));
|
||||||
|
}
|
||||||
|
|
||||||
|
if((addr & 0xf00000) == 0xe00000) {
|
||||||
|
//$[e0-ef]:[0000-ffff]
|
||||||
|
return memory::cartrom.read(ex_offset + (addr & 0x0fffff));
|
||||||
|
}
|
||||||
|
|
||||||
|
if((addr & 0xf00000) == 0xf00000) {
|
||||||
|
//$[f0-ff]:[0000-ffff]
|
||||||
|
return memory::cartrom.read(fx_offset + (addr & 0x0fffff));
|
||||||
|
}
|
||||||
|
|
||||||
|
return cpu.regs.mdr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SPC7110::write(uint addr, uint8 data) {
|
||||||
|
if((addr & 0xffe000) == 0x006000 || (addr & 0xffe000) == 0x306000) {
|
||||||
|
//$[00|30]:[6000-7fff]
|
||||||
|
if(r4830 & 0x80) memory::cartram.write(addr & 0x1fff, data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SPC7110::SPC7110() {
|
||||||
|
}
|
133
src/chip/spc7110/spc7110.h
Normal file
133
src/chip/spc7110/spc7110.h
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
/*****
|
||||||
|
* SPC7110 emulator - version 0.03 (2008-08-10)
|
||||||
|
* Copyright (c) 2008, byuu and neviksti
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* The software is provided "as is" and the author disclaims all warranties
|
||||||
|
* with regard to this software including all implied warranties of
|
||||||
|
* merchantibility and fitness, in no event shall the author be liable for
|
||||||
|
* any special, direct, indirect, or consequential damages or any damages
|
||||||
|
* whatsoever resulting from loss of use, data or profits, whether in an
|
||||||
|
* action of contract, negligence or other tortious action, arising out of
|
||||||
|
* or in connection with the use or performance of this software.
|
||||||
|
*****/
|
||||||
|
|
||||||
|
#include "decomp.h"
|
||||||
|
|
||||||
|
class SPC7110 : public MMIO, public Memory {
|
||||||
|
public:
|
||||||
|
void init();
|
||||||
|
void enable();
|
||||||
|
void power();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
unsigned datarom_addr(unsigned addr);
|
||||||
|
|
||||||
|
unsigned data_pointer();
|
||||||
|
unsigned data_adjust();
|
||||||
|
unsigned data_increment();
|
||||||
|
void set_data_pointer(unsigned addr);
|
||||||
|
void set_data_adjust(unsigned addr);
|
||||||
|
|
||||||
|
void update_time(int offset = 0);
|
||||||
|
time_t create_time();
|
||||||
|
|
||||||
|
uint8 mmio_read (uint addr);
|
||||||
|
void mmio_write(uint addr, uint8 data);
|
||||||
|
|
||||||
|
uint8 read (uint addr);
|
||||||
|
void write(uint addr, uint8 data);
|
||||||
|
|
||||||
|
//spc7110decomp
|
||||||
|
void decomp_init();
|
||||||
|
uint8 decomp_read();
|
||||||
|
|
||||||
|
SPC7110();
|
||||||
|
|
||||||
|
private:
|
||||||
|
//==================
|
||||||
|
//decompression unit
|
||||||
|
//==================
|
||||||
|
uint8 r4801; //compression table low
|
||||||
|
uint8 r4802; //compression table high
|
||||||
|
uint8 r4803; //compression table bank
|
||||||
|
uint8 r4804; //compression table index
|
||||||
|
uint8 r4805; //decompression buffer index low
|
||||||
|
uint8 r4806; //decompression buffer index high
|
||||||
|
uint8 r4807; //???
|
||||||
|
uint8 r4808; //???
|
||||||
|
uint8 r4809; //compression length low
|
||||||
|
uint8 r480a; //compression length high
|
||||||
|
uint8 r480b; //decompression control register
|
||||||
|
uint8 r480c; //decompression status
|
||||||
|
|
||||||
|
SPC7110Decomp decomp;
|
||||||
|
|
||||||
|
//==============
|
||||||
|
//data port unit
|
||||||
|
//==============
|
||||||
|
uint8 r4811; //data pointer low
|
||||||
|
uint8 r4812; //data pointer high
|
||||||
|
uint8 r4813; //data pointer bank
|
||||||
|
uint8 r4814; //data adjust low
|
||||||
|
uint8 r4815; //data adjust high
|
||||||
|
uint8 r4816; //data increment low
|
||||||
|
uint8 r4817; //data increment high
|
||||||
|
uint8 r4818; //data port control register
|
||||||
|
|
||||||
|
uint8 r481x;
|
||||||
|
|
||||||
|
bool r4814_latch;
|
||||||
|
bool r4815_latch;
|
||||||
|
|
||||||
|
//=========
|
||||||
|
//math unit
|
||||||
|
//=========
|
||||||
|
uint8 r4820; //16-bit multiplicand B0, 32-bit dividend B0
|
||||||
|
uint8 r4821; //16-bit multiplicand B1, 32-bit dividend B1
|
||||||
|
uint8 r4822; //32-bit dividend B2
|
||||||
|
uint8 r4823; //32-bit dividend B3
|
||||||
|
uint8 r4824; //16-bit multiplier B0
|
||||||
|
uint8 r4825; //16-bit multiplier B1
|
||||||
|
uint8 r4826; //16-bit divisor B0
|
||||||
|
uint8 r4827; //16-bit divisor B1
|
||||||
|
uint8 r4828; //32-bit product B0, 32-bit quotient B0
|
||||||
|
uint8 r4829; //32-bit product B1, 32-bit quotient B1
|
||||||
|
uint8 r482a; //32-bit product B2, 32-bit quotient B2
|
||||||
|
uint8 r482b; //32-bit product B3, 32-bit quotient B3
|
||||||
|
uint8 r482c; //16-bit remainder B0
|
||||||
|
uint8 r482d; //16-bit remainder B1
|
||||||
|
uint8 r482e; //math control register
|
||||||
|
uint8 r482f; //math status
|
||||||
|
|
||||||
|
//===================
|
||||||
|
//memory mapping unit
|
||||||
|
//===================
|
||||||
|
uint8 r4830; //SRAM write enable
|
||||||
|
uint8 r4831; //$[d0-df]:[0000-ffff] mapping
|
||||||
|
uint8 r4832; //$[e0-ef]:[0000-ffff] mapping
|
||||||
|
uint8 r4833; //$[f0-ff]:[0000-ffff] mapping
|
||||||
|
uint8 r4834; //???
|
||||||
|
|
||||||
|
unsigned dx_offset;
|
||||||
|
unsigned ex_offset;
|
||||||
|
unsigned fx_offset;
|
||||||
|
|
||||||
|
//====================
|
||||||
|
//real-time clock unit
|
||||||
|
//====================
|
||||||
|
uint8 r4840; //RTC latch
|
||||||
|
uint8 r4841; //RTC index/data port
|
||||||
|
uint8 r4842; //RTC status
|
||||||
|
|
||||||
|
enum RTC_State { RTCS_Inactive, RTCS_ModeSelect, RTCS_IndexSelect, RTCS_Write } rtc_state;
|
||||||
|
enum RTC_Mode { RTCM_Linear = 0x03, RTCM_Indexed = 0x0c } rtc_mode;
|
||||||
|
unsigned rtc_index;
|
||||||
|
|
||||||
|
static const unsigned months[12];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern SPC7110 spc7110;
|
@@ -1,189 +1,213 @@
|
|||||||
/*
|
#include "../../base.h"
|
||||||
S-RTC chip emulation
|
|
||||||
Used by Hudson Soft in Dai Kaijuu Monogatari II and Far East of Eden Zero.
|
const unsigned SRTC::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||||
Currently, only the former is supported by bsnes.
|
|
||||||
|
void SRTC::init() {
|
||||||
Original S-RTC emulation code via John Weidman/SNES9x
|
}
|
||||||
Rewritten for compatibility with bsnes via byuu
|
|
||||||
|
void SRTC::enable() {
|
||||||
The S-RTC is a real-time clock chip that was added to the above two carts
|
memory::mmio.map(0x2800, *this);
|
||||||
to allow the games to maintain the current time, even when the game was not
|
memory::mmio.map(0x2801, *this);
|
||||||
powered on. Thus allowing special events at certain times, and on certain
|
}
|
||||||
dates. Hudson Soft called this the PLG (Player's Life Gameplay System).
|
|
||||||
|
void SRTC::power() {
|
||||||
This chip is a special case to the term 'emulation' itself.
|
reset();
|
||||||
There are a few different ways to go about emulating this chip, and each
|
}
|
||||||
result in a different style of emulation.
|
|
||||||
|
void SRTC::reset() {
|
||||||
The first is to simply return the current PC system time when the S-RTC is
|
rtc_mode = RTCM_Read;
|
||||||
read from. This emulates the original S-RTC in the sense that it always
|
rtc_index = -1;
|
||||||
returns the true current time, ignoring the speed that the SNES itself is
|
update_time();
|
||||||
running at. The downside to this method is that you lose the ability to set
|
}
|
||||||
the time to whatever you choose inside the game itself. It will always return
|
|
||||||
the true time, regardless. This can be overcome by changing the PC system time,
|
void SRTC::update_time() {
|
||||||
which actually adds a greater degree of control over event timing, very useful
|
time_t rtc_time;
|
||||||
for emulation. It also has a timeshifting flaw discussed below.
|
rtc_time = memory::cartrtc.read(16);
|
||||||
|
rtc_time |= memory::cartrtc.read(17) << 8;
|
||||||
The second is to run the S-RTC relative to the SNES speed. This means that
|
rtc_time |= memory::cartrtc.read(18) << 16;
|
||||||
if the emulator is sped up (via fast forward key, frameskipping, etc), or
|
rtc_time |= memory::cartrtc.read(19) << 24;
|
||||||
slowed down (via slowdown key, system bottlenecking, etc); the time increments
|
|
||||||
slower, thus ~60 frames on the SNES equal one second. Without this, timeshifting
|
time_t current_time = time(0);
|
||||||
will occur between the S-RTC and the real SNES.
|
if(current_time > rtc_time) {
|
||||||
|
unsigned second = memory::cartrtc.read( 0) + memory::cartrtc.read( 1) * 10;
|
||||||
The third and final method is to save a copy of the local system time when the
|
unsigned minute = memory::cartrtc.read( 2) + memory::cartrtc.read( 3) * 10;
|
||||||
S-RTC is initially set, and compare the current system time against this value
|
unsigned hour = memory::cartrtc.read( 4) + memory::cartrtc.read( 5) * 10;
|
||||||
when setting the S-RTC time. This overcomes the first methods' shortcoming of
|
unsigned day = memory::cartrtc.read( 6) + memory::cartrtc.read( 7) * 10;
|
||||||
not allowing the player to set the time in-game, however a new problem arises.
|
unsigned month = memory::cartrtc.read( 8);
|
||||||
You now have to save the time when the RTC was initially set to both savestates
|
unsigned year = memory::cartrtc.read( 9) + memory::cartrtc.read(10) * 10 + memory::cartrtc.read(11) * 100;
|
||||||
and to save-game data. This would require an extra file, or the breaking of
|
unsigned weekday = memory::cartrtc.read(12);
|
||||||
perhaps the only standard format (.srm savegame backups) in the entire SNES
|
|
||||||
emulation scene. You also give up the control of being able to override the
|
day--;
|
||||||
RTC clock at will via the PC system time outside of emulation.
|
month--;
|
||||||
The first method has another advantage over the third: Dai Kaijuu Monogatari II
|
year += 1000;
|
||||||
only allows dates in the range of the years 1996-2199. The first method gets
|
|
||||||
around this limitation. But who knows, maybe it will break something in the
|
second += (unsigned)(current_time - rtc_time);
|
||||||
game if the date exceeds 2199... I guess we'll worry about that in two hundred
|
|
||||||
years from now.
|
while(second >= 60) {
|
||||||
|
second -= 60;
|
||||||
For my implementation, I chose to go with the first method. Both for simplicity
|
|
||||||
and because I did not wish to create a new method for saving the system time
|
minute++;
|
||||||
whenever the RTC is set.
|
if(minute < 60) continue;
|
||||||
*/
|
minute = 0;
|
||||||
|
|
||||||
#include "../../base.h"
|
hour++;
|
||||||
|
if(hour < 24) continue;
|
||||||
void SRTC::set_time() {
|
hour = 0;
|
||||||
time_t rawtime;
|
|
||||||
tm *t;
|
day++;
|
||||||
::time(&rawtime);
|
weekday = (weekday + 1) % 7;
|
||||||
t = localtime(&rawtime);
|
unsigned days = months[month % 12];
|
||||||
|
if(days == 28) {
|
||||||
//see srtc.h for format of srtc.data[]
|
bool leapyear = false;
|
||||||
srtc.data[0] = t->tm_sec % 10;
|
if((year % 4) == 0) {
|
||||||
srtc.data[1] = t->tm_sec / 10;
|
leapyear = true;
|
||||||
srtc.data[2] = t->tm_min % 10;
|
if((year % 100) == 0 && (year % 400) != 0) leapyear = false;
|
||||||
srtc.data[3] = t->tm_min / 10;
|
}
|
||||||
srtc.data[4] = t->tm_hour % 10;
|
if(leapyear) days++;
|
||||||
srtc.data[5] = t->tm_hour / 10;
|
}
|
||||||
srtc.data[6] = t->tm_mday % 10;
|
if(day < days) continue;
|
||||||
srtc.data[7] = t->tm_mday / 10;
|
day = 0;
|
||||||
srtc.data[8] = t->tm_mon + 1;
|
|
||||||
srtc.data[9] = t->tm_year % 10;
|
month++;
|
||||||
srtc.data[10] = (t->tm_year / 10) % 10;
|
if(month < 12) continue;
|
||||||
srtc.data[11] = 9 + (t->tm_year / 100);
|
month = 0;
|
||||||
srtc.data[12] = t->tm_wday;
|
|
||||||
}
|
year++;
|
||||||
|
}
|
||||||
void SRTC::init() {}
|
|
||||||
|
day++;
|
||||||
void SRTC::enable() {
|
month++;
|
||||||
memory::mmio.map(0x2800, *this);
|
year -= 1000;
|
||||||
memory::mmio.map(0x2801, *this);
|
|
||||||
}
|
memory::cartrtc.write( 0, second % 10);
|
||||||
|
memory::cartrtc.write( 1, second / 10);
|
||||||
void SRTC::power() {
|
memory::cartrtc.write( 2, minute % 10);
|
||||||
memset(&srtc, 0, sizeof(srtc));
|
memory::cartrtc.write( 3, minute / 10);
|
||||||
reset();
|
memory::cartrtc.write( 4, hour % 10);
|
||||||
}
|
memory::cartrtc.write( 5, hour / 10);
|
||||||
|
memory::cartrtc.write( 6, day % 10);
|
||||||
void SRTC::reset() {
|
memory::cartrtc.write( 7, day / 10);
|
||||||
srtc.index = -1;
|
memory::cartrtc.write( 8, month);
|
||||||
srtc.mode = SRTC_READ;
|
memory::cartrtc.write( 9, year % 10);
|
||||||
}
|
memory::cartrtc.write(10, (year / 10) % 10);
|
||||||
|
memory::cartrtc.write(11, year / 100);
|
||||||
uint8 SRTC::mmio_read(uint addr) {
|
memory::cartrtc.write(12, weekday % 7);
|
||||||
switch(addr & 0xffff) {
|
}
|
||||||
|
|
||||||
case 0x2800: {
|
memory::cartrtc.write(16, current_time);
|
||||||
if(srtc.mode == SRTC_READ) {
|
memory::cartrtc.write(17, current_time >> 8);
|
||||||
if(srtc.index < 0) {
|
memory::cartrtc.write(18, current_time >> 16);
|
||||||
set_time();
|
memory::cartrtc.write(19, current_time >> 24);
|
||||||
srtc.index++;
|
}
|
||||||
return 0x0f; //send start message
|
|
||||||
} else if(srtc.index > MAX_SRTC_INDEX) {
|
//returns day of week for specified date
|
||||||
srtc.index = -1;
|
//eg 0 = Sunday, 1 = Monday, ... 6 = Saturday
|
||||||
return 0x0f; //send finished message
|
//usage: weekday(2008, 1, 1) returns weekday of January 1st, 2008
|
||||||
} else {
|
unsigned SRTC::weekday(unsigned year, unsigned month, unsigned day) {
|
||||||
return srtc.data[srtc.index++];
|
unsigned y = 1900, m = 1; //epoch is 1900-01-01
|
||||||
}
|
unsigned sum = 0; //number of days passed since epoch
|
||||||
} else {
|
|
||||||
return 0x00;
|
year = max(1900, year);
|
||||||
}
|
month = max(1, min(12, month));
|
||||||
} break;
|
day = max(1, min(31, day));
|
||||||
|
|
||||||
case 0x2801: {
|
while(y < year) {
|
||||||
} break;
|
bool leapyear = false;
|
||||||
|
if((y % 4) == 0) {
|
||||||
}
|
leapyear = true;
|
||||||
|
if((y % 100) == 0 && (y % 400) != 0) leapyear = false;
|
||||||
return cpu.regs.mdr;
|
}
|
||||||
}
|
sum += leapyear ? 366 : 365;
|
||||||
|
y++;
|
||||||
//Please see notes above about the implementation of the S-RTC
|
}
|
||||||
//Writes are stored the srtc.data[] array, but they are ignored
|
|
||||||
//as reads will refresh the data array with the current system
|
while(m < month) {
|
||||||
//time. The write method is only here for the sake of faux
|
unsigned days = months[m - 1];
|
||||||
//emulation of the real hardware.
|
if(days == 28) {
|
||||||
void SRTC::mmio_write(uint addr, uint8 data) {
|
bool leapyear = false;
|
||||||
switch(addr & 0xffff) {
|
if((y % 4) == 0) {
|
||||||
|
leapyear = true;
|
||||||
case 0x2800: {
|
if((y % 100) == 0 && (y % 400) != 0) leapyear = false;
|
||||||
} break;
|
}
|
||||||
|
if(leapyear) days++;
|
||||||
case 0x2801: {
|
}
|
||||||
data &= 0x0f; //only the low four bits are used
|
sum += days;
|
||||||
|
m++;
|
||||||
if(data >= 0x0d) {
|
}
|
||||||
switch(data) {
|
|
||||||
case 0x0d:
|
sum += day - 1;
|
||||||
srtc.mode = SRTC_READ;
|
return (sum + 1) % 7; //1900-01-01 was a Monday
|
||||||
srtc.index = -1;
|
}
|
||||||
break;
|
|
||||||
case 0x0e:
|
uint8 SRTC::mmio_read(uint addr) {
|
||||||
srtc.mode = SRTC_COMMAND;
|
addr &= 0xffff;
|
||||||
break;
|
|
||||||
case 0x0f:
|
if(addr == 0x2800) {
|
||||||
//unknown behaviour
|
if(rtc_mode != RTCM_Read) return 0x00;
|
||||||
break;
|
|
||||||
}
|
if(rtc_index < 0) {
|
||||||
return;
|
update_time();
|
||||||
}
|
rtc_index++;
|
||||||
|
return 0x0f;
|
||||||
if(srtc.mode == SRTC_WRITE) {
|
} else if(rtc_index > 12) {
|
||||||
if(srtc.index >= 0 && srtc.index < MAX_SRTC_INDEX) {
|
rtc_index = -1;
|
||||||
srtc.data[srtc.index++] = data;
|
return 0x0f;
|
||||||
|
} else {
|
||||||
if(srtc.index == MAX_SRTC_INDEX) {
|
return memory::cartrtc.read(rtc_index++);
|
||||||
//all S-RTC data has been loaded by program
|
}
|
||||||
srtc.data[srtc.index++] = 0x00; //day_of_week
|
}
|
||||||
}
|
|
||||||
}
|
return cpu.regs.mdr;
|
||||||
} else if(srtc.mode == SRTC_COMMAND) {
|
}
|
||||||
switch(data) {
|
|
||||||
case SRTC_COMMAND_CLEAR:
|
void SRTC::mmio_write(uint addr, uint8 data) {
|
||||||
memset(srtc.data, 0, MAX_SRTC_INDEX + 1);
|
addr &= 0xffff;
|
||||||
srtc.index = -1;
|
|
||||||
srtc.mode = SRTC_READY;
|
if(addr == 0x2801) {
|
||||||
break;
|
data &= 0x0f; //only the low four bits are used
|
||||||
case SRTC_COMMAND_WRITE:
|
|
||||||
srtc.index = 0;
|
if(data == 0x0d) {
|
||||||
srtc.mode = SRTC_WRITE;
|
rtc_mode = RTCM_Read;
|
||||||
break;
|
rtc_index = -1;
|
||||||
default:
|
return;
|
||||||
//unknown behaviour
|
}
|
||||||
srtc.mode = SRTC_READY;
|
|
||||||
break;
|
if(data == 0x0e) {
|
||||||
}
|
rtc_mode = RTCM_Command;
|
||||||
} else {
|
return;
|
||||||
if(srtc.mode == SRTC_READ) {
|
}
|
||||||
//ignore writes while in read mode
|
|
||||||
} else if(srtc.mode == SRTC_READY) {
|
if(data == 0x0f) return; //unknown behavior
|
||||||
//unknown behaviour
|
|
||||||
}
|
if(rtc_mode == RTCM_Write) {
|
||||||
}
|
if(rtc_index >= 0 && rtc_index < 12) {
|
||||||
} break;
|
memory::cartrtc.write(rtc_index++, data);
|
||||||
|
|
||||||
}
|
if(rtc_index == 12) {
|
||||||
}
|
//day of week is automatically calculated and written
|
||||||
|
unsigned day = memory::cartrtc.read( 6) + memory::cartrtc.read( 7) * 10;
|
||||||
SRTC::SRTC() {}
|
unsigned month = memory::cartrtc.read( 8);
|
||||||
|
unsigned year = memory::cartrtc.read( 9) + memory::cartrtc.read(10) * 10 + memory::cartrtc.read(11) * 100;
|
||||||
|
year += 1000;
|
||||||
|
|
||||||
|
memory::cartrtc.write(rtc_index++, weekday(year, month, day));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(rtc_mode == RTCM_Command) {
|
||||||
|
if(data == 0) {
|
||||||
|
rtc_mode = RTCM_Write;
|
||||||
|
rtc_index = 0;
|
||||||
|
} else if(data == 4) {
|
||||||
|
rtc_mode = RTCM_Ready;
|
||||||
|
rtc_index = -1;
|
||||||
|
for(unsigned i = 0; i < 13; i++) memory::cartrtc.write(i, 0);
|
||||||
|
} else {
|
||||||
|
//unknown behavior
|
||||||
|
rtc_mode = RTCM_Ready;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SRTC::SRTC() {
|
||||||
|
}
|
||||||
|
@@ -1,52 +1,22 @@
|
|||||||
class SRTC : public MMIO {
|
class SRTC : public MMIO {
|
||||||
public:
|
public:
|
||||||
enum { MAX_SRTC_INDEX = 0x0c };
|
void update_time();
|
||||||
|
unsigned weekday(unsigned year, unsigned month, unsigned day);
|
||||||
enum {
|
|
||||||
SRTC_READ = 0,
|
void init();
|
||||||
SRTC_WRITE,
|
void enable();
|
||||||
SRTC_COMMAND,
|
void power();
|
||||||
SRTC_READY
|
void reset();
|
||||||
};
|
|
||||||
|
uint8 mmio_read (uint addr);
|
||||||
enum {
|
void mmio_write(uint addr, uint8 data);
|
||||||
SRTC_COMMAND_WRITE = 0,
|
|
||||||
SRTC_COMMAND_CLEAR = 4
|
SRTC();
|
||||||
};
|
|
||||||
|
private:
|
||||||
/******************************
|
static const unsigned months[12];
|
||||||
[srtc.data structure]
|
enum RTC_Mode { RTCM_Ready, RTCM_Command, RTCM_Read, RTCM_Write } rtc_mode;
|
||||||
Index Description Range
|
signed rtc_index;
|
||||||
----- ----------- -----
|
};
|
||||||
0 Seconds low 0-9
|
|
||||||
1 Seconds high 0-5
|
extern SRTC srtc;
|
||||||
2 Minutes low 0-9
|
|
||||||
3 Minutes high 0-5
|
|
||||||
4 Hour low 0-9
|
|
||||||
5 Hour high 0-2
|
|
||||||
6 Day low 0-9
|
|
||||||
7 Day high 0-3
|
|
||||||
8 Month 1-12
|
|
||||||
9 Year ones 0-9
|
|
||||||
10 Year tens 0-9
|
|
||||||
11 Year hundreds 9-11 (9=19xx, 10=20xx, 11=21xx)
|
|
||||||
12 Day of week 0-6 (0=Sunday, ...)
|
|
||||||
******************************/
|
|
||||||
struct {
|
|
||||||
int8 index;
|
|
||||||
uint8 mode;
|
|
||||||
uint8 data[MAX_SRTC_INDEX + 1];
|
|
||||||
} srtc;
|
|
||||||
void set_time();
|
|
||||||
void init();
|
|
||||||
void enable();
|
|
||||||
void power();
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
uint8 mmio_read (uint addr);
|
|
||||||
void mmio_write(uint addr, uint8 data);
|
|
||||||
|
|
||||||
SRTC();
|
|
||||||
};
|
|
||||||
|
|
||||||
extern SRTC srtc;
|
|
||||||
|
@@ -44,8 +44,9 @@ string file_updatepath(const char *req_file, const char *req_path) {
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
string_setting Path::base("path.base",
|
string_setting Path::base("path.base", "Path that bsnes resides in", "");
|
||||||
"Path that bsnes resides in", "");
|
string_setting Path::user("path.user", "Path to user folder", "");
|
||||||
|
|
||||||
string_setting Path::rom(config(), "path.rom",
|
string_setting Path::rom(config(), "path.rom",
|
||||||
"Default path to look for ROM files in (\"\" = use default directory)", "");
|
"Default path to look for ROM files in (\"\" = use default directory)", "");
|
||||||
string_setting Path::patch(config(), "path.patch",
|
string_setting Path::patch(config(), "path.patch",
|
||||||
@@ -57,15 +58,15 @@ string_setting Path::cheat(config(), "path.cheat",
|
|||||||
string_setting Path::bsx(config(), "path.bsx", "", "");
|
string_setting Path::bsx(config(), "path.bsx", "", "");
|
||||||
string_setting Path::st(config(), "path.st", "", "");
|
string_setting Path::st(config(), "path.st", "", "");
|
||||||
|
|
||||||
integral_setting SNES::controller_port0(config(), "snes.controller_port_1",
|
integral_setting SNES::controller_port1(config(), "snes.controller_port1",
|
||||||
"Controller attached to SNES port 1", integral_setting::decimal, ::SNES::Input::DeviceIDJoypad1);
|
"Controller attached to SNES port 1", integral_setting::decimal, ::SNES::Input::DeviceJoypad);
|
||||||
integral_setting SNES::controller_port1(config(), "snes.controller_port_2",
|
integral_setting SNES::controller_port2(config(), "snes.controller_port2",
|
||||||
"Controller attached to SNES port 2", integral_setting::decimal, ::SNES::Input::DeviceIDJoypad2);
|
"Controller attached to SNES port 2", integral_setting::decimal, ::SNES::Input::DeviceJoypad);
|
||||||
|
|
||||||
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);
|
||||||
integral_setting CPU::pal_clock_rate(config(), "cpu.pal_clock_rate",
|
integral_setting CPU::pal_clock_rate(config(), "cpu.pal_clock_rate",
|
||||||
"PAL S-CPU clock rate (in hz)", integral_setting::decimal, 21281370);
|
"PAL S-CPU clock rate (in hz)", integral_setting::decimal, 21281370);
|
||||||
integral_setting CPU::wram_init_value(config(), "cpu.wram_init_value",
|
integral_setting CPU::wram_init_value(config(), "cpu.wram_init_value",
|
||||||
"Value to initialize 128k WRAM to upon power cycle.\n"
|
"Value to initialize 128k WRAM to upon power cycle.\n"
|
||||||
"Note that on real hardware, this value is undefined; meaning it can vary\n"
|
"Note that on real hardware, this value is undefined; meaning it can vary\n"
|
||||||
@@ -80,13 +81,10 @@ integral_setting CPU::wram_init_value(config(), "cpu.wram_init_value",
|
|||||||
"which do not properly initialize WRAM upon power cycle.\n",
|
"which do not properly initialize WRAM upon power cycle.\n",
|
||||||
integral_setting::hex, 0x55);
|
integral_setting::hex, 0x55);
|
||||||
|
|
||||||
integral_setting CPU::hdma_enable("cpu.hdma_enable",
|
|
||||||
"Enable HDMA effects", integral_setting::boolean, true);
|
|
||||||
|
|
||||||
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, 24606720);
|
"NTSC S-SMP clock rate (in hz)", integral_setting::decimal, 32040 * 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, 24606720);
|
"PAL S-SMP clock rate (in hz)", integral_setting::decimal, 32040 * 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",
|
||||||
|
@@ -10,19 +10,18 @@ extern struct File {
|
|||||||
} file;
|
} file;
|
||||||
|
|
||||||
extern struct Path {
|
extern struct Path {
|
||||||
static string_setting base, rom, patch, save, cheat;
|
static string_setting base, user, rom, patch, save, cheat;
|
||||||
static string_setting bsx, st;
|
static string_setting bsx, st;
|
||||||
} path;
|
} path;
|
||||||
|
|
||||||
extern struct SNES {
|
extern struct SNES {
|
||||||
static integral_setting controller_port0;
|
|
||||||
static integral_setting controller_port1;
|
static integral_setting controller_port1;
|
||||||
|
static integral_setting controller_port2;
|
||||||
} snes;
|
} snes;
|
||||||
|
|
||||||
extern struct CPU {
|
extern struct CPU {
|
||||||
static integral_setting ntsc_clock_rate, pal_clock_rate;
|
static integral_setting ntsc_clock_rate, pal_clock_rate;
|
||||||
static integral_setting wram_init_value;
|
static integral_setting wram_init_value;
|
||||||
static integral_setting hdma_enable;
|
|
||||||
} cpu;
|
} cpu;
|
||||||
|
|
||||||
extern struct SMP {
|
extern struct SMP {
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
#include "dcpu.cpp"
|
#include "dcpu.cpp"
|
||||||
|
|
||||||
CPU::CPU() {
|
CPU::CPU() {
|
||||||
cpu_version = 1;
|
cpu_version = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
CPU::~CPU() {
|
CPU::~CPU() {
|
||||||
|
@@ -15,7 +15,8 @@ public:
|
|||||||
virtual uint16 hcounter() = 0;
|
virtual uint16 hcounter() = 0;
|
||||||
virtual uint16 hdot() = 0;
|
virtual uint16 hdot() = 0;
|
||||||
|
|
||||||
virtual uint8 pio_status() = 0;
|
virtual uint8 pio() = 0;
|
||||||
|
virtual bool joylatch() = 0;
|
||||||
virtual uint8 port_read(uint8 port) = 0;
|
virtual uint8 port_read(uint8 port) = 0;
|
||||||
virtual void port_write(uint8 port, uint8 value) = 0;
|
virtual void port_write(uint8 port, uint8 value) = 0;
|
||||||
|
|
||||||
|
@@ -1,19 +1,32 @@
|
|||||||
|
template<int mask>
|
||||||
|
struct CPUFlag {
|
||||||
|
uint8 &data;
|
||||||
|
|
||||||
|
inline operator bool() const { return data & mask; }
|
||||||
|
inline CPUFlag& operator=(bool i) { data = (data & ~mask) | (-i & mask); return *this; }
|
||||||
|
|
||||||
|
CPUFlag(uint8 &data_) : data(data_) {}
|
||||||
|
};
|
||||||
|
|
||||||
class CPURegFlags {
|
class CPURegFlags {
|
||||||
public:
|
public:
|
||||||
union {
|
uint8 data;
|
||||||
uint8 data;
|
CPUFlag<0x80> n;
|
||||||
struct {
|
CPUFlag<0x40> v;
|
||||||
bool order_msb8(n:1, v:1, m:1, x:1, d:1, i:1, z:1, c:1);
|
CPUFlag<0x20> m;
|
||||||
};
|
CPUFlag<0x10> x;
|
||||||
};
|
CPUFlag<0x08> d;
|
||||||
|
CPUFlag<0x04> i;
|
||||||
|
CPUFlag<0x02> z;
|
||||||
|
CPUFlag<0x01> c;
|
||||||
|
|
||||||
inline operator unsigned() const { return data; }
|
inline operator unsigned() const { return data; }
|
||||||
template<typename T> inline unsigned operator = (const T i) { data = i; return data; }
|
inline unsigned operator = (unsigned i) { data = i; return data; }
|
||||||
template<typename T> inline unsigned operator |= (const T i) { data |= i; return data; }
|
inline unsigned operator |= (unsigned i) { data |= i; return data; }
|
||||||
template<typename T> inline unsigned operator ^= (const T i) { data ^= i; return data; }
|
inline unsigned operator ^= (unsigned i) { data ^= i; return data; }
|
||||||
template<typename T> inline unsigned operator &= (const T i) { data &= i; return data; }
|
inline unsigned operator &= (unsigned i) { data &= i; return data; }
|
||||||
|
|
||||||
CPURegFlags() : data(0) {}
|
CPURegFlags() : data(0), n(data), v(data), m(data), x(data), d(data), i(data), z(data), c(data) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CPUReg16 {
|
class CPUReg16 {
|
||||||
@@ -24,17 +37,17 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
inline operator unsigned() const { return w; }
|
inline operator unsigned() const { return w; }
|
||||||
template<typename T> inline unsigned operator = (const T i) { w = i; return w; }
|
inline unsigned operator = (unsigned i) { w = i; return w; }
|
||||||
template<typename T> inline unsigned operator |= (const T i) { w |= i; return w; }
|
inline unsigned operator |= (unsigned i) { w |= i; return w; }
|
||||||
template<typename T> inline unsigned operator ^= (const T i) { w ^= i; return w; }
|
inline unsigned operator ^= (unsigned i) { w ^= i; return w; }
|
||||||
template<typename T> inline unsigned operator &= (const T i) { w &= i; return w; }
|
inline unsigned operator &= (unsigned i) { w &= i; return w; }
|
||||||
template<typename T> inline unsigned operator <<= (const T i) { w <<= i; return w; }
|
inline unsigned operator <<= (unsigned i) { w <<= i; return w; }
|
||||||
template<typename T> inline unsigned operator >>= (const T i) { w >>= i; return w; }
|
inline unsigned operator >>= (unsigned i) { w >>= i; return w; }
|
||||||
template<typename T> inline unsigned operator += (const T i) { w += i; return w; }
|
inline unsigned operator += (unsigned i) { w += i; return w; }
|
||||||
template<typename T> inline unsigned operator -= (const T i) { w -= i; return w; }
|
inline unsigned operator -= (unsigned i) { w -= i; return w; }
|
||||||
template<typename T> inline unsigned operator *= (const T i) { w *= i; return w; }
|
inline unsigned operator *= (unsigned i) { w *= i; return w; }
|
||||||
template<typename T> inline unsigned operator /= (const T i) { w /= i; return w; }
|
inline unsigned operator /= (unsigned i) { w /= i; return w; }
|
||||||
template<typename T> inline unsigned operator %= (const T i) { w %= i; return w; }
|
inline unsigned operator %= (unsigned i) { w %= i; return w; }
|
||||||
|
|
||||||
CPUReg16() : w(0) {}
|
CPUReg16() : w(0) {}
|
||||||
};
|
};
|
||||||
@@ -48,17 +61,17 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
inline operator unsigned() const { return d; }
|
inline operator unsigned() const { return d; }
|
||||||
template<typename T> inline unsigned operator = (const T i) { d = uclip<24>(i); return d; }
|
inline unsigned operator = (unsigned i) { d = uclip<24>(i); return d; }
|
||||||
template<typename T> inline unsigned operator |= (const T i) { d = uclip<24>(d | i); return d; }
|
inline unsigned operator |= (unsigned i) { d = uclip<24>(d | i); return d; }
|
||||||
template<typename T> inline unsigned operator ^= (const T i) { d = uclip<24>(d ^ i); return d; }
|
inline unsigned operator ^= (unsigned i) { d = uclip<24>(d ^ i); return d; }
|
||||||
template<typename T> inline unsigned operator &= (const T i) { d = uclip<24>(d & i); return d; }
|
inline unsigned operator &= (unsigned i) { d = uclip<24>(d & i); return d; }
|
||||||
template<typename T> inline unsigned operator <<= (const T i) { d = uclip<24>(d << i); return d; }
|
inline unsigned operator <<= (unsigned i) { d = uclip<24>(d << i); return d; }
|
||||||
template<typename T> inline unsigned operator >>= (const T i) { d = uclip<24>(d >> i); return d; }
|
inline unsigned operator >>= (unsigned i) { d = uclip<24>(d >> i); return d; }
|
||||||
template<typename T> inline unsigned operator += (const T i) { d = uclip<24>(d + i); return d; }
|
inline unsigned operator += (unsigned i) { d = uclip<24>(d + i); return d; }
|
||||||
template<typename T> inline unsigned operator -= (const T i) { d = uclip<24>(d - i); return d; }
|
inline unsigned operator -= (unsigned i) { d = uclip<24>(d - i); return d; }
|
||||||
template<typename T> inline unsigned operator *= (const T i) { d = uclip<24>(d * i); return d; }
|
inline unsigned operator *= (unsigned i) { d = uclip<24>(d * i); return d; }
|
||||||
template<typename T> inline unsigned operator /= (const T i) { d = uclip<24>(d / i); return d; }
|
inline unsigned operator /= (unsigned i) { d = uclip<24>(d / i); return d; }
|
||||||
template<typename T> inline unsigned operator %= (const T i) { d = uclip<24>(d % i); return d; }
|
inline unsigned operator %= (unsigned i) { d = uclip<24>(d % i); return d; }
|
||||||
|
|
||||||
CPUReg24() : d(0) {}
|
CPUReg24() : d(0) {}
|
||||||
};
|
};
|
||||||
@@ -70,6 +83,6 @@ public:
|
|||||||
CPURegFlags p;
|
CPURegFlags p;
|
||||||
uint8 db;
|
uint8 db;
|
||||||
uint8 mdr;
|
uint8 mdr;
|
||||||
bool e;
|
bool e;
|
||||||
CPURegs() : db(0), mdr(0x00), e(false) {}
|
CPURegs() : db(0), mdr(0), e(false) {}
|
||||||
};
|
};
|
||||||
|
@@ -2,210 +2,204 @@
|
|||||||
|
|
||||||
//op_read
|
//op_read
|
||||||
inline void sCPU::op_adc_b() {
|
inline void sCPU::op_adc_b() {
|
||||||
int32 r = regs.a.l + rd.l + regs.p.c;
|
int r;
|
||||||
if(regs.p.d) {
|
if(regs.p.d) {
|
||||||
uint8 n0 = (regs.a.l ) & 15;
|
uint8 n0 = (regs.a.l ) & 15;
|
||||||
uint8 n1 = (regs.a.l >> 4) & 15;
|
uint8 n1 = (regs.a.l >> 4) & 15;
|
||||||
n0 += ((rd.l) & 15) + regs.p.c;
|
n0 += (rd.l & 15) + regs.p.c;
|
||||||
if(n0 > 9) {
|
if(n0 > 9) {
|
||||||
n0 -= 10;
|
n0 = (n0 - 10) & 15;
|
||||||
n0 &= 15;
|
|
||||||
n1++;
|
n1++;
|
||||||
}
|
}
|
||||||
n1 += ((rd.l >> 4) & 15);
|
n1 += ((rd.l >> 4) & 15);
|
||||||
if(n1 > 9) {
|
if(n1 > 9) {
|
||||||
n1 -= 10;
|
n1 = (n1 - 10) & 15;
|
||||||
n1 &= 15;
|
|
||||||
regs.p.c = 1;
|
regs.p.c = 1;
|
||||||
} else {
|
} else {
|
||||||
regs.p.c = 0;
|
regs.p.c = 0;
|
||||||
}
|
}
|
||||||
r = (n1 << 4) | (n0);
|
r = (n1 << 4) | n0;
|
||||||
} else {
|
} else {
|
||||||
r = regs.a.l + rd.l + regs.p.c;
|
r = regs.a.l + rd.l + regs.p.c;
|
||||||
regs.p.c = (r > 0xff);
|
regs.p.c = r > 0xff;
|
||||||
}
|
}
|
||||||
regs.p.n = !!(r & 0x80);
|
regs.p.n = r & 0x80;
|
||||||
regs.p.v = !!(~(regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
|
regs.p.v = ~(regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80;
|
||||||
regs.p.z = ((uint8)r == 0);
|
regs.p.z = (uint8)r == 0;
|
||||||
regs.a.l = r;
|
regs.a.l = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_adc_w() {
|
inline void sCPU::op_adc_w() {
|
||||||
int32 r;
|
int r;
|
||||||
if(regs.p.d) {
|
if(regs.p.d) {
|
||||||
uint8 n0 = (regs.a.w ) & 15;
|
uint8 n0 = (regs.a.w ) & 15;
|
||||||
uint8 n1 = (regs.a.w >> 4) & 15;
|
uint8 n1 = (regs.a.w >> 4) & 15;
|
||||||
uint8 n2 = (regs.a.w >> 8) & 15;
|
uint8 n2 = (regs.a.w >> 8) & 15;
|
||||||
uint8 n3 = (regs.a.w >> 12) & 15;
|
uint8 n3 = (regs.a.w >> 12) & 15;
|
||||||
n0 += ((rd.w) & 15) + regs.p.c;
|
n0 += (rd.w & 15) + regs.p.c;
|
||||||
if(n0 > 9) {
|
if(n0 > 9) {
|
||||||
n0 -= 10;
|
n0 = (n0 - 10) & 15;
|
||||||
n0 &= 15;
|
|
||||||
n1++;
|
n1++;
|
||||||
}
|
}
|
||||||
n1 += ((rd.w >> 4) & 15);
|
n1 += ((rd.w >> 4) & 15);
|
||||||
if(n1 > 9) {
|
if(n1 > 9) {
|
||||||
n1 -= 10;
|
n1 = (n1 - 10) & 15;
|
||||||
n1 &= 15;
|
|
||||||
n2++;
|
n2++;
|
||||||
}
|
}
|
||||||
n2 += ((rd.w >> 8) & 15);
|
n2 += ((rd.w >> 8) & 15);
|
||||||
if(n2 > 9) {
|
if(n2 > 9) {
|
||||||
n2 -= 10;
|
n2 = (n2 - 10) & 15;
|
||||||
n2 &= 15;
|
|
||||||
n3++;
|
n3++;
|
||||||
}
|
}
|
||||||
n3 += ((rd.w >> 12) & 15);
|
n3 += ((rd.w >> 12) & 15);
|
||||||
if(n3 > 9) {
|
if(n3 > 9) {
|
||||||
n3 -= 10;
|
n3 = (n3 - 10) & 15;
|
||||||
n3 &= 15;
|
|
||||||
regs.p.c = 1;
|
regs.p.c = 1;
|
||||||
} else {
|
} else {
|
||||||
regs.p.c = 0;
|
regs.p.c = 0;
|
||||||
}
|
}
|
||||||
r = (n3 << 12) | (n2 << 8) | (n1 << 4) | (n0);
|
r = (n3 << 12) | (n2 << 8) | (n1 << 4) | n0;
|
||||||
} else {
|
} else {
|
||||||
r = regs.a.w + rd.w + regs.p.c;
|
r = regs.a.w + rd.w + regs.p.c;
|
||||||
regs.p.c = (r > 0xffff);
|
regs.p.c = r > 0xffff;
|
||||||
}
|
}
|
||||||
regs.p.n = !!(r & 0x8000);
|
regs.p.n = r & 0x8000;
|
||||||
regs.p.v = !!(~(regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
|
regs.p.v = ~(regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000;
|
||||||
regs.p.z = ((uint16)r == 0);
|
regs.p.z = (uint16)r == 0;
|
||||||
regs.a.w = r;
|
regs.a.w = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_and_b() {
|
inline void sCPU::op_and_b() {
|
||||||
regs.a.l &= rd.l;
|
regs.a.l &= rd.l;
|
||||||
regs.p.n = !!(regs.a.l & 0x80);
|
regs.p.n = regs.a.l & 0x80;
|
||||||
regs.p.z = (regs.a.l == 0);
|
regs.p.z = regs.a.l == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_and_w() {
|
inline void sCPU::op_and_w() {
|
||||||
regs.a.w &= rd.w;
|
regs.a.w &= rd.w;
|
||||||
regs.p.n = !!(regs.a.w & 0x8000);
|
regs.p.n = regs.a.w & 0x8000;
|
||||||
regs.p.z = (regs.a.w == 0);
|
regs.p.z = regs.a.w == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_bit_b() {
|
inline void sCPU::op_bit_b() {
|
||||||
regs.p.n = !!(rd.l & 0x80);
|
regs.p.n = rd.l & 0x80;
|
||||||
regs.p.v = !!(rd.l & 0x40);
|
regs.p.v = rd.l & 0x40;
|
||||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
regs.p.z = (rd.l & regs.a.l) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_bit_w() {
|
inline void sCPU::op_bit_w() {
|
||||||
regs.p.n = !!(rd.w & 0x8000);
|
regs.p.n = rd.w & 0x8000;
|
||||||
regs.p.v = !!(rd.w & 0x4000);
|
regs.p.v = rd.w & 0x4000;
|
||||||
regs.p.z = ((rd.w & regs.a.w) == 0);
|
regs.p.z = (rd.w & regs.a.w) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_cmp_b() {
|
inline void sCPU::op_cmp_b() {
|
||||||
int32 r = regs.a.l - rd.l;
|
int r = regs.a.l - rd.l;
|
||||||
regs.p.n = !!(r & 0x80);
|
regs.p.n = r & 0x80;
|
||||||
regs.p.z = ((uint8)r == 0);
|
regs.p.z = (uint8)r == 0;
|
||||||
regs.p.c = (r >= 0);
|
regs.p.c = r >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_cmp_w() {
|
inline void sCPU::op_cmp_w() {
|
||||||
int32 r = regs.a.w - rd.w;
|
int r = regs.a.w - rd.w;
|
||||||
regs.p.n = !!(r & 0x8000);
|
regs.p.n = r & 0x8000;
|
||||||
regs.p.z = ((uint16)r == 0);
|
regs.p.z = (uint16)r == 0;
|
||||||
regs.p.c = (r >= 0);
|
regs.p.c = r >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_cpx_b() {
|
inline void sCPU::op_cpx_b() {
|
||||||
int32 r = regs.x.l - rd.l;
|
int r = regs.x.l - rd.l;
|
||||||
regs.p.n = !!(r & 0x80);
|
regs.p.n = r & 0x80;
|
||||||
regs.p.z = ((uint8)r == 0);
|
regs.p.z = (uint8)r == 0;
|
||||||
regs.p.c = (r >= 0);
|
regs.p.c = r >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_cpx_w() {
|
inline void sCPU::op_cpx_w() {
|
||||||
int32 r = regs.x.w - rd.w;
|
int r = regs.x.w - rd.w;
|
||||||
regs.p.n = !!(r & 0x8000);
|
regs.p.n = r & 0x8000;
|
||||||
regs.p.z = ((uint16)r == 0);
|
regs.p.z = (uint16)r == 0;
|
||||||
regs.p.c = (r >= 0);
|
regs.p.c = r >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_cpy_b() {
|
inline void sCPU::op_cpy_b() {
|
||||||
int32 r = regs.y.l - rd.l;
|
int r = regs.y.l - rd.l;
|
||||||
regs.p.n = !!(r & 0x80);
|
regs.p.n = r & 0x80;
|
||||||
regs.p.z = ((uint8)r == 0);
|
regs.p.z = (uint8)r == 0;
|
||||||
regs.p.c = (r >= 0);
|
regs.p.c = r >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_cpy_w() {
|
inline void sCPU::op_cpy_w() {
|
||||||
int32 r = regs.y.w - rd.w;
|
int r = regs.y.w - rd.w;
|
||||||
regs.p.n = !!(r & 0x8000);
|
regs.p.n = r & 0x8000;
|
||||||
regs.p.z = ((uint16)r == 0);
|
regs.p.z = (uint16)r == 0;
|
||||||
regs.p.c = (r >= 0);
|
regs.p.c = r >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_eor_b() {
|
inline void sCPU::op_eor_b() {
|
||||||
regs.a.l ^= rd.l;
|
regs.a.l ^= rd.l;
|
||||||
regs.p.n = !!(regs.a.l & 0x80);
|
regs.p.n = regs.a.l & 0x80;
|
||||||
regs.p.z = (regs.a.l == 0);
|
regs.p.z = regs.a.l == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_eor_w() {
|
inline void sCPU::op_eor_w() {
|
||||||
regs.a.w ^= rd.w;
|
regs.a.w ^= rd.w;
|
||||||
regs.p.n = !!(regs.a.w & 0x8000);
|
regs.p.n = regs.a.w & 0x8000;
|
||||||
regs.p.z = (regs.a.w == 0);
|
regs.p.z = regs.a.w == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_lda_b() {
|
inline void sCPU::op_lda_b() {
|
||||||
regs.a.l = rd.l;
|
regs.a.l = rd.l;
|
||||||
regs.p.n = !!(regs.a.l & 0x80);
|
regs.p.n = regs.a.l & 0x80;
|
||||||
regs.p.z = (regs.a.l == 0);
|
regs.p.z = regs.a.l == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_lda_w() {
|
inline void sCPU::op_lda_w() {
|
||||||
regs.a.w = rd.w;
|
regs.a.w = rd.w;
|
||||||
regs.p.n = !!(regs.a.w & 0x8000);
|
regs.p.n = regs.a.w & 0x8000;
|
||||||
regs.p.z = (regs.a.w == 0);
|
regs.p.z = regs.a.w == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_ldx_b() {
|
inline void sCPU::op_ldx_b() {
|
||||||
regs.x.l = rd.l;
|
regs.x.l = rd.l;
|
||||||
regs.p.n = !!(regs.x.l & 0x80);
|
regs.p.n = regs.x.l & 0x80;
|
||||||
regs.p.z = (regs.x.l == 0);
|
regs.p.z = regs.x.l == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_ldx_w() {
|
inline void sCPU::op_ldx_w() {
|
||||||
regs.x.w = rd.w;
|
regs.x.w = rd.w;
|
||||||
regs.p.n = !!(regs.x.w & 0x8000);
|
regs.p.n = regs.x.w & 0x8000;
|
||||||
regs.p.z = (regs.x.w == 0);
|
regs.p.z = regs.x.w == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_ldy_b() {
|
inline void sCPU::op_ldy_b() {
|
||||||
regs.y.l = rd.l;
|
regs.y.l = rd.l;
|
||||||
regs.p.n = !!(regs.y.l & 0x80);
|
regs.p.n = regs.y.l & 0x80;
|
||||||
regs.p.z = (regs.y.l == 0);
|
regs.p.z = regs.y.l == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_ldy_w() {
|
inline void sCPU::op_ldy_w() {
|
||||||
regs.y.w = rd.w;
|
regs.y.w = rd.w;
|
||||||
regs.p.n = !!(regs.y.w & 0x8000);
|
regs.p.n = regs.y.w & 0x8000;
|
||||||
regs.p.z = (regs.y.w == 0);
|
regs.p.z = regs.y.w == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_ora_b() {
|
inline void sCPU::op_ora_b() {
|
||||||
regs.a.l |= rd.l;
|
regs.a.l |= rd.l;
|
||||||
regs.p.n = !!(regs.a.l & 0x80);
|
regs.p.n = regs.a.l & 0x80;
|
||||||
regs.p.z = (regs.a.l == 0);
|
regs.p.z = regs.a.l == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_ora_w() {
|
inline void sCPU::op_ora_w() {
|
||||||
regs.a.w |= rd.w;
|
regs.a.w |= rd.w;
|
||||||
regs.p.n = !!(regs.a.w & 0x8000);
|
regs.p.n = regs.a.w & 0x8000;
|
||||||
regs.p.z = (regs.a.w == 0);
|
regs.p.z = regs.a.w == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_sbc_b() {
|
inline void sCPU::op_sbc_b() {
|
||||||
int32 r;
|
int r;
|
||||||
if(regs.p.d) {
|
if(regs.p.d) {
|
||||||
uint8 n0 = (regs.a.l ) & 15;
|
uint8 n0 = (regs.a.l ) & 15;
|
||||||
uint8 n1 = (regs.a.l >> 4) & 15;
|
uint8 n1 = (regs.a.l >> 4) & 15;
|
||||||
n0 -= ((rd.l ) & 15) + !regs.p.c;
|
n0 -= ((rd.l ) & 15) + !regs.p.c;
|
||||||
n1 -= ((rd.l >> 4) & 15);
|
n1 -= ((rd.l >> 4) & 15);
|
||||||
if(n0 > 9) {
|
if(n0 > 9) {
|
||||||
@@ -221,21 +215,21 @@ int32 r;
|
|||||||
r = (n1 << 4) | (n0);
|
r = (n1 << 4) | (n0);
|
||||||
} else {
|
} else {
|
||||||
r = regs.a.l - rd.l - !regs.p.c;
|
r = regs.a.l - rd.l - !regs.p.c;
|
||||||
regs.p.c = (r >= 0);
|
regs.p.c = r >= 0;
|
||||||
}
|
}
|
||||||
regs.p.n = !!(r & 0x80);
|
regs.p.n = r & 0x80;
|
||||||
regs.p.v = !!((regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
|
regs.p.v = (regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80;
|
||||||
regs.p.z = ((uint8)r == 0);
|
regs.p.z = (uint8)r == 0;
|
||||||
regs.a.l = r;
|
regs.a.l = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_sbc_w() {
|
inline void sCPU::op_sbc_w() {
|
||||||
int32 r;
|
int r;
|
||||||
if(regs.p.d) {
|
if(regs.p.d) {
|
||||||
uint8 n0 = (regs.a.w ) & 15;
|
uint8 n0 = (regs.a.w ) & 15;
|
||||||
uint8 n1 = (regs.a.w >> 4) & 15;
|
uint8 n1 = (regs.a.w >> 4) & 15;
|
||||||
uint8 n2 = (regs.a.w >> 8) & 15;
|
uint8 n2 = (regs.a.w >> 8) & 15;
|
||||||
uint8 n3 = (regs.a.w >> 12) & 15;
|
uint8 n3 = (regs.a.w >> 12) & 15;
|
||||||
n0 -= ((rd.w ) & 15) + !regs.p.c;
|
n0 -= ((rd.w ) & 15) + !regs.p.c;
|
||||||
n1 -= ((rd.w >> 4) & 15);
|
n1 -= ((rd.w >> 4) & 15);
|
||||||
n2 -= ((rd.w >> 8) & 15);
|
n2 -= ((rd.w >> 8) & 15);
|
||||||
@@ -261,116 +255,116 @@ int32 r;
|
|||||||
r = (n3 << 12) | (n2 << 8) | (n1 << 4) | (n0);
|
r = (n3 << 12) | (n2 << 8) | (n1 << 4) | (n0);
|
||||||
} else {
|
} else {
|
||||||
r = regs.a.w - rd.w - !regs.p.c;
|
r = regs.a.w - rd.w - !regs.p.c;
|
||||||
regs.p.c = (r >= 0);
|
regs.p.c = r >= 0;
|
||||||
}
|
}
|
||||||
regs.p.n = !!(r & 0x8000);
|
regs.p.n = r & 0x8000;
|
||||||
regs.p.v = !!((regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
|
regs.p.v = (regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000;
|
||||||
regs.p.z = ((uint16)r == 0);
|
regs.p.z = (uint16)r == 0;
|
||||||
regs.a.w = r;
|
regs.a.w = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
//op_rmw
|
//op_rmw
|
||||||
inline void sCPU::op_inc_b() {
|
inline void sCPU::op_inc_b() {
|
||||||
rd.l++;
|
rd.l++;
|
||||||
regs.p.n = !!(rd.l & 0x80);
|
regs.p.n = rd.l & 0x80;
|
||||||
regs.p.z = (rd.l == 0);
|
regs.p.z = rd.l == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_inc_w() {
|
inline void sCPU::op_inc_w() {
|
||||||
rd.w++;
|
rd.w++;
|
||||||
regs.p.n = !!(rd.w & 0x8000);
|
regs.p.n = rd.w & 0x8000;
|
||||||
regs.p.z = (rd.w == 0);
|
regs.p.z = rd.w == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_dec_b() {
|
inline void sCPU::op_dec_b() {
|
||||||
rd.l--;
|
rd.l--;
|
||||||
regs.p.n = !!(rd.l & 0x80);
|
regs.p.n = rd.l & 0x80;
|
||||||
regs.p.z = (rd.l == 0);
|
regs.p.z = rd.l == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_dec_w() {
|
inline void sCPU::op_dec_w() {
|
||||||
rd.w--;
|
rd.w--;
|
||||||
regs.p.n = !!(rd.w & 0x8000);
|
regs.p.n = rd.w & 0x8000;
|
||||||
regs.p.z = (rd.w == 0);
|
regs.p.z = rd.w == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_asl_b() {
|
inline void sCPU::op_asl_b() {
|
||||||
regs.p.c = !!(rd.l & 0x80);
|
regs.p.c = rd.l & 0x80;
|
||||||
rd.l <<= 1;
|
rd.l <<= 1;
|
||||||
regs.p.n = !!(rd.l & 0x80);
|
regs.p.n = rd.l & 0x80;
|
||||||
regs.p.z = (rd.l == 0);
|
regs.p.z = rd.l == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_asl_w() {
|
inline void sCPU::op_asl_w() {
|
||||||
regs.p.c = !!(rd.w & 0x8000);
|
regs.p.c = rd.w & 0x8000;
|
||||||
rd.w <<= 1;
|
rd.w <<= 1;
|
||||||
regs.p.n = !!(rd.w & 0x8000);
|
regs.p.n = rd.w & 0x8000;
|
||||||
regs.p.z = (rd.w == 0);
|
regs.p.z = rd.w == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_lsr_b() {
|
inline void sCPU::op_lsr_b() {
|
||||||
regs.p.c = rd.l & 1;
|
regs.p.c = rd.l & 1;
|
||||||
rd.l >>= 1;
|
rd.l >>= 1;
|
||||||
regs.p.n = !!(rd.l & 0x80);
|
regs.p.n = rd.l & 0x80;
|
||||||
regs.p.z = (rd.l == 0);
|
regs.p.z = rd.l == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_lsr_w() {
|
inline void sCPU::op_lsr_w() {
|
||||||
regs.p.c = rd.w & 1;
|
regs.p.c = rd.w & 1;
|
||||||
rd.w >>= 1;
|
rd.w >>= 1;
|
||||||
regs.p.n = !!(rd.w & 0x8000);
|
regs.p.n = rd.w & 0x8000;
|
||||||
regs.p.z = (rd.w == 0);
|
regs.p.z = rd.w == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_rol_b() {
|
inline void sCPU::op_rol_b() {
|
||||||
uint16 carry = (uint16)regs.p.c;
|
unsigned carry = (unsigned)regs.p.c;
|
||||||
regs.p.c = !!(rd.l & 0x80);
|
regs.p.c = rd.l & 0x80;
|
||||||
rd.l = (rd.l << 1) | carry;
|
rd.l = (rd.l << 1) | carry;
|
||||||
regs.p.n = !!(rd.l & 0x80);
|
regs.p.n = rd.l & 0x80;
|
||||||
regs.p.z = (rd.l == 0);
|
regs.p.z = rd.l == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_rol_w() {
|
inline void sCPU::op_rol_w() {
|
||||||
uint16 carry = (uint16)regs.p.c;
|
unsigned carry = (unsigned)regs.p.c;
|
||||||
regs.p.c = !!(rd.w & 0x8000);
|
regs.p.c = rd.w & 0x8000;
|
||||||
rd.w = (rd.w << 1) | carry;
|
rd.w = (rd.w << 1) | carry;
|
||||||
regs.p.n = !!(rd.w & 0x8000);
|
regs.p.n = rd.w & 0x8000;
|
||||||
regs.p.z = (rd.w == 0);
|
regs.p.z = rd.w == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_ror_b() {
|
inline void sCPU::op_ror_b() {
|
||||||
uint16 carry = (uint16)regs.p.c << 7;
|
unsigned carry = (unsigned)regs.p.c << 7;
|
||||||
regs.p.c = rd.l & 1;
|
regs.p.c = rd.l & 1;
|
||||||
rd.l = carry | (rd.l >> 1);
|
rd.l = carry | (rd.l >> 1);
|
||||||
regs.p.n = !!(rd.l & 0x80);
|
regs.p.n = rd.l & 0x80;
|
||||||
regs.p.z = (rd.l == 0);
|
regs.p.z = rd.l == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_ror_w() {
|
inline void sCPU::op_ror_w() {
|
||||||
uint16 carry = (uint16)regs.p.c << 15;
|
unsigned carry = (unsigned)regs.p.c << 15;
|
||||||
regs.p.c = rd.w & 1;
|
regs.p.c = rd.w & 1;
|
||||||
rd.w = carry | (rd.w >> 1);
|
rd.w = carry | (rd.w >> 1);
|
||||||
regs.p.n = !!(rd.w & 0x8000);
|
regs.p.n = rd.w & 0x8000;
|
||||||
regs.p.z = (rd.w == 0);
|
regs.p.z = rd.w == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_trb_b() {
|
inline void sCPU::op_trb_b() {
|
||||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
regs.p.z = (rd.l & regs.a.l) == 0;
|
||||||
rd.l &= ~regs.a.l;
|
rd.l &= ~regs.a.l;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_trb_w() {
|
inline void sCPU::op_trb_w() {
|
||||||
regs.p.z = ((rd.w & regs.a.w) == 0);
|
regs.p.z = (rd.w & regs.a.w) == 0;
|
||||||
rd.w &= ~regs.a.w;
|
rd.w &= ~regs.a.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_tsb_b() {
|
inline void sCPU::op_tsb_b() {
|
||||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
regs.p.z = (rd.l & regs.a.l) == 0;
|
||||||
rd.l |= regs.a.l;
|
rd.l |= regs.a.l;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sCPU::op_tsb_w() {
|
inline void sCPU::op_tsb_w() {
|
||||||
regs.p.z = ((rd.w & regs.a.w) == 0);
|
regs.p.z = (rd.w & regs.a.w) == 0;
|
||||||
rd.w |= regs.a.w;
|
rd.w |= regs.a.w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,52 +5,51 @@ void sCPU::dma_add_clocks(uint clocks) {
|
|||||||
add_clocks(clocks);
|
add_clocks(clocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****
|
bool sCPU::dma_addr_valid(uint32 abus) {
|
||||||
* used by both DMA and HDMA
|
//reads from B-bus or S-CPU registers are invalid
|
||||||
*
|
if((abus & 0x40ff00) == 0x2100) return false; //$[00-3f|80-bf]:[2100-21ff]
|
||||||
* DMA address bus A cannot read from or write to the following addresses :
|
if((abus & 0x40fe00) == 0x4000) return false; //$[00-3f|80-bf]:[4000-41ff]
|
||||||
* $[00-3f|80-bf]:43[00-7f] <DMA control registers>
|
if((abus & 0x40ffe0) == 0x4200) return false; //$[00-3f|80-bf]:[4200-421f]
|
||||||
* $[00-3f|80-bf]:420b <DMA enable register>
|
if((abus & 0x40ff80) == 0x4300) return false; //$[00-3f|80-bf]:[4300-437f]
|
||||||
* $[00-3f|80-bf]:420c <HDMA enable register>
|
return true;
|
||||||
*
|
}
|
||||||
* WRAM<>WRAM transfers via $2180 are also illegal
|
|
||||||
*****/
|
uint8 sCPU::dma_read(uint32 abus) {
|
||||||
|
if(dma_addr_valid(abus) == false) return 0x00; //does not return S-CPU MDR
|
||||||
|
return bus.read(abus);
|
||||||
|
}
|
||||||
|
|
||||||
void sCPU::dma_transfer(bool direction, uint8 bbus, uint32 abus) {
|
void sCPU::dma_transfer(bool direction, uint8 bbus, uint32 abus) {
|
||||||
if(direction == 0) {
|
if(direction == 0) {
|
||||||
//a->b transfer (to $21xx)
|
//a->b transfer (to $21xx)
|
||||||
if(bbus == 0x80 && ((abus & 0xfe0000) == 0x7e0000 || (abus & 0x40e000) == 0x0000)) {
|
if(bbus == 0x80 && ((abus & 0xfe0000) == 0x7e0000 || (abus & 0x40e000) == 0x0000)) {
|
||||||
//illegal WRAM->WRAM transfer
|
//illegal WRAM->WRAM transfer (bus conflict)
|
||||||
//read most likely occurs; no write occurs
|
//read most likely occurs; no write occurs
|
||||||
//read is irrelevant, as it has no observable effect on emulation
|
//read is irrelevent, as it cannot be observed by software
|
||||||
} else if((abus & 0x40ff00) == 0x2100 || (abus & 0x40ff80) == 0x4300
|
dma_add_clocks(8);
|
||||||
|| (abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c) {
|
|
||||||
//illegal register access
|
|
||||||
bus.write(0x2100 | bbus, regs.mdr); //TODO: verify if MDR is written here
|
|
||||||
} else {
|
} else {
|
||||||
//valid transfer
|
dma_add_clocks(4);
|
||||||
bus.write(0x2100 | bbus, bus.read(abus));
|
uint8 data = dma_read(abus);
|
||||||
|
dma_add_clocks(4);
|
||||||
|
bus.write(0x2100 | bbus, data);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//b->a transfer (from $21xx)
|
//b->a transfer (from $21xx)
|
||||||
if(bbus == 0x80 && ((abus & 0xfe0000) == 0x7e0000 || (abus & 0x40e000) == 0x0000)) {
|
if(bbus == 0x80 && ((abus & 0xfe0000) == 0x7e0000 || (abus & 0x40e000) == 0x0000)) {
|
||||||
//illegal WRAM->WRAM transfer
|
//illegal WRAM->WRAM transfer (bus conflict)
|
||||||
//no read occurs; write does occur
|
//no read occurs; write does occur
|
||||||
//does not write MDR as expected
|
dma_add_clocks(8);
|
||||||
//TODO: 0x00 was observed on hardware; verify if other values are possible
|
bus.write(abus, 0x00); //does not write S-CPU MDR
|
||||||
bus.write(abus, 0x00);
|
|
||||||
} else if((abus & 0x40ff00) == 0x2100 || (abus & 0x40ff80) == 0x4300
|
|
||||||
|| (abus & 0x40ffff) == 0x420b || (abus & 0x40ffff) == 0x420c) {
|
|
||||||
//illegal register access
|
|
||||||
bus.write(abus, regs.mdr); //TODO: verify if MDR is written here
|
|
||||||
} else {
|
} else {
|
||||||
//valid transfer
|
dma_add_clocks(4);
|
||||||
bus.write(abus, bus.read(0x2100 | bbus));
|
uint8 data = bus.read(0x2100 | bbus);
|
||||||
|
dma_add_clocks(4);
|
||||||
|
if(dma_addr_valid(abus) == true) {
|
||||||
|
bus.write(abus, data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//each byte *always* consumes 8 clocks, even if transfer is invalid and no read and/or write occurs
|
|
||||||
dma_add_clocks(8);
|
|
||||||
cycle_edge();
|
cycle_edge();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,10 +119,22 @@ inline void sCPU::dma_write(uint8 i, uint8 index) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8 sCPU::dma_enabled_channels() {
|
||||||
|
uint8 r = 0;
|
||||||
|
for(unsigned i = 0; i < 8; i++) {
|
||||||
|
if(channel[i].dma_enabled) r++;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
void sCPU::dma_run() {
|
void sCPU::dma_run() {
|
||||||
for(int i = 0; i < 8; i++) {
|
dma_add_clocks(8);
|
||||||
|
cycle_edge();
|
||||||
|
|
||||||
|
for(unsigned i = 0; i < 8; i++) {
|
||||||
if(channel[i].dma_enabled == false) continue;
|
if(channel[i].dma_enabled == false) continue;
|
||||||
dma_add_clocks(8);
|
dma_add_clocks(8);
|
||||||
|
cycle_edge();
|
||||||
|
|
||||||
if(cartridge.info.sdd1 == true) {
|
if(cartridge.info.sdd1 == true) {
|
||||||
sdd1.dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr), channel[i].xfersize);
|
sdd1.dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr), channel[i].xfersize);
|
||||||
@@ -138,7 +149,7 @@ void sCPU::dma_run() {
|
|||||||
channel[i].xfersize, channel[i].xfersize ? channel[i].xfersize : 65536);
|
channel[i].xfersize, channel[i].xfersize ? channel[i].xfersize : 65536);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint index = 0;
|
unsigned index = 0;
|
||||||
do {
|
do {
|
||||||
dma_write(i, dma_bbus(i, index++));
|
dma_write(i, dma_bbus(i, index++));
|
||||||
} while(channel[i].dma_enabled && channel[i].xfersize);
|
} while(channel[i].dma_enabled && channel[i].xfersize);
|
||||||
@@ -158,7 +169,7 @@ inline bool sCPU::hdma_active(uint8 i) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool sCPU::hdma_active_after(uint8 i) {
|
inline bool sCPU::hdma_active_after(uint8 i) {
|
||||||
for(int n = i + 1; n < 8; n++) {
|
for(unsigned n = i + 1; n < 8; n++) {
|
||||||
if(hdma_active(n) == true) return true;
|
if(hdma_active(n) == true) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -166,7 +177,7 @@ inline bool sCPU::hdma_active_after(uint8 i) {
|
|||||||
|
|
||||||
inline uint8 sCPU::hdma_enabled_channels() {
|
inline uint8 sCPU::hdma_enabled_channels() {
|
||||||
uint8 r = 0;
|
uint8 r = 0;
|
||||||
for(int i = 0; i < 8; i++) {
|
for(unsigned i = 0; i < 8; i++) {
|
||||||
if(channel[i].hdma_enabled) r++;
|
if(channel[i].hdma_enabled) r++;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
@@ -174,55 +185,57 @@ inline uint8 sCPU::hdma_enabled_channels() {
|
|||||||
|
|
||||||
inline uint8 sCPU::hdma_active_channels() {
|
inline uint8 sCPU::hdma_active_channels() {
|
||||||
uint8 r = 0;
|
uint8 r = 0;
|
||||||
for(int i = 0; i < 8; i++) {
|
for(unsigned i = 0; i < 8; i++) {
|
||||||
if(hdma_active(i) == true) r++;
|
if(hdma_active(i) == true) r++;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sCPU::hdma_update(uint8 i) {
|
void sCPU::hdma_update(uint8 i) {
|
||||||
channel[i].hdma_line_counter = bus.read(hdma_addr(i));
|
channel[i].hdma_line_counter = dma_read(hdma_addr(i));
|
||||||
dma_add_clocks(8);
|
dma_add_clocks(8);
|
||||||
|
|
||||||
channel[i].hdma_completed = (channel[i].hdma_line_counter == 0);
|
channel[i].hdma_completed = (channel[i].hdma_line_counter == 0);
|
||||||
channel[i].hdma_do_transfer = !channel[i].hdma_completed;
|
channel[i].hdma_do_transfer = !channel[i].hdma_completed;
|
||||||
|
|
||||||
if(channel[i].hdma_indirect) {
|
if(channel[i].hdma_indirect) {
|
||||||
channel[i].hdma_iaddr = bus.read(hdma_addr(i)) << 8;
|
channel[i].hdma_iaddr = dma_read(hdma_addr(i)) << 8;
|
||||||
dma_add_clocks(8);
|
dma_add_clocks(8);
|
||||||
|
|
||||||
if(!channel[i].hdma_completed || hdma_active_after(i)) {
|
if(!channel[i].hdma_completed || hdma_active_after(i)) {
|
||||||
channel[i].hdma_iaddr >>= 8;
|
channel[i].hdma_iaddr >>= 8;
|
||||||
channel[i].hdma_iaddr |= bus.read(hdma_addr(i)) << 8;
|
channel[i].hdma_iaddr |= dma_read(hdma_addr(i)) << 8;
|
||||||
dma_add_clocks(8);
|
dma_add_clocks(8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sCPU::hdma_run() {
|
void sCPU::hdma_run() {
|
||||||
static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
|
dma_add_clocks(8);
|
||||||
for(int i = 0; i < 8; i++) {
|
|
||||||
|
for(unsigned i = 0; i < 8; i++) {
|
||||||
if(hdma_active(i) == false) continue;
|
if(hdma_active(i) == false) continue;
|
||||||
channel[i].dma_enabled = false; //HDMA run during DMA will stop DMA mid-transfer
|
channel[i].dma_enabled = false; //HDMA run during DMA will stop DMA mid-transfer
|
||||||
dma_add_clocks(8);
|
|
||||||
|
|
||||||
if(channel[i].hdma_do_transfer) {
|
if(channel[i].hdma_do_transfer) {
|
||||||
int xferlen = hdma_xferlen[channel[i].xfermode];
|
static const unsigned transfer_length[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
|
||||||
for(int index = 0; index < xferlen; index++) {
|
unsigned length = transfer_length[channel[i].xfermode];
|
||||||
if(bool(config::cpu.hdma_enable) == true) {
|
for(unsigned index = 0; index < length; index++) {
|
||||||
dma_transfer(channel[i].direction, dma_bbus(i, index),
|
unsigned addr = !channel[i].hdma_indirect ? hdma_addr(i) : hdma_iaddr(i);
|
||||||
!channel[i].hdma_indirect ? hdma_addr(i) : hdma_iaddr(i));
|
dma_transfer(channel[i].direction, dma_bbus(i, index), addr);
|
||||||
} else {
|
|
||||||
dma_add_clocks(8);
|
|
||||||
cycle_edge();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(unsigned i = 0; i < 8; i++) {
|
||||||
|
if(hdma_active(i) == false) continue;
|
||||||
|
|
||||||
channel[i].hdma_line_counter--;
|
channel[i].hdma_line_counter--;
|
||||||
channel[i].hdma_do_transfer = bool(channel[i].hdma_line_counter & 0x80);
|
channel[i].hdma_do_transfer = bool(channel[i].hdma_line_counter & 0x80);
|
||||||
if((channel[i].hdma_line_counter & 0x7f) == 0) {
|
if((channel[i].hdma_line_counter & 0x7f) == 0) {
|
||||||
hdma_update(i);
|
hdma_update(i);
|
||||||
|
} else {
|
||||||
|
dma_add_clocks(8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,15 +243,17 @@ void sCPU::hdma_run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sCPU::hdma_init_reset() {
|
void sCPU::hdma_init_reset() {
|
||||||
for(int i = 0; i < 8; i++) {
|
for(unsigned i = 0; i < 8; i++) {
|
||||||
channel[i].hdma_completed = false;
|
channel[i].hdma_completed = false;
|
||||||
channel[i].hdma_do_transfer = false;
|
channel[i].hdma_do_transfer = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sCPU::hdma_init() {
|
void sCPU::hdma_init() {
|
||||||
for(int i = 0; i < 8; i++) {
|
dma_add_clocks(8);
|
||||||
if(!channel[i].hdma_enabled)continue;
|
|
||||||
|
for(unsigned i = 0; i < 8; i++) {
|
||||||
|
if(!channel[i].hdma_enabled) continue;
|
||||||
channel[i].dma_enabled = false; //HDMA init during DMA will stop DMA mid-transfer
|
channel[i].dma_enabled = false; //HDMA init during DMA will stop DMA mid-transfer
|
||||||
|
|
||||||
channel[i].hdma_addr = channel[i].srcaddr;
|
channel[i].hdma_addr = channel[i].srcaddr;
|
||||||
@@ -253,7 +268,7 @@ void sCPU::hdma_init() {
|
|||||||
*****/
|
*****/
|
||||||
|
|
||||||
void sCPU::dma_power() {
|
void sCPU::dma_power() {
|
||||||
for(int i = 0; i < 8; i++) {
|
for(unsigned i = 0; i < 8; i++) {
|
||||||
channel[i].dmap = 0xff;
|
channel[i].dmap = 0xff;
|
||||||
channel[i].direction = 1;
|
channel[i].direction = 1;
|
||||||
channel[i].hdma_indirect = true;
|
channel[i].hdma_indirect = true;
|
||||||
@@ -277,7 +292,7 @@ void sCPU::dma_power() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sCPU::dma_reset() {
|
void sCPU::dma_reset() {
|
||||||
for(int i = 0; i < 8; i++) {
|
for(unsigned i = 0; i < 8; i++) {
|
||||||
channel[i].dma_enabled = false;
|
channel[i].dma_enabled = false;
|
||||||
channel[i].hdma_enabled = false;
|
channel[i].hdma_enabled = false;
|
||||||
|
|
||||||
|
@@ -46,6 +46,8 @@
|
|||||||
} channel[8];
|
} channel[8];
|
||||||
|
|
||||||
void dma_add_clocks(uint clocks);
|
void dma_add_clocks(uint clocks);
|
||||||
|
bool dma_addr_valid(uint32 abus);
|
||||||
|
uint8 dma_read(uint32 abus);
|
||||||
void dma_transfer(bool direction, uint8 bbus, uint32 abus);
|
void dma_transfer(bool direction, uint8 bbus, uint32 abus);
|
||||||
|
|
||||||
uint8 dma_bbus(uint8 i, uint8 index);
|
uint8 dma_bbus(uint8 i, uint8 index);
|
||||||
@@ -56,6 +58,7 @@
|
|||||||
void dma_transfertobusb(uint8 i, uint8 bbus);
|
void dma_transfertobusb(uint8 i, uint8 bbus);
|
||||||
void dma_transfertobusa(uint8 i, uint8 bbus);
|
void dma_transfertobusa(uint8 i, uint8 bbus);
|
||||||
void dma_write(uint8 i, uint8 index);
|
void dma_write(uint8 i, uint8 index);
|
||||||
|
uint8 dma_enabled_channels();
|
||||||
void dma_run();
|
void dma_run();
|
||||||
|
|
||||||
bool hdma_active(uint8 i);
|
bool hdma_active(uint8 i);
|
||||||
|
@@ -1,8 +1,7 @@
|
|||||||
#ifdef SCPU_CPP
|
#ifdef SCPU_CPP
|
||||||
|
|
||||||
uint8 sCPU::pio_status() {
|
uint8 sCPU::pio() { return status.pio; }
|
||||||
return status.pio;
|
bool sCPU::joylatch() { return status.joypad_strobe_latch; }
|
||||||
}
|
|
||||||
|
|
||||||
//WMDATA
|
//WMDATA
|
||||||
uint8 sCPU::mmio_r2180() {
|
uint8 sCPU::mmio_r2180() {
|
||||||
@@ -55,7 +54,7 @@ void sCPU::mmio_w4016(uint8 data) {
|
|||||||
//realtime or buffered status of joypadN.b
|
//realtime or buffered status of joypadN.b
|
||||||
uint8 sCPU::mmio_r4016() {
|
uint8 sCPU::mmio_r4016() {
|
||||||
uint8 r = regs.mdr & 0xfc;
|
uint8 r = regs.mdr & 0xfc;
|
||||||
r |= (uint8)snes.input.port_read(0);
|
r |= snes.input.port_read(0) & 3;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +64,7 @@ uint8 sCPU::mmio_r4016() {
|
|||||||
//1-0 = Joypad serial data
|
//1-0 = Joypad serial data
|
||||||
uint8 sCPU::mmio_r4017() {
|
uint8 sCPU::mmio_r4017() {
|
||||||
uint8 r = (regs.mdr & 0xe0) | 0x1c;
|
uint8 r = (regs.mdr & 0xe0) | 0x1c;
|
||||||
r |= (uint8)snes.input.port_read(1);
|
r |= snes.input.port_read(1) & 3;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,19 +142,16 @@ void sCPU::mmio_w420a(uint8 data) {
|
|||||||
|
|
||||||
//DMAEN
|
//DMAEN
|
||||||
void sCPU::mmio_w420b(uint8 data) {
|
void sCPU::mmio_w420b(uint8 data) {
|
||||||
for(int i = 0; i < 8; i++) {
|
for(unsigned i = 0; i < 8; i++) {
|
||||||
channel[i].dma_enabled = !!(data & (1 << i));
|
channel[i].dma_enabled = data & (1 << i);
|
||||||
}
|
|
||||||
if(data) {
|
|
||||||
status.dma_state = DMASTATE_DMASYNC;
|
|
||||||
status.dma_pending = true;
|
|
||||||
}
|
}
|
||||||
|
if(data) status.dma_pending = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//HDMAEN
|
//HDMAEN
|
||||||
void sCPU::mmio_w420c(uint8 data) {
|
void sCPU::mmio_w420c(uint8 data) {
|
||||||
for(int i = 0; i < 8; i++) {
|
for(unsigned i = 0; i < 8; i++) {
|
||||||
channel[i].hdma_enabled = !!(data & (1 << i));
|
channel[i].hdma_enabled = data & (1 << i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,7 +3,8 @@
|
|||||||
uint8 mmio_read(uint addr);
|
uint8 mmio_read(uint addr);
|
||||||
void mmio_write(uint addr, uint8 data);
|
void mmio_write(uint addr, uint8 data);
|
||||||
|
|
||||||
uint8 pio_status();
|
uint8 pio();
|
||||||
|
bool joylatch();
|
||||||
|
|
||||||
uint8 mmio_r2180();
|
uint8 mmio_r2180();
|
||||||
uint8 mmio_r4016();
|
uint8 mmio_r4016();
|
||||||
|
@@ -15,13 +15,13 @@ public:
|
|||||||
} event;
|
} event;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint nmi_hold;
|
unsigned nmi_hold;
|
||||||
uint irq_hold;
|
unsigned irq_hold;
|
||||||
|
|
||||||
uint nmi_fire;
|
unsigned nmi_fire;
|
||||||
uint irq_fire;
|
unsigned irq_fire;
|
||||||
uint irq_delay;
|
unsigned irq_delay;
|
||||||
uint hw_math;
|
unsigned hw_math;
|
||||||
|
|
||||||
alwaysinline void set(uint &ctr, uint clocks) {
|
alwaysinline void set(uint &ctr, uint clocks) {
|
||||||
if(clocks >= ctr) { ctr = clocks; }
|
if(clocks >= ctr) { ctr = clocks; }
|
||||||
@@ -36,55 +36,50 @@ public:
|
|||||||
}
|
}
|
||||||
} counter;
|
} counter;
|
||||||
|
|
||||||
enum {
|
enum DMA_State { DMA_Inactive, DMA_Run, DMA_CPUsync };
|
||||||
DMASTATE_INACTIVE,
|
|
||||||
DMASTATE_DMASYNC,
|
|
||||||
DMASTATE_RUN,
|
|
||||||
DMASTATE_CPUSYNC,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
//core
|
//core
|
||||||
uint8 opcode;
|
uint8 opcode;
|
||||||
bool in_opcode;
|
bool in_opcode;
|
||||||
|
|
||||||
uint clock_count;
|
unsigned clock_count;
|
||||||
|
|
||||||
//timing
|
//timing
|
||||||
uint16 vcounter, hcounter;
|
uint16 vcounter, hcounter;
|
||||||
uint16 field_lines, line_clocks;
|
uint16 field_lines, line_clocks;
|
||||||
|
|
||||||
bool line_rendered;
|
bool line_rendered;
|
||||||
uint16 line_render_position;
|
uint16 line_render_position;
|
||||||
|
|
||||||
bool dram_refreshed;
|
bool dram_refreshed;
|
||||||
uint16 dram_refresh_position;
|
uint16 dram_refresh_position;
|
||||||
|
|
||||||
bool hdmainit_triggered;
|
bool hdmainit_triggered;
|
||||||
uint16 hdmainit_trigger_position;
|
uint16 hdmainit_trigger_position;
|
||||||
|
|
||||||
bool hdma_triggered;
|
bool hdma_triggered;
|
||||||
|
|
||||||
uint16 irq_delay;
|
uint16 irq_delay;
|
||||||
|
|
||||||
bool nmi_valid;
|
bool nmi_valid;
|
||||||
bool nmi_line;
|
bool nmi_line;
|
||||||
bool nmi_transition;
|
bool nmi_transition;
|
||||||
bool nmi_pending;
|
bool nmi_pending;
|
||||||
|
|
||||||
uint16 virq_trigger_pos, hirq_trigger_pos;
|
uint16 virq_trigger_pos, hirq_trigger_pos;
|
||||||
bool irq_valid;
|
bool irq_valid;
|
||||||
bool irq_line;
|
bool irq_line;
|
||||||
bool irq_transition;
|
bool irq_transition;
|
||||||
bool irq_pending;
|
bool irq_pending;
|
||||||
|
|
||||||
//dma
|
//dma
|
||||||
uint dma_counter;
|
unsigned dma_counter;
|
||||||
uint dma_clocks;
|
unsigned dma_clocks;
|
||||||
uint dma_state;
|
bool dma_pending;
|
||||||
bool dma_pending;
|
bool hdma_pending;
|
||||||
bool hdma_pending;
|
bool hdma_mode; //0 = init, 1 = run
|
||||||
bool hdmainit_pending;
|
DMA_State dma_state;
|
||||||
|
|
||||||
//mmio
|
//mmio
|
||||||
|
|
||||||
@@ -92,20 +87,20 @@ public:
|
|||||||
uint32 wram_addr;
|
uint32 wram_addr;
|
||||||
|
|
||||||
//$4016-$4017
|
//$4016-$4017
|
||||||
bool joypad_strobe_latch;
|
bool joypad_strobe_latch;
|
||||||
uint32 joypad1_bits;
|
uint32 joypad1_bits;
|
||||||
uint32 joypad2_bits;
|
uint32 joypad2_bits;
|
||||||
|
|
||||||
//$4200
|
//$4200
|
||||||
bool nmi_enabled;
|
bool nmi_enabled;
|
||||||
bool hirq_enabled, virq_enabled;
|
bool hirq_enabled, virq_enabled;
|
||||||
bool auto_joypad_poll;
|
bool auto_joypad_poll;
|
||||||
|
|
||||||
//$4201
|
//$4201
|
||||||
uint8 pio;
|
uint8 pio;
|
||||||
|
|
||||||
//$4202-$4203
|
//$4202-$4203
|
||||||
uint8 mul_a, mul_b;
|
uint8 mul_a, mul_b;
|
||||||
|
|
||||||
//$4204-$4206
|
//$4204-$4206
|
||||||
uint16 div_a;
|
uint16 div_a;
|
||||||
@@ -119,10 +114,10 @@ public:
|
|||||||
uint16 r4216;
|
uint16 r4216;
|
||||||
|
|
||||||
//$4218-$421f
|
//$4218-$421f
|
||||||
uint8 joy1l, joy1h;
|
uint8 joy1l, joy1h;
|
||||||
uint8 joy2l, joy2h;
|
uint8 joy2l, joy2h;
|
||||||
uint8 joy3l, joy3h;
|
uint8 joy3l, joy3h;
|
||||||
uint8 joy4l, joy4h;
|
uint8 joy4l, joy4h;
|
||||||
} status;
|
} status;
|
||||||
|
|
||||||
void power();
|
void power();
|
||||||
|
@@ -1,10 +1,15 @@
|
|||||||
#ifdef SCPU_CPP
|
#ifdef SCPU_CPP
|
||||||
|
|
||||||
void sCPU::run_auto_joypad_poll() {
|
void sCPU::run_auto_joypad_poll() {
|
||||||
uint16_t joy1 = 0, joy2 = 0;
|
uint16 joy1 = 0, joy2 = 0, joy3 = 0, joy4 = 0;
|
||||||
for(unsigned i = 0; i < 16; i++) {
|
for(unsigned i = 0; i < 16; i++) {
|
||||||
joy1 |= (uint16_t)snes.input.port_read(0) ? (0x8000 >> i) : 0;
|
uint8 port0 = snes.input.port_read(0);
|
||||||
joy2 |= (uint16_t)snes.input.port_read(1) ? (0x8000 >> i) : 0;
|
uint8 port1 = snes.input.port_read(1);
|
||||||
|
|
||||||
|
joy1 |= (port0 & 1) ? (0x8000 >> i) : 0;
|
||||||
|
joy2 |= (port1 & 1) ? (0x8000 >> i) : 0;
|
||||||
|
joy3 |= (port0 & 2) ? (0x8000 >> i) : 0;
|
||||||
|
joy4 |= (port1 & 2) ? (0x8000 >> i) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
status.joy1l = joy1;
|
status.joy1l = joy1;
|
||||||
@@ -13,11 +18,11 @@ void sCPU::run_auto_joypad_poll() {
|
|||||||
status.joy2l = joy2;
|
status.joy2l = joy2;
|
||||||
status.joy2h = joy2 >> 8;
|
status.joy2h = joy2 >> 8;
|
||||||
|
|
||||||
status.joy3l = 0x00;
|
status.joy3l = joy3;
|
||||||
status.joy3h = 0x00;
|
status.joy3h = joy3 >> 8;
|
||||||
|
|
||||||
status.joy4l = 0x00;
|
status.joy4l = joy4;
|
||||||
status.joy4h = 0x00;
|
status.joy4h = joy4 >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //ifdef SCPU_CPP
|
#endif //ifdef SCPU_CPP
|
||||||
|
@@ -1,9 +1,4 @@
|
|||||||
#ifdef SCPU_CPP
|
#ifdef SCPU_CPP
|
||||||
|
|
||||||
#define ntsc_color_burst_phase_shift_scanline() ( \
|
|
||||||
snes.region() == SNES::NTSC && status.vcounter == 240 && \
|
|
||||||
ppu.interlace() == false && ppu.field() == 1 \
|
|
||||||
)
|
|
||||||
|
|
||||||
#include "irq.cpp"
|
#include "irq.cpp"
|
||||||
#include "joypad.cpp"
|
#include "joypad.cpp"
|
||||||
@@ -22,6 +17,12 @@ uint sCPU::dma_counter() { return (status.dma_counter + status.hcounter) & 7; }
|
|||||||
* Dot 323 range = { 1292, 1294, 1296 }
|
* Dot 323 range = { 1292, 1294, 1296 }
|
||||||
* Dot 327 range = { 1310, 1312, 1314 }
|
* Dot 327 range = { 1310, 1312, 1314 }
|
||||||
*****/
|
*****/
|
||||||
|
|
||||||
|
#define ntsc_color_burst_phase_shift_scanline() ( \
|
||||||
|
snes.region() == SNES::NTSC && status.vcounter == 240 && \
|
||||||
|
ppu.interlace() == false && ppu.field() == 1 \
|
||||||
|
)
|
||||||
|
|
||||||
uint16 sCPU::hdot() {
|
uint16 sCPU::hdot() {
|
||||||
if(ntsc_color_burst_phase_shift_scanline() == true) return (status.hcounter >> 2);
|
if(ntsc_color_burst_phase_shift_scanline() == true) return (status.hcounter >> 2);
|
||||||
return (status.hcounter - ((status.hcounter > 1292) << 1) - ((status.hcounter > 1310) << 1)) >> 2;
|
return (status.hcounter - ((status.hcounter > 1292) << 1) - ((status.hcounter > 1310) << 1)) >> 2;
|
||||||
@@ -55,15 +56,7 @@ void sCPU::scanline() {
|
|||||||
|
|
||||||
//dram refresh occurs once every scanline
|
//dram refresh occurs once every scanline
|
||||||
status.dram_refreshed = false;
|
status.dram_refreshed = false;
|
||||||
if(cpu_version == 2) {
|
if(cpu_version == 2) status.dram_refresh_position = 530 + 8 - dma_counter();
|
||||||
if(ntsc_color_burst_phase_shift_scanline() == false) {
|
|
||||||
if(status.dram_refresh_position == 534) {
|
|
||||||
status.dram_refresh_position = 538;
|
|
||||||
} else {
|
|
||||||
status.dram_refresh_position = 534;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//hdma triggers once every visible scanline
|
//hdma triggers once every visible scanline
|
||||||
status.line_rendered = false;
|
status.line_rendered = false;
|
||||||
@@ -86,8 +79,7 @@ void sCPU::frame() {
|
|||||||
|
|
||||||
status.vcounter = 0;
|
status.vcounter = 0;
|
||||||
status.field_lines = (snes.region() == SNES::NTSC ? 525 : 625) >> 1;
|
status.field_lines = (snes.region() == SNES::NTSC ? 525 : 625) >> 1;
|
||||||
//interlaced even fields have one extra scanline
|
//interlaced even fields have one extra scanline (263+262=525 NTSC, 313+312=625 PAL)
|
||||||
//(263+262=525 NTSC, 313+312=625 PAL)
|
|
||||||
if(ppu.interlace() == true && ppu.field() == 0) status.field_lines++;
|
if(ppu.interlace() == true && ppu.field() == 0) status.field_lines++;
|
||||||
|
|
||||||
status.hdmainit_triggered = false;
|
status.hdmainit_triggered = false;
|
||||||
@@ -101,20 +93,19 @@ void sCPU::frame() {
|
|||||||
/*****
|
/*****
|
||||||
* precycle_edge()
|
* precycle_edge()
|
||||||
*
|
*
|
||||||
* Used for DMA/HDMA bus synchronization
|
* Used for H/DMA bus synchronization
|
||||||
*****/
|
*****/
|
||||||
alwaysinline void sCPU::precycle_edge() {
|
void sCPU::precycle_edge() {
|
||||||
if(status.dma_state == DMASTATE_CPUSYNC) {
|
if(status.dma_state == DMA_CPUsync) {
|
||||||
status.dma_state = DMASTATE_INACTIVE;
|
add_clocks(status.clock_count - (status.dma_clocks % status.clock_count));
|
||||||
uint n = status.clock_count - (status.dma_clocks % status.clock_count);
|
status.dma_state = DMA_Inactive;
|
||||||
add_clocks(n ? n : status.clock_count);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
* cycle_edge()
|
* cycle_edge()
|
||||||
*
|
*
|
||||||
* Used to test for HDMA, which can trigger on the edge of every opcode cycle.
|
* Used to test for H/DMA, which can trigger on the edge of every opcode cycle.
|
||||||
*****/
|
*****/
|
||||||
void sCPU::cycle_edge() {
|
void sCPU::cycle_edge() {
|
||||||
if(status.line_rendered == false) {
|
if(status.line_rendered == false) {
|
||||||
@@ -129,47 +120,55 @@ void sCPU::cycle_edge() {
|
|||||||
status.hdmainit_triggered = true;
|
status.hdmainit_triggered = true;
|
||||||
hdma_init_reset();
|
hdma_init_reset();
|
||||||
if(hdma_enabled_channels()) {
|
if(hdma_enabled_channels()) {
|
||||||
if(status.dma_state == DMASTATE_INACTIVE) {
|
status.hdma_pending = true;
|
||||||
status.dma_state = DMASTATE_DMASYNC;
|
status.hdma_mode = 0;
|
||||||
status.hdmainit_pending = true;
|
|
||||||
} else {
|
|
||||||
hdma_init();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(status.hdma_triggered == false) {
|
if(status.hdma_triggered == false) {
|
||||||
if(status.hcounter >= 1106) {
|
if(status.hcounter >= 1104) {
|
||||||
status.hdma_triggered = true;
|
status.hdma_triggered = true;
|
||||||
if(hdma_active_channels()) {
|
if(hdma_active_channels()) {
|
||||||
if(status.dma_state == DMASTATE_INACTIVE) {
|
status.hdma_pending = true;
|
||||||
status.dma_state = DMASTATE_DMASYNC;
|
status.hdma_mode = 1;
|
||||||
status.hdma_pending = true;
|
|
||||||
} else {
|
|
||||||
hdma_run();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(status.dma_state) {
|
//H/DMA pending && DMA inactive?
|
||||||
case DMASTATE_INACTIVE: break;
|
//.. Run one full CPU cycle
|
||||||
|
//.. HDMA pending && HDMA enabled ? DMA sync + HDMA run
|
||||||
case DMASTATE_DMASYNC: {
|
//.. DMA pending && DMA enabled ? DMA sync + DMA run
|
||||||
status.dma_state = DMASTATE_RUN;
|
//.... HDMA during DMA && HDMA enabled ? DMA sync + HDMA run
|
||||||
} break;
|
//.. Run one bus CPU cycle
|
||||||
|
//.. CPU sync
|
||||||
case DMASTATE_RUN: {
|
|
||||||
status.dma_state = DMASTATE_CPUSYNC;
|
if(status.dma_state == DMA_Run) {
|
||||||
status.dma_clocks = 8 - dma_counter() + 8;
|
if(status.hdma_pending) {
|
||||||
add_clocks(status.dma_clocks);
|
status.hdma_pending = false;
|
||||||
|
if(hdma_enabled_channels()) {
|
||||||
if(status.hdmainit_pending) { hdma_init(); status.hdmainit_pending = false; }
|
dma_add_clocks(8 - dma_counter()); //DMA sync
|
||||||
if(status.hdma_pending) { hdma_run(); status.hdma_pending = false; }
|
status.hdma_mode == 0 ? hdma_init() : hdma_run();
|
||||||
if(status.dma_pending) { dma_run(); status.dma_pending = false; }
|
if(!dma_enabled_channels()) status.dma_state = DMA_CPUsync;
|
||||||
|
}
|
||||||
} break;
|
}
|
||||||
|
|
||||||
|
if(status.dma_pending) {
|
||||||
|
status.dma_pending = false;
|
||||||
|
if(dma_enabled_channels()) {
|
||||||
|
dma_add_clocks(8 - dma_counter()); //DMA sync
|
||||||
|
dma_run();
|
||||||
|
status.dma_state = DMA_CPUsync;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(status.dma_state == DMA_Inactive) {
|
||||||
|
if(status.dma_pending || status.hdma_pending) {
|
||||||
|
status.dma_clocks = 0;
|
||||||
|
status.dma_state = DMA_Run;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,7 +211,7 @@ void sCPU::timing_reset() {
|
|||||||
status.line_clocks = 1364;
|
status.line_clocks = 1364;
|
||||||
|
|
||||||
status.line_rendered = false;
|
status.line_rendered = false;
|
||||||
status.line_render_position = min(1112U, (uint)config::ppu.hack.render_scanline_position);
|
status.line_render_position = min(1112U, (unsigned)config::ppu.hack.render_scanline_position);
|
||||||
|
|
||||||
status.dram_refreshed = false;
|
status.dram_refreshed = false;
|
||||||
status.dram_refresh_position = (cpu_version == 1) ? 530 : 538;
|
status.dram_refresh_position = (cpu_version == 1) ? 530 : 538;
|
||||||
@@ -236,11 +235,12 @@ void sCPU::timing_reset() {
|
|||||||
|
|
||||||
update_interrupts();
|
update_interrupts();
|
||||||
|
|
||||||
status.dma_counter = 0;
|
status.dma_counter = 0;
|
||||||
status.dma_state = DMASTATE_INACTIVE;
|
status.dma_clocks = 0;
|
||||||
status.dma_pending = false;
|
status.dma_pending = false;
|
||||||
status.hdma_pending = false;
|
status.hdma_pending = false;
|
||||||
status.hdmainit_pending = false;
|
status.hdma_mode = 0;
|
||||||
|
status.dma_state = DMA_Inactive;
|
||||||
|
|
||||||
history.reset();
|
history.reset();
|
||||||
|
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.3 KiB |
@@ -2,39 +2,40 @@ static char enc_icon48[] = {
|
|||||||
"_gAB8AHwAfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB8AHw"
|
"_gAB8AHwAfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB8AHw"
|
||||||
"AfD_AfAB8AHwAfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB"
|
"AfD_AfAB8AHwAfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB"
|
||||||
"8AHwAfD_AfAB8AHwAfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHw"
|
"8AHwAfD_AfAB8AHwAfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHw"
|
||||||
"AfAB8AHwAfD_AfAB8AHwAfAB8AHwAfABgFD_oRYPBAA1BABWVQQAWwQAQQQAGgQA"
|
"AfAB8AHwAfD_AfAB8AHwAfAB8AHwAfABAAD_qgAD_p8VOwD_oRaI_qEWthD-oBbL"
|
||||||
"Av8u8AHwAfAB8AHwAfAB8AHwVbSAAQQALQQAsAQA9FUEAP8EwPsEAM4EAFP9BAAE"
|
"CADE_qEAFaP_oBZm_p38GBU28AHwAfAB8AHwAfBfAfAB8AFQuBCoAMe0AP4twAD_"
|
||||||
"QvAB8AHwAfAB8AHwqwHwvOAEBACFBAD5uPDVBOD-BAC9BAAUSvAB8L8B8AHwAfAB"
|
"BPAEIPAkAIX_-JkZCkLwAfAB8AHwAfBHAfAB8HSB_wABtABvPQQA-7DwBPAEECwA"
|
||||||
"8AHwvGADBACuoqjwBPAEwNsEABZS8H8B8AHwAfAB8AHwAfDAIHuvnPAE8ATwBCDH"
|
"0P74oBIbTvAB8AHwAfAB8EcB8AHweEGgFWwkAv0HqPAE8MSwFdX-oRr-E1LwAfAB"
|
||||||
"BAAFVvC_AfAB8AHwAfAB8LzAIAQA3vaY8ATwBPAEYGZa8AHw3wHwAfAB8AHwwMCX"
|
"8AHwAfAB8Lzg6KEUMRAC96DwBPAE8P3EIKXAEVrwAfAB8AHwAfDzAfDAsBa3mPAE"
|
||||||
"kPAE8OsE8ASg3wQABl7wAfAB8K8B8AHwAfC8QAYEAOeQ8PcE8ATw0OMvYvAB8AHw"
|
"8ATwwED_uAE4E1rwAfAB8AHwAfAB8PG8YKIVJDjyBPAE8ATA-KAWoF7wAfAB8AHw"
|
||||||
"AfDXAfAB8MBAHAQA_JDwBPALBPAE4GRi8AAAPz9U_wEEAA0EAB0EAB59BAAPBABE"
|
"AfB7AfD4gmmQ8ATwBPDM4-Z_XvAB8AHwAfAB8AHwwICPH_wSePQE8ATwBMClDxEB"
|
||||||
"9gHwAfDA8BVVBABxBAB3BAChUET9p5zwBPAE8BaGuMALBACqbAQAzgQA9AQA-wQA"
|
"YNBERP8PPz_-oEw-Pv56CACMCACCgggAXT8__yD2BA808wHwAfDAkKMSDv6AmxwS"
|
||||||
"qvwEAPYEANYEAHoEAL4SlvAB8AHwAfAEhjIEAF68FEKo8ATwBFCBcIFHtQQA5AQA"
|
"_qQYH8QC6kjIAJTUAOug8ATwhOFDRABYUDw8_hWsAI9QPj7_8KwA_wTw_oL6BAC1"
|
||||||
"_wTwBKDuBAB-XDQQjvAB8AHwAfAQhmhHzPYE8ARgpQ5YwEBor2xBsPAE8AQQ_QQA"
|
"PT3-MpbwjwHwAfAB8AxmpRkUFAOOkxjzBPAEoJ8PEEAQdZQAOrwA47TwBPAoAPh9"
|
||||||
"hFTyfwHwAfAB8MjA-Bgg8wTQowAQ-_-rACMuNrz_SrzwBPAE8MQgZ4LwbwHwAfAB"
|
"yAB0hvAB8AHwAfBcsha6XFwC-KzwBPDsAOQ0EHWQAD0EAPSs8ATwBMCAn4LwAfAB"
|
||||||
"8BDJkbTwBMCnAAfLfV-0ETU6fP_mnPAE8ATwBCAkExxfhvAB8AHwAfDEgBEEAO0D"
|
"8AHwXLUVakz4gwTwKACbQkL-F0wBTuac8ATwiPH-_AQATh-C8AHwAfAB8ExifwAC"
|
||||||
"uPAEQKQO_f-tAIBCLDX_cTw-mPA3BPAE8ASAlYLwAUDNAKoBBAAFBAAUBAAiBAB-"
|
"DcAAtbTwfKT8_qETejSAAJOc8ATwBPAUY9p9CAAIhvAB8AHwAfCEYZ4MGDWE8YCn"
|
||||||
"JQhAEBAYEETz5PYE8KgABZxKRfIENju8_9eQ8ATwBPAEoOq0wKoDBAAsBACGBADM"
|
"nEs8_3oRgAD1lPAE8ATwBKBVh4LwAQAUCwDNACQEAKBNAMwAaggAewgAoH8AywBz"
|
||||||
"BADq7AQA_AQA_gSAEBAYEOrKBACDBAAqBABMo6gAFkC88AQgrvgCBy83wP8VPj7_"
|
"CABbCABgNwDIAA458Nxp2IO88Hwhzf-ZEQ-0A15XjPAE8ATwhOGlfaDOVAA1oACY"
|
||||||
"-JDwBPCvBPAIs7yAuBDEoED_BPBXBPAEQDAQwAQAKcCAHRf8S7hQMBl_uFk4O_--"
|
"sADhCAD9jQgA_wTwBEDMAPQEAHq7NABjCAAcq2QRvPAW9sUMXHwAiIzwBPAE8MDg"
|
||||||
"KYzwBPAE8ATwvEBhBABe95zwBPAE8ARg9gQAW1HAIJ8XFKwA8uhIkFUEAB-sxhkE"
|
"otZxIMsAGYQArQQATv6s8ATwzPAA4wQAUVcKAGQmYAR9MILpBAB3sP-qKgbgUPwC"
|
||||||
"AH0EAJL1BADDBADznPAE8ATwwADozQBIBAD5kPAE8ATwAQTg-ADQACn_nrwYAshD"
|
"mwQAevuAAP6U8ATwBPDAYO3QANEAHIQA3JjwBPCrBPAEoPwEAGyAQVRwAeCV_qIX"
|
||||||
"pPUB8NAQEQQA3nGgRqjwBPDAkOKI8ATw9wTwBPAEIM8UAwHwAfAB8HvIEPQYzKjw"
|
"WPQWZNJ8AKoQgAQbSAI2hABtzAC6xAgA_aDwBPCIxOc4Ab6mjPAE8ATwBPAEAPYE"
|
||||||
"BPAEQDQS0t-I8ATwBPAE8ARAeprwAfB3AfDEYLAZyqzwBPAEAMX1cAAvBADxiPAE"
|
"AK9YZwHwAfA2QwLAAEgEAK7dqPAE8MCAx8AA5Ijw_wTwBPAE8ExCFPQB8AHwAQDQ"
|
||||||
"8ATwBOB68AQAGZbwAfAB8MSgHK0EAPGw8ASg_gQAScBDvj4URZTwBPAE8AQw6gQA"
|
"Q0P-E5QAw6zwBPD1wECLcAC2iPAE8ATwBPD1BAD70AMqmvAB8AHwATDQODj-EpgA"
|
||||||
"RjwN9mwJ__8IBAAT_QQAGgRADBAUEET2xHDgE6u48ARwuwQAA0CFGQQAup0EAPOc"
|
"1LDwxPbFBAAxcCDNAOyM8ATwewTwBOCGkvAB8AHwIOM8t-AzuPC8g66UasQwyJDw"
|
||||||
"8ATwBIDyBACgmADLABe0gAkEAKpFBACaBADSBADsBABa-QQA-wRADBDtBADTVQQA"
|
"VwTwBPAEIPHEBG4KAAJBDcYKAP7-LAQAT1UEAGUEAHAEAGoEAFd1BAA5BAASJAAY"
|
||||||
"nQQASAQACsDAGK0EAPW48AQg3QQAFfbwVcggEQQAUwQAoRxD6b0EAPRcJNwwEBAY"
|
"-8Qg_gaytPB8Yeg7O_8eUTGgvwAEyABUUAK3XZAA9aTw6OJsFdgIAIOQAM8AG_11"
|
||||||
"EJ8EAKpRBAAQuIAGBABuBAC66AQA_wTwBPAEgOoEAEpzBAAHSxBBOFgryF-88BQg"
|
"_guUAKpgCAC1BADvDAD_BPAxBED-_vgIAEoA_nzDBAD4o0BA_lO88Lwgjuy4FPLw"
|
||||||
"LHEB8NDQBgQAC10EAA0IQLj-vDAQBADFr5jwBPAE8ASgywQAFMRA6pm4gOcEAHAE"
|
"AYDPABCYAKpCoABtBACKBACbEACKngQAk4wnzQBXoCd3qBe5plgh4azwBPDM8P76"
|
||||||
"AOAgAfCvAfAB8AHwvEACBAC1jPAvBPAE8ATwBAC_VBBDMtT_TrAAeQQAPAQAYKLf"
|
"9QQAiwwA1CjgGeQSvMD6yAQAKbHwAfAB8AHwvMC9RBH-nPAE8ATwBKDAxCFVVDXu"
|
||||||
"AfAB8AHwAfDAQBnYQozw1wTwBPAE8P0EAB1p8AHwrwHwAfAB8MDgGAQA-ojw7wTw"
|
"sADzCAC9dEgEX3nwAfAB8AHwvMAxBAD8X4zwBPAE8ATwTAB-3Ewh_bQADHHwAfAB"
|
||||||
"BPAE8AQA_AQA3PsB8N8B8AHwAfDA8CQVsYjwBPD3BPAE8AQAulz1AfAB8AHw1wHw"
|
"8AHwAfDAYL50iPAE8ATwBPDAQMRl8L8B8AHwAfAB8AHwcABMiPDvBPAE8ATwwECc"
|
||||||
"AfDEQA0EAL2M8ATw9wTwBKAEFBFh8AHwAfAB8FcB8AHwxIAFBABoBADjXQQA_pzw"
|
"ZfAB8AHwrwHwAfAB8HQAAnQAsIzw9wTwBPC84OQIABy1AfAB8O8B8AHwAfDs1ZUI"
|
||||||
"BPAEgOUEAG3_hCUB8AHwAfAB8AHwAfAB8KvIEFwXPQQAkgQAz8BGXveYQwQQDBAU"
|
"8wTwBPD1vGDHBAAkXfAB8AHwAfCnAfAB8Mjw_zCEAJ8EAK7rpPAE8CgA9wQAvAQA"
|
||||||
"ENAEAJT9BABB9CYB8AHwAfAB8AHwrwHwAfAB8NBwBAQADtgl_QQwDxRA5PIB8AHw"
|
"_lQQAJC1AfAB8AHwAfAB8FcB8MjwkBE6BABsBACPVQQApAQArwQAqQQAl_UgAHgI"
|
||||||
"AfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB8AHwAfD_AfAB8AHwAfAB"
|
"AEsEANQsAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB8AHwAfD_AfAB"
|
||||||
"8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB8AHwAfD_AfAB8AHw"
|
"8AHwAfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB8AHwAfD_"
|
||||||
"AfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHwfwHwAfAB8AHwAfAB8AGA"
|
"AfAB8AHwAfAB8AHwAfAB8P8B8AHwAfAB8AHwAfAB8AHw_wHwAfAB8AHwAfAB8AHw"
|
||||||
|
"AfD_AfAB8AHwAfAB8AHwAfAB8A8B8AHwAfABsA"
|
||||||
};
|
};
|
||||||
|
@@ -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) + ram[(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);
|
||||||
|
@@ -12,17 +12,19 @@ int sDSP::echo_output(bool channel) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sDSP::echo_read(bool channel) {
|
void sDSP::echo_read(bool channel) {
|
||||||
uint8 *in = &ram[state.t_echo_ptr + channel * 2];
|
unsigned addr = state.t_echo_ptr + channel * 2;
|
||||||
int s = (int16)((in[1] << 8) + in[0]);
|
uint8 lo = memory::apuram[(uint16)(addr + 0)];
|
||||||
|
uint8 hi = memory::apuram[(uint16)(addr + 1)];
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sDSP::echo_write(bool channel) {
|
void sDSP::echo_write(bool channel) {
|
||||||
if(!(state.t_echo_disabled & 0x20)) {
|
if(!(state.t_echo_disabled & 0x20)) {
|
||||||
uint8 *out = &ram[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];
|
||||||
out[0] = (uint8)(s);
|
memory::apuram[(uint16)(addr + 0)] = s;
|
||||||
out[1] = (uint8)(s >> 8);
|
memory::apuram[(uint16)(addr + 1)] = s >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
state.t_echo_out[channel] = 0;
|
state.t_echo_out[channel] = 0;
|
||||||
|
@@ -249,8 +249,6 @@ void sDSP::write(uint8 addr, uint8 data) {
|
|||||||
/* initialization */
|
/* initialization */
|
||||||
|
|
||||||
void sDSP::power() {
|
void sDSP::power() {
|
||||||
ram = (uint8*)smp.get_spcram_handle(); //TODO: move to sMemory
|
|
||||||
|
|
||||||
memset(&state.regs, 0, sizeof state.regs);
|
memset(&state.regs, 0, sizeof state.regs);
|
||||||
state.echo_hist_pos = 0;
|
state.echo_hist_pos = 0;
|
||||||
state.every_other_sample = false;
|
state.every_other_sample = false;
|
||||||
|
@@ -12,9 +12,6 @@ public:
|
|||||||
~sDSP();
|
~sDSP();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//external
|
|
||||||
uint8 *ram;
|
|
||||||
|
|
||||||
//USE_STATE_MACHINE variable
|
//USE_STATE_MACHINE variable
|
||||||
unsigned phase_index;
|
unsigned phase_index;
|
||||||
|
|
||||||
|
@@ -22,9 +22,11 @@ void sDSP::voice_1(voice_t &v) {
|
|||||||
|
|
||||||
void sDSP::voice_2(voice_t &v) {
|
void sDSP::voice_2(voice_t &v) {
|
||||||
//read sample pointer (ignored if not needed)
|
//read sample pointer (ignored if not needed)
|
||||||
const uint8 *entry = &ram[state.t_dir_addr];
|
uint16 addr = state.t_dir_addr;
|
||||||
if(!v.kon_delay) entry += 2;
|
if(!v.kon_delay) addr += 2;
|
||||||
state.t_brr_next_addr = (entry[1] << 8) + entry[0];
|
uint8 lo = memory::apuram[(uint16)(addr + 0)];
|
||||||
|
uint8 hi = memory::apuram[(uint16)(addr + 1)];
|
||||||
|
state.t_brr_next_addr = ((hi << 8) + lo);
|
||||||
|
|
||||||
state.t_adsr0 = VREG(adsr0);
|
state.t_adsr0 = VREG(adsr0);
|
||||||
|
|
||||||
@@ -43,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 = ram[(uint16)(v.brr_addr + v.brr_offset)];
|
state.t_brr_byte = memory::apuram[(uint16)(v.brr_addr + v.brr_offset)];
|
||||||
state.t_brr_header = ram[(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) {
|
||||||
|
206
src/lib/bbase.h
206
src/lib/bbase.h
@@ -1,24 +1,24 @@
|
|||||||
/*
|
/*
|
||||||
bbase : version 0.13 ~byuu (2008-04-02)
|
bbase : version 0.15 ~byuu (2008-09-14)
|
||||||
license: public domain
|
license: public domain
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef BBASE_H
|
#ifndef BBASE_H
|
||||||
#define BBASE_H
|
#define BBASE_H
|
||||||
|
|
||||||
#include <nall/stdint.hpp>
|
#include <nall/stdint.hpp>
|
||||||
typedef int8_t int8;
|
typedef int8_t int8;
|
||||||
typedef int16_t int16;
|
typedef int16_t int16;
|
||||||
typedef int32_t int32;
|
typedef int32_t int32;
|
||||||
typedef int64_t int64;
|
typedef int64_t int64;
|
||||||
typedef uint8_t uint8;
|
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 int uint;
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
using std::min;
|
using std::min;
|
||||||
using std::max;
|
using std::max;
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@@ -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
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
@@ -87,49 +80,31 @@ using std::max;
|
|||||||
* OS localization
|
* 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__)
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
static char *userpath(char *output) {
|
static char* realpath(const char *file_name, char *resolved_name) {
|
||||||
strcpy(output, "."); //failsafe
|
wchar_t filename[PATH_MAX] = L"";
|
||||||
SHGetFolderPath(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, output);
|
_wfullpath(filename, utf16(file_name), PATH_MAX);
|
||||||
|
strcpy(resolved_name, utf8(filename));
|
||||||
|
return resolved_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char* userpath(char *output) {
|
||||||
|
wchar_t path[PATH_MAX] = L"."; //failsafe
|
||||||
|
SHGetFolderPathW(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, path);
|
||||||
|
strcpy(output, utf8(path));
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
#define mkdir(path) _wmkdir(utf16(path))
|
||||||
#else
|
#else
|
||||||
static char *userpath(char *output) {
|
static char* userpath(char *output) {
|
||||||
strcpy(output, "."); //failsafe
|
strcpy(output, "."); //failsafe
|
||||||
struct passwd *userinfo = getpwuid(getuid());
|
struct passwd *userinfo = getpwuid(getuid());
|
||||||
if(userinfo) { strcpy(output, userinfo->pw_dir); }
|
if(userinfo) { strcpy(output, userinfo->pw_dir); }
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
#define mkdir(path) (mkdir)(path, 0755);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*****
|
|
||||||
* template functions
|
|
||||||
*****/
|
|
||||||
|
|
||||||
template<typename T> inline void safe_free(T &handle) {
|
|
||||||
if(handle) {
|
|
||||||
free(handle);
|
|
||||||
handle = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T> inline void safe_delete(T &handle) {
|
|
||||||
if(handle) {
|
|
||||||
delete handle;
|
|
||||||
handle = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T> inline void safe_release(T &handle) {
|
|
||||||
if(handle) {
|
|
||||||
handle->Release();
|
|
||||||
handle = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int min, int max, typename T> inline T minmax(const T x) {
|
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;
|
return (x < (T)min) ? (T)min : (x > (T)max) ? (T)max : x;
|
||||||
}
|
}
|
||||||
@@ -138,93 +113,48 @@ template<int min, int max, typename T> inline T minmax(const T x) {
|
|||||||
* endian wrappers
|
* endian wrappers
|
||||||
*****/
|
*****/
|
||||||
|
|
||||||
#ifndef ARCH_MSB
|
#ifndef ARCH_MSB
|
||||||
//little-endian: uint8[] { 0x01, 0x02, 0x03, 0x04 } == 0x04030201
|
//little-endian: uint8[] { 0x01, 0x02, 0x03, 0x04 } == 0x04030201
|
||||||
#define order_lsb2(a,b) a,b
|
#define order_lsb2(a,b) a,b
|
||||||
#define order_lsb3(a,b,c) a,b,c
|
#define order_lsb3(a,b,c) a,b,c
|
||||||
#define order_lsb4(a,b,c,d) a,b,c,d
|
#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_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_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_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_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_msb2(a,b) b,a
|
||||||
#define order_msb3(a,b,c) c,b,a
|
#define order_msb3(a,b,c) c,b,a
|
||||||
#define order_msb4(a,b,c,d) d,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_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_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_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
|
#define order_msb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a
|
||||||
#else
|
#else
|
||||||
//big-endian: uint8[] { 0x01, 0x02, 0x03, 0x04 } == 0x01020304
|
//big-endian: uint8[] { 0x01, 0x02, 0x03, 0x04 } == 0x01020304
|
||||||
#define order_lsb2(a,b) b,a
|
#define order_lsb2(a,b) b,a
|
||||||
#define order_lsb3(a,b,c) c,b,a
|
#define order_lsb3(a,b,c) c,b,a
|
||||||
#define order_lsb4(a,b,c,d) d,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_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_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_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_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_msb2(a,b) a,b
|
||||||
#define order_msb3(a,b,c) a,b,c
|
#define order_msb3(a,b,c) a,b,c
|
||||||
#define order_msb4(a,b,c,d) a,b,c,d
|
#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_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_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_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
|
#define order_msb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*****
|
/*****
|
||||||
* libc extensions
|
* libc extensions
|
||||||
*****/
|
*****/
|
||||||
|
|
||||||
//pseudo-random number generator
|
//pseudo-random number generator
|
||||||
static uint prng() {
|
static unsigned prng() {
|
||||||
static uint n = 0;
|
static unsigned n = 0;
|
||||||
return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320);
|
return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64 fget(FILE *fp, uint length = 1) {
|
|
||||||
uint64 data = 0;
|
|
||||||
for(uint i = 0; i < length; i++) {
|
|
||||||
data |= fgetc(fp) << (i << 3);
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fput(FILE *fp, uint64 data, uint length = 1) {
|
|
||||||
for(uint 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 uint32 fsize(FILE *fp) {
|
|
||||||
if(!fp)return 0;
|
|
||||||
uint32 pos = ftell(fp);
|
|
||||||
fseek(fp, 0, SEEK_END);
|
|
||||||
uint32 size = ftell(fp);
|
|
||||||
fseek(fp, pos, SEEK_SET);
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32 fsize(const char *fn) {
|
|
||||||
FILE *fp = fopen(fn, "rb");
|
|
||||||
if(!fp)return 0;
|
|
||||||
fseek(fp, 0, SEEK_END);
|
|
||||||
uint32 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,9 +1,10 @@
|
|||||||
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);
|
||||||
gtk_widget_set_size_request(button, width, height);
|
gtk_widget_set_size_request(button, width, height);
|
||||||
gtk_widget_show(button);
|
gtk_widget_show(button);
|
||||||
g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(hiro_pbutton_tick), (gpointer)this);
|
g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(hiro_pbutton_tick), (gpointer)this);
|
||||||
|
@@ -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,7 +14,7 @@ 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) {
|
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;
|
||||||
@@ -54,7 +54,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,9 +1,10 @@
|
|||||||
void hiro_pcheckbox_tick(pCheckbox *p) {
|
void hiro_pcheckbox_tick(pCheckbox *p) {
|
||||||
if(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);
|
||||||
gtk_widget_set_size_request(checkbox, width, height);
|
gtk_widget_set_size_request(checkbox, width, height);
|
||||||
gtk_widget_show(checkbox);
|
gtk_widget_show(checkbox);
|
||||||
g_signal_connect_swapped(G_OBJECT(checkbox), "toggled", G_CALLBACK(hiro_pcheckbox_tick), (gpointer)this);
|
g_signal_connect_swapped(G_OBJECT(checkbox), "toggled", G_CALLBACK(hiro_pcheckbox_tick), (gpointer)this);
|
||||||
@@ -15,7 +16,9 @@ void pCheckbox::set_text(const char *text) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void pCheckbox::check(bool state) {
|
void pCheckbox::check(bool state) {
|
||||||
|
locked = true;
|
||||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox), state ? TRUE : FALSE);
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbox), state ? TRUE : FALSE);
|
||||||
|
locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pCheckbox::uncheck() {
|
void pCheckbox::uncheck() {
|
||||||
@@ -28,6 +31,7 @@ bool pCheckbox::checked() {
|
|||||||
|
|
||||||
pCheckbox::pCheckbox(Checkbox &self_) : pFormControl(self_), self(self_) {
|
pCheckbox::pCheckbox(Checkbox &self_) : pFormControl(self_), self(self_) {
|
||||||
checkbox = 0;
|
checkbox = 0;
|
||||||
|
locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* internal */
|
/* internal */
|
||||||
|
@@ -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();
|
||||||
@@ -10,6 +10,7 @@ public:
|
|||||||
pCheckbox(Checkbox&);
|
pCheckbox(Checkbox&);
|
||||||
|
|
||||||
/* internal */
|
/* internal */
|
||||||
GtkWidget *checkbox;
|
|
||||||
GtkWidget* gtk_handle();
|
GtkWidget* gtk_handle();
|
||||||
|
GtkWidget *checkbox;
|
||||||
|
bool locked;
|
||||||
};
|
};
|
||||||
|
@@ -1,9 +1,10 @@
|
|||||||
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);
|
||||||
gtk_widget_set_size_request(combobox, width, height);
|
gtk_widget_set_size_request(combobox, width, height);
|
||||||
gtk_widget_show(combobox);
|
gtk_widget_show(combobox);
|
||||||
|
|
||||||
|
@@ -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,4 @@
|
|||||||
void pEditbox::create(uint style, uint width, uint height, const char *text) {
|
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) {
|
||||||
@@ -8,12 +8,12 @@ void pEditbox::create(uint style, uint width, uint height, const char *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);
|
||||||
} 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 :
|
||||||
GTK_POLICY_AUTOMATIC;
|
GTK_POLICY_AUTOMATIC;
|
||||||
GtkPolicyType vscroll = (style & Editbox::VerticalScrollAlways) ? GTK_POLICY_ALWAYS :
|
GtkPolicyType vscroll = (style & Editbox::VerticalScrollAlways) ? GTK_POLICY_ALWAYS :
|
||||||
(style & Editbox::VerticalScrollNever) ? GTK_POLICY_NEVER :
|
(style & Editbox::VerticalScrollNever) ? GTK_POLICY_NEVER :
|
||||||
GTK_POLICY_AUTOMATIC;
|
GTK_POLICY_AUTOMATIC;
|
||||||
scrollbox = gtk_scrolled_window_new(0, 0);
|
scrollbox = gtk_scrolled_window_new(0, 0);
|
||||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollbox), hscroll, vscroll);
|
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollbox), hscroll, vscroll);
|
||||||
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollbox), GTK_SHADOW_ETCHED_IN);
|
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollbox), GTK_SHADOW_ETCHED_IN);
|
||||||
@@ -26,6 +26,8 @@ void pEditbox::create(uint style, uint width, uint height, const char *text) {
|
|||||||
gtk_widget_show(editbox);
|
gtk_widget_show(editbox);
|
||||||
gtk_widget_show(scrollbox);
|
gtk_widget_show(scrollbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set_default_font(editbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pEditbox::set_text(const char *text) {
|
void pEditbox::set_text(const char *text) {
|
||||||
@@ -36,12 +38,12 @@ 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);
|
||||||
} else {
|
} else {
|
||||||
GtkTextIter start, end;
|
GtkTextIter start, end;
|
||||||
gtk_text_buffer_get_start_iter(buffer, &start);
|
gtk_text_buffer_get_start_iter(buffer, &start);
|
||||||
gtk_text_buffer_get_end_iter(buffer, &end);
|
gtk_text_buffer_get_end_iter(buffer, &end);
|
||||||
return strlcpy(text, gtk_text_buffer_get_text(buffer, &start, &end, true), length);
|
return strlcpy(text, gtk_text_buffer_get_text(buffer, &start, &end, true), 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,5 +1,6 @@
|
|||||||
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);
|
||||||
gtk_widget_set_size_request(frame, width, height);
|
gtk_widget_set_size_request(frame, width, height);
|
||||||
gtk_widget_show(frame);
|
gtk_widget_show(frame);
|
||||||
}
|
}
|
||||||
|
@@ -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&);
|
||||||
|
@@ -6,6 +6,17 @@ using nall::max;
|
|||||||
|
|
||||||
namespace libhiro {
|
namespace libhiro {
|
||||||
|
|
||||||
|
static void set_font(GtkWidget *widget, gpointer font) {
|
||||||
|
gtk_widget_modify_font(widget, (PangoFontDescription*)font);
|
||||||
|
if(GTK_IS_CONTAINER(widget)) {
|
||||||
|
gtk_container_foreach(GTK_CONTAINER(widget), (GtkCallback)set_font, font);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_default_font(GtkWidget *widget) {
|
||||||
|
set_font(widget, phiro().font);
|
||||||
|
}
|
||||||
|
|
||||||
#include "keymap.cpp"
|
#include "keymap.cpp"
|
||||||
#include "widget.cpp"
|
#include "widget.cpp"
|
||||||
#include "window.cpp"
|
#include "window.cpp"
|
||||||
@@ -49,9 +60,15 @@ void pHiro::init() {
|
|||||||
} else {
|
} else {
|
||||||
colormap = gdk_screen_get_rgb_colormap(screen);
|
colormap = gdk_screen_get_rgb_colormap(screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
font = pango_font_description_new();
|
||||||
|
pango_font_description_set_family(font, "Sans");
|
||||||
|
pango_font_description_set_absolute_size(font, 11.0 * PANGO_SCALE);
|
||||||
|
pango_font_description_set_style(font, PANGO_STYLE_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pHiro::term() {
|
void pHiro::term() {
|
||||||
|
pango_font_description_free(font);
|
||||||
enable_screensaver();
|
enable_screensaver();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,11 +158,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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -43,8 +43,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();
|
||||||
@@ -55,13 +55,14 @@ public:
|
|||||||
/* internal */
|
/* internal */
|
||||||
GdkScreen *screen;
|
GdkScreen *screen;
|
||||||
GdkColormap *colormap;
|
GdkColormap *colormap;
|
||||||
|
PangoFontDescription *font;
|
||||||
bool is_composited;
|
bool is_composited;
|
||||||
char default_path[PATH_MAX];
|
char default_path[PATH_MAX];
|
||||||
|
|
||||||
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,5 +1,6 @@
|
|||||||
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);
|
||||||
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
|
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
|
||||||
gtk_widget_set_size_request(label, width, height);
|
gtk_widget_set_size_request(label, width, height);
|
||||||
gtk_widget_show(label);
|
gtk_widget_show(label);
|
||||||
|
@@ -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,30 +1,30 @@
|
|||||||
void hiro_plistbox_change(pListbox *p) {
|
void hiro_plistbox_change(pListbox *p) {
|
||||||
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));
|
if(p->self.on_change) p->self.on_change(event_t(event_t::Change, p->listbox_selection = p->get_selection(), &p->self));
|
||||||
}
|
}
|
||||||
|
|
||||||
void hiro_plistbox_activate(pListbox *p) {
|
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));
|
if(p->self.on_activate) p->self.on_activate(event_t(event_t::Activate, p->listbox_selection = p->get_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);
|
||||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollbox), hscroll, vscroll);
|
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollbox), hscroll, vscroll);
|
||||||
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollbox), GTK_SHADOW_ETCHED_IN);
|
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollbox), GTK_SHADOW_ETCHED_IN);
|
||||||
|
|
||||||
lstring list;
|
lstring list;
|
||||||
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 +35,9 @@ GType *v = (GType*)malloc(count(list) * sizeof(GType));
|
|||||||
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 +46,7 @@ GType *v = (GType*)malloc(count(list) * sizeof(GType));
|
|||||||
|
|
||||||
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);
|
||||||
@@ -54,13 +54,15 @@ GType *v = (GType*)malloc(count(list) * sizeof(GType));
|
|||||||
|
|
||||||
g_signal_connect_swapped(G_OBJECT(listbox), "cursor-changed", G_CALLBACK(hiro_plistbox_change), (gpointer)this);
|
g_signal_connect_swapped(G_OBJECT(listbox), "cursor-changed", G_CALLBACK(hiro_plistbox_change), (gpointer)this);
|
||||||
g_signal_connect_swapped(G_OBJECT(listbox), "row-activated", G_CALLBACK(hiro_plistbox_activate), (gpointer)this);
|
g_signal_connect_swapped(G_OBJECT(listbox), "row-activated", G_CALLBACK(hiro_plistbox_activate), (gpointer)this);
|
||||||
|
|
||||||
|
set_default_font(listbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListbox::autosize_columns() {
|
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);
|
||||||
}
|
}
|
||||||
@@ -69,14 +71,14 @@ 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, 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);
|
||||||
@@ -84,7 +86,7 @@ GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(listbox));
|
|||||||
|
|
||||||
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, list[i](), -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,7 +96,7 @@ 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; }
|
||||||
}
|
}
|
||||||
@@ -109,12 +111,12 @@ GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(listbox));
|
|||||||
if(index < 0) { goto end; }
|
if(index < 0) { goto end; }
|
||||||
if(gtk_tree_model_get_iter_first(model, &iter) == false) { goto end; }
|
if(gtk_tree_model_get_iter_first(model, &iter) == false) { goto end; }
|
||||||
if(index == 0) { gtk_tree_selection_select_iter(selection, &iter); goto end; }
|
if(index == 0) { gtk_tree_selection_select_iter(selection, &iter); goto end; }
|
||||||
for(uint i = 1; i < 100000; i++) {
|
for(unsigned i = 1; i < 100000; i++) {
|
||||||
if(gtk_tree_model_iter_next(model, &iter) == false) { goto end; }
|
if(gtk_tree_model_iter_next(model, &iter) == false) { goto end; }
|
||||||
if(index == i) { gtk_tree_selection_select_iter(selection, &iter); goto end; }
|
if(index == i) { gtk_tree_selection_select_iter(selection, &iter); goto end; }
|
||||||
}
|
}
|
||||||
end:
|
end:
|
||||||
if(current != index) ;//{ owner->message(Message::Changed, (uintptr_t)this); }
|
if(current != index); //{ owner->message(Message::Changed, (uintptr_t)this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListbox::reset() {
|
void pListbox::reset() {
|
||||||
|
@@ -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,15 +1,18 @@
|
|||||||
void hiro_pmenucheckitem_tick(pMenuCheckItem *p) {
|
void hiro_pmenucheckitem_tick(pMenuCheckItem *p) {
|
||||||
if(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) {
|
||||||
item = gtk_check_menu_item_new_with_label(text ? text : "?");
|
item = gtk_check_menu_item_new_with_label(text ? text : "?");
|
||||||
|
set_default_font(item);
|
||||||
gtk_widget_show(item);
|
gtk_widget_show(item);
|
||||||
g_signal_connect_swapped(G_OBJECT(item), "toggled", G_CALLBACK(hiro_pmenucheckitem_tick), (gpointer)this);
|
g_signal_connect_swapped(G_OBJECT(item), "toggled", G_CALLBACK(hiro_pmenucheckitem_tick), (gpointer)this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pMenuCheckItem::check(bool state) {
|
void pMenuCheckItem::check(bool state) {
|
||||||
|
locked = true;
|
||||||
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), state ? TRUE : FALSE);
|
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), state ? TRUE : FALSE);
|
||||||
|
locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pMenuCheckItem::uncheck() {
|
void pMenuCheckItem::uncheck() {
|
||||||
@@ -22,6 +25,7 @@ bool pMenuCheckItem::checked() {
|
|||||||
|
|
||||||
pMenuCheckItem::pMenuCheckItem(MenuCheckItem &self_) : pMenuControl(self_), self(self_) {
|
pMenuCheckItem::pMenuCheckItem(MenuCheckItem &self_) : pMenuControl(self_), self(self_) {
|
||||||
item = 0;
|
item = 0;
|
||||||
|
locked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* internal */
|
/* internal */
|
||||||
|
@@ -9,6 +9,7 @@ public:
|
|||||||
pMenuCheckItem(MenuCheckItem&);
|
pMenuCheckItem(MenuCheckItem&);
|
||||||
|
|
||||||
/* internal */
|
/* internal */
|
||||||
GtkWidget *item;
|
|
||||||
GtkWidget* gtk_handle();
|
GtkWidget* gtk_handle();
|
||||||
|
GtkWidget *item;
|
||||||
|
bool locked;
|
||||||
};
|
};
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
void pMenuGroup::create(const char *text) {
|
void pMenuGroup::create(const char *text) {
|
||||||
group = gtk_menu_new();
|
group = gtk_menu_new();
|
||||||
item = gtk_menu_item_new_with_label(text ? text : "");
|
item = gtk_menu_item_new_with_label(text ? text : "");
|
||||||
|
set_default_font(item);
|
||||||
gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), group);
|
gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), group);
|
||||||
gtk_widget_show(item);
|
gtk_widget_show(item);
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,10 @@
|
|||||||
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) {
|
||||||
item = gtk_menu_item_new_with_label(text ? text : "");
|
item = gtk_menu_item_new_with_label(text ? text : "");
|
||||||
|
set_default_font(item);
|
||||||
g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(hiro_pmenuitem_tick), (gpointer)this);
|
g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(hiro_pmenuitem_tick), (gpointer)this);
|
||||||
gtk_widget_show(item);
|
gtk_widget_show(item);
|
||||||
}
|
}
|
||||||
|
@@ -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->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) {
|
||||||
@@ -10,12 +10,15 @@ void pMenuRadioItem::create(MenuRadioItemGroup &group, const char *text) {
|
|||||||
} else {
|
} else {
|
||||||
item = gtk_radio_menu_item_new_with_label_from_widget(GTK_RADIO_MENU_ITEM(group[0]->p.gtk_handle()), text ? text : "");
|
item = gtk_radio_menu_item_new_with_label_from_widget(GTK_RADIO_MENU_ITEM(group[0]->p.gtk_handle()), text ? text : "");
|
||||||
}
|
}
|
||||||
|
set_default_font(item);
|
||||||
gtk_widget_show(item);
|
gtk_widget_show(item);
|
||||||
g_signal_connect_swapped(G_OBJECT(item), "toggled", G_CALLBACK(hiro_pmenuradioitem_tick), (gpointer)this);
|
g_signal_connect_swapped(G_OBJECT(item), "toggled", G_CALLBACK(hiro_pmenuradioitem_tick), (gpointer)this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pMenuRadioItem::check() {
|
void pMenuRadioItem::check() {
|
||||||
|
locked = true;
|
||||||
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE);
|
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE);
|
||||||
|
locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pMenuRadioItem::checked() {
|
bool pMenuRadioItem::checked() {
|
||||||
@@ -24,6 +27,7 @@ bool pMenuRadioItem::checked() {
|
|||||||
|
|
||||||
pMenuRadioItem::pMenuRadioItem(MenuRadioItem &self_) : pMenuControl(self_), self(self_) {
|
pMenuRadioItem::pMenuRadioItem(MenuRadioItem &self_) : pMenuControl(self_), self(self_) {
|
||||||
item = 0;
|
item = 0;
|
||||||
|
locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* internal */
|
/* internal */
|
||||||
|
@@ -8,6 +8,7 @@ public:
|
|||||||
pMenuRadioItem(MenuRadioItem&);
|
pMenuRadioItem(MenuRadioItem&);
|
||||||
|
|
||||||
/* internal */
|
/* internal */
|
||||||
GtkWidget *item;
|
|
||||||
GtkWidget* gtk_handle();
|
GtkWidget* gtk_handle();
|
||||||
|
GtkWidget *item;
|
||||||
|
bool locked;
|
||||||
};
|
};
|
||||||
|
@@ -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,15 +1,16 @@
|
|||||||
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->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 {
|
||||||
radiobox = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(group[0]->p.gtk_handle()), text ? text : "");
|
radiobox = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(group[0]->p.gtk_handle()), text ? text : "");
|
||||||
}
|
}
|
||||||
|
set_default_font(radiobox);
|
||||||
gtk_widget_set_size_request(radiobox, width, height);
|
gtk_widget_set_size_request(radiobox, width, height);
|
||||||
gtk_widget_show(radiobox);
|
gtk_widget_show(radiobox);
|
||||||
g_signal_connect_swapped(G_OBJECT(radiobox), "toggled", G_CALLBACK(hiro_pradiobox_tick), (gpointer)this);
|
g_signal_connect_swapped(G_OBJECT(radiobox), "toggled", G_CALLBACK(hiro_pradiobox_tick), (gpointer)this);
|
||||||
@@ -21,7 +22,9 @@ void pRadiobox::set_text(const char *text) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void pRadiobox::check() {
|
void pRadiobox::check() {
|
||||||
|
locked = true;
|
||||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radiobox), TRUE);
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radiobox), TRUE);
|
||||||
|
locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pRadiobox::checked() {
|
bool pRadiobox::checked() {
|
||||||
@@ -30,6 +33,7 @@ bool pRadiobox::checked() {
|
|||||||
|
|
||||||
pRadiobox::pRadiobox(Radiobox &self_) : pFormControl(self), self(self_) {
|
pRadiobox::pRadiobox(Radiobox &self_) : pFormControl(self), self(self_) {
|
||||||
radiobox = 0;
|
radiobox = 0;
|
||||||
|
locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* internal */
|
/* internal */
|
||||||
|
@@ -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();
|
||||||
@@ -9,6 +9,7 @@ public:
|
|||||||
pRadiobox(Radiobox&);
|
pRadiobox(Radiobox&);
|
||||||
|
|
||||||
/* internal */
|
/* internal */
|
||||||
GtkWidget *radiobox;
|
|
||||||
GtkWidget* gtk_handle();
|
GtkWidget* gtk_handle();
|
||||||
|
GtkWidget *radiobox;
|
||||||
|
bool locked;
|
||||||
};
|
};
|
||||||
|
@@ -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 +1,14 @@
|
|||||||
class pSlider : public pFormControl {
|
class pSlider : public pFormControl {
|
||||||
public:
|
public:
|
||||||
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);
|
||||||
|
|
||||||
Slider &self;
|
Slider &self;
|
||||||
pSlider(Slider&);
|
pSlider(Slider&);
|
||||||
|
|
||||||
/* internal */
|
/* internal */
|
||||||
GtkWidget *slider;
|
GtkWidget *slider;
|
||||||
uint slider_position;
|
unsigned slider_position;
|
||||||
GtkWidget* gtk_handle();
|
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,16 @@ 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_keydown) p->self.on_keydown(event_t(event_t::KeyDown, phiro().translate_key(key->keyval), &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_keyup) p->self.on_keyup(event_t(event_t::KeyUp, phiro().translate_key(key->keyval), &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);
|
||||||
|
|
||||||
@@ -65,6 +65,7 @@ void pWindow::create(uint style, uint width, uint height, const char *text) {
|
|||||||
//without affecting the statusbar color
|
//without affecting the statusbar color
|
||||||
statuscontainer = gtk_event_box_new();
|
statuscontainer = gtk_event_box_new();
|
||||||
statusbar = gtk_statusbar_new();
|
statusbar = gtk_statusbar_new();
|
||||||
|
set_default_font(statusbar);
|
||||||
gtk_container_add(GTK_CONTAINER(statuscontainer), statusbar);
|
gtk_container_add(GTK_CONTAINER(statuscontainer), statusbar);
|
||||||
gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(statusbar), false);
|
gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(statusbar), false);
|
||||||
gtk_box_pack_start(GTK_BOX(menucontainer), statuscontainer, false, false, 0);
|
gtk_box_pack_start(GTK_BOX(menucontainer), statuscontainer, false, false, 0);
|
||||||
@@ -80,12 +81,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;
|
||||||
@@ -131,14 +132,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()) {
|
||||||
@@ -197,7 +198,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,
|
||||||
@@ -215,15 +216,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);
|
||||||
|
@@ -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.003 (2008-04-06)
|
version: 0.006 (2008-08-12)
|
||||||
author: byuu
|
author: byuu
|
||||||
license: public domain
|
license: public domain
|
||||||
*/
|
*/
|
||||||
@@ -11,10 +11,10 @@
|
|||||||
#include <nall/array.hpp>
|
#include <nall/array.hpp>
|
||||||
#include <nall/function.hpp>
|
#include <nall/function.hpp>
|
||||||
#include <nall/input.hpp>
|
#include <nall/input.hpp>
|
||||||
|
#include <nall/new.hpp>
|
||||||
#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;
|
|
||||||
|
|
||||||
namespace libhiro {
|
namespace libhiro {
|
||||||
|
|
||||||
@@ -88,8 +88,8 @@ 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,
|
KeyDown,
|
||||||
@@ -101,7 +101,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_) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -116,8 +116,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();
|
||||||
@@ -181,26 +181,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:
|
||||||
@@ -223,10 +223,10 @@ 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_keydown;
|
||||||
nall::function<uintptr_t (Event)> on_keyup;
|
nall::function<uintptr_t (event_t)> on_keyup;
|
||||||
|
|
||||||
Window();
|
Window();
|
||||||
|
|
||||||
@@ -267,7 +267,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;
|
||||||
@@ -282,7 +282,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;
|
||||||
@@ -296,7 +296,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;
|
||||||
@@ -315,7 +315,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);
|
||||||
@@ -334,7 +334,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();
|
||||||
@@ -346,7 +346,7 @@ 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();
|
||||||
|
|
||||||
@@ -359,7 +359,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();
|
||||||
@@ -371,10 +371,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();
|
||||||
|
|
||||||
@@ -385,13 +385,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();
|
||||||
|
|
||||||
@@ -402,12 +402,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();
|
||||||
|
|
||||||
@@ -431,8 +431,8 @@ 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 = "");
|
||||||
|
|
||||||
Editbox();
|
Editbox();
|
||||||
@@ -456,17 +456,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();
|
||||||
|
|
||||||
@@ -477,13 +477,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();
|
||||||
|
|
||||||
@@ -494,9 +494,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();
|
||||||
|
|
||||||
@@ -512,11 +512,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,5 +1,5 @@
|
|||||||
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("BUTTON", text ? 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);
|
||||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this);
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this);
|
||||||
@@ -7,7 +7,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) {
|
||||||
SetWindowText(hwnd, text ? text : "");
|
SetWindowText(hwnd, utf16(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
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,5 +1,5 @@
|
|||||||
void pCanvas::create(uint style, uint width, uint height) {
|
void pCanvas::create(unsigned style, unsigned width, unsigned height) {
|
||||||
hwnd = CreateWindow("hiro_window", "", 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);
|
||||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this);
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this);
|
||||||
@@ -8,6 +8,11 @@ void pCanvas::create(uint style, uint width, uint height) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void pCanvas::redraw() {
|
void pCanvas::redraw() {
|
||||||
|
PAINTSTRUCT ps;
|
||||||
|
BeginPaint(hwnd, &ps);
|
||||||
|
SetDIBitsToDevice(ps.hdc, 0, 0, iwidth, iheight, 0, 0, 0, iheight, (void*)ibuffer, &bmi, DIB_RGB_COLORS);
|
||||||
|
EndPaint(hwnd, &ps);
|
||||||
|
InvalidateRect(hwnd, 0, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t* pCanvas::buffer() {
|
uint32_t* pCanvas::buffer() {
|
||||||
@@ -30,14 +35,7 @@ pCanvas::~pCanvas() {
|
|||||||
|
|
||||||
/* internal */
|
/* internal */
|
||||||
|
|
||||||
void pCanvas::blit() {
|
void pCanvas::resize(unsigned width, unsigned height) {
|
||||||
PAINTSTRUCT ps;
|
|
||||||
BeginPaint(hwnd, &ps);
|
|
||||||
SetDIBitsToDevice(ps.hdc, 0, 0, iwidth, iheight, 0, 0, 0, iheight, (void*)ibuffer, &bmi, DIB_RGB_COLORS);
|
|
||||||
EndPaint(hwnd, &ps);
|
|
||||||
}
|
|
||||||
|
|
||||||
void pCanvas::resize(uint width, uint 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,7 +11,6 @@ public:
|
|||||||
/* internal */
|
/* internal */
|
||||||
BITMAPINFO bmi;
|
BITMAPINFO bmi;
|
||||||
uint32_t *ibuffer;
|
uint32_t *ibuffer;
|
||||||
uint ipitch, iwidth, iheight;
|
unsigned ipitch, iwidth, iheight;
|
||||||
void blit();
|
void resize(unsigned width, unsigned height);
|
||||||
void resize(uint width, uint height);
|
|
||||||
};
|
};
|
||||||
|
@@ -1,20 +1,16 @@
|
|||||||
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("BUTTON", text ? 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);
|
||||||
SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0);
|
SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pCheckbox::set_text(const char *text) {
|
void pCheckbox::set_text(const char *text) {
|
||||||
SetWindowText(hwnd, text ? text : "");
|
SetWindowText(hwnd, utf16(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pCheckbox::check(bool state) {
|
void pCheckbox::check(bool state) {
|
||||||
bool prev = checked();
|
|
||||||
SendMessage(hwnd, BM_SETCHECK, (WPARAM)(state ? TRUE : FALSE), 0);
|
SendMessage(hwnd, BM_SETCHECK, (WPARAM)(state ? TRUE : FALSE), 0);
|
||||||
if(prev != state) {
|
|
||||||
if(self.on_tick) self.on_tick(Event(Event::Tick, state, &self));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pCheckbox::uncheck() {
|
void pCheckbox::uncheck() {
|
||||||
|
@@ -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,5 +1,5 @@
|
|||||||
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, "COMBOBOX", "",
|
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,
|
||||||
phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
phiro().default_hwnd, (HMENU)instance, GetModuleHandle(0), 0);
|
||||||
@@ -17,7 +17,7 @@ void pCombobox::create(uint style, uint width, uint height, const char *text) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void pCombobox::add_item(const char *text) {
|
void pCombobox::add_item(const char *text) {
|
||||||
SendMessage(hwnd, CB_ADDSTRING, 0, (LPARAM)text);
|
SendMessage(hwnd, CB_ADDSTRING, 0, (LPARAM)(wchar_t*)utf16(text));
|
||||||
if(SendMessage(hwnd, CB_GETCOUNT, 0, 0) == 1) set_selection(0);
|
if(SendMessage(hwnd, CB_GETCOUNT, 0, 0) == 1) set_selection(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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,14 +1,14 @@
|
|||||||
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, "EDIT", "",
|
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, L"EDIT", L"",
|
||||||
WS_CHILD | WS_VISIBLE | vscroll | hscroll |
|
WS_CHILD | WS_VISIBLE | vscroll | hscroll |
|
||||||
(multiline == true ? ES_MULTILINE | ES_WANTRETURN : WS_TABSTOP) |
|
(multiline == true ? ES_MULTILINE | ES_WANTRETURN : WS_TABSTOP) |
|
||||||
(readonly == true ? ES_READONLY : 0),
|
(readonly == true ? ES_READONLY : 0),
|
||||||
@@ -22,14 +22,16 @@ void pEditbox::set_text(const char *text) {
|
|||||||
string temp = text ? text : "";
|
string temp = text ? text : "";
|
||||||
replace(temp, "\r", "");
|
replace(temp, "\r", "");
|
||||||
replace(temp, "\n", "\r\n");
|
replace(temp, "\n", "\r\n");
|
||||||
SetWindowText(hwnd, temp);
|
SetWindowText(hwnd, utf16(temp));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint pEditbox::get_text(char *text, uint length) {
|
unsigned pEditbox::get_text(char *text, unsigned length) {
|
||||||
GetWindowText(hwnd, text, length);
|
wchar_t *buffer = new wchar_t[length + 1];
|
||||||
string temp = text;
|
GetWindowText(hwnd, buffer, length);
|
||||||
|
string temp = (const char*)utf8(buffer);
|
||||||
|
delete[] buffer;
|
||||||
replace(temp, "\r", "");
|
replace(temp, "\r", "");
|
||||||
strcpy(text, temp);
|
strlcpy(text, temp, length);
|
||||||
return strlen(text);
|
return strlen(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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) {
|
||||||
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,12 +1,12 @@
|
|||||||
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("BUTTON", text ? 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);
|
||||||
SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0);
|
SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pFrame::set_text(const char *text) {
|
void pFrame::set_text(const char *text) {
|
||||||
SetWindowText(hwnd, text ? text : "");
|
SetWindowText(hwnd, utf16(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
pFrame::pFrame(Frame &self_) : pFormControl(self_), self(self_) {
|
pFrame::pFrame(Frame &self_) : pFormControl(self_), self(self_) {
|
||||||
|
@@ -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&);
|
||||||
|
@@ -4,6 +4,10 @@
|
|||||||
using nall::min;
|
using nall::min;
|
||||||
using nall::max;
|
using nall::max;
|
||||||
|
|
||||||
|
#include <nall/utf8.hpp>
|
||||||
|
using nall::utf8;
|
||||||
|
using nall::utf16;
|
||||||
|
|
||||||
namespace libhiro {
|
namespace libhiro {
|
||||||
|
|
||||||
LRESULT CALLBACK phiro_wndproc(HWND, UINT, WPARAM, LPARAM);
|
LRESULT CALLBACK phiro_wndproc(HWND, UINT, WPARAM, LPARAM);
|
||||||
@@ -43,14 +47,14 @@ void pHiro::init() {
|
|||||||
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
|
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
|
||||||
wc.hInstance = GetModuleHandle(0);
|
wc.hInstance = GetModuleHandle(0);
|
||||||
wc.lpfnWndProc = phiro_wndproc;
|
wc.lpfnWndProc = phiro_wndproc;
|
||||||
wc.lpszClassName = "hiro_window";
|
wc.lpszClassName = L"hiro_window";
|
||||||
wc.lpszMenuName = 0;
|
wc.lpszMenuName = 0;
|
||||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||||
RegisterClass(&wc);
|
RegisterClass(&wc);
|
||||||
|
|
||||||
InitCommonControls();
|
InitCommonControls();
|
||||||
default_hwnd = CreateWindow("hiro_window", "", WS_POPUP, 0, 0, 640, 480, 0, 0, GetModuleHandle(0), 0);
|
default_hwnd = CreateWindow(L"hiro_window", L"", WS_POPUP, 0, 0, 640, 480, 0, 0, GetModuleHandle(0), 0);
|
||||||
default_font = create_font("Tahoma", 9);
|
default_font = create_font("Tahoma", 8);
|
||||||
black_brush = CreateSolidBrush(RGB(0, 0, 0));
|
black_brush = CreateSolidBrush(RGB(0, 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,12 +80,13 @@ bool pHiro::pending() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool pHiro::folder_select(Window *focus, char *filename, const char *path) {
|
bool pHiro::folder_select(Window *focus, char *filename, const char *path) {
|
||||||
|
wchar_t wfilename[_MAX_PATH] = L"";
|
||||||
strcpy(filename, "");
|
strcpy(filename, "");
|
||||||
BROWSEINFO bi;
|
BROWSEINFO bi;
|
||||||
bi.hwndOwner = focus ? focus->p.hwnd : 0;
|
bi.hwndOwner = focus ? focus->p.hwnd : 0;
|
||||||
bi.pidlRoot = NULL;
|
bi.pidlRoot = NULL;
|
||||||
bi.pszDisplayName = filename;
|
bi.pszDisplayName = wfilename;
|
||||||
bi.lpszTitle = "Select Folder";
|
bi.lpszTitle = L"";
|
||||||
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS;
|
bi.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS;
|
||||||
bi.lpfn = NULL;
|
bi.lpfn = NULL;
|
||||||
bi.lParam = 0;
|
bi.lParam = 0;
|
||||||
@@ -89,7 +94,7 @@ bool pHiro::folder_select(Window *focus, char *filename, const char *path) {
|
|||||||
bool result = false;
|
bool result = false;
|
||||||
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
|
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
|
||||||
if(pidl) {
|
if(pidl) {
|
||||||
if(SHGetPathFromIDList(pidl, filename)) {
|
if(SHGetPathFromIDList(pidl, wfilename)) {
|
||||||
result = true;
|
result = true;
|
||||||
IMalloc *imalloc = 0;
|
IMalloc *imalloc = 0;
|
||||||
if(SUCCEEDED(SHGetMalloc(&imalloc))) {
|
if(SUCCEEDED(SHGetMalloc(&imalloc))) {
|
||||||
@@ -98,6 +103,7 @@ bool pHiro::folder_select(Window *focus, char *filename, const char *path) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
strcpy(filename, utf8(wfilename));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,23 +114,28 @@ bool pHiro::file_open(Window *focus, char *filename, const char *path, const cha
|
|||||||
|
|
||||||
lstring type, part;
|
lstring type, part;
|
||||||
strcpy(f, "");
|
strcpy(f, "");
|
||||||
split(type, "|", filter);
|
split(type, "\n", filter);
|
||||||
for(int i = 0; i < count(type); i++) {
|
for(int i = 0; i < count(type); i++) {
|
||||||
split(part, ";", type[i]);
|
split(part, "\t", type[i]);
|
||||||
if(count(part) != 2)continue;
|
if(count(part) != 2) continue;
|
||||||
|
|
||||||
strcat(f, part[0]);
|
strcat(f, part[0]);
|
||||||
strcat(f, " (");
|
strcat(f, " (");
|
||||||
strcat(f, part[1]);
|
strcat(f, part[1]);
|
||||||
strcat(f, ")|");
|
strcat(f, ")\t");
|
||||||
replace(part[1], ",", ";");
|
replace(part[1], ",", ";");
|
||||||
strcat(f, part[1]);
|
strcat(f, part[1]);
|
||||||
strcat(f, "|");
|
strcat(f, "\t");
|
||||||
}
|
}
|
||||||
|
|
||||||
char *pf = f();
|
utf16 wfilter(f);
|
||||||
for(int i = strlen(pf) - 1; i >= 0; i--) {
|
utf16 wdir(dir);
|
||||||
if(pf[i] == '|') pf[i] = '\0';
|
wchar_t wfilename[_MAX_PATH] = L"";
|
||||||
|
|
||||||
|
wchar_t *p = wfilter;
|
||||||
|
while(*p != L'\0') {
|
||||||
|
if(*p == L'\t') *p = L'\0';
|
||||||
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
OPENFILENAME ofn;
|
OPENFILENAME ofn;
|
||||||
@@ -132,14 +143,16 @@ bool pHiro::file_open(Window *focus, char *filename, const char *path, const cha
|
|||||||
memset(&ofn, 0, sizeof(ofn));
|
memset(&ofn, 0, sizeof(ofn));
|
||||||
ofn.lStructSize = sizeof(ofn);
|
ofn.lStructSize = sizeof(ofn);
|
||||||
ofn.hwndOwner = focus ? focus->p.hwnd : 0;
|
ofn.hwndOwner = focus ? focus->p.hwnd : 0;
|
||||||
ofn.lpstrFilter = pf;
|
ofn.lpstrFilter = wfilter;
|
||||||
ofn.lpstrInitialDir = dir;
|
ofn.lpstrInitialDir = wdir;
|
||||||
ofn.lpstrFile = filename;
|
ofn.lpstrFile = wfilename;
|
||||||
ofn.nMaxFile = MAX_PATH;
|
ofn.nMaxFile = MAX_PATH;
|
||||||
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST;
|
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST;
|
||||||
ofn.lpstrDefExt = "";
|
ofn.lpstrDefExt = L"";
|
||||||
|
|
||||||
return GetOpenFileName(&ofn);
|
bool result = GetOpenFileName(&ofn);
|
||||||
|
strcpy(filename, utf8(wfilename));
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pHiro::file_save(Window *focus, char *filename, const char *path, const char *filter) {
|
bool pHiro::file_save(Window *focus, char *filename, const char *path, const char *filter) {
|
||||||
@@ -149,23 +162,28 @@ bool pHiro::file_save(Window *focus, char *filename, const char *path, const cha
|
|||||||
|
|
||||||
lstring type, part;
|
lstring type, part;
|
||||||
strcpy(f, "");
|
strcpy(f, "");
|
||||||
split(type, "|", filter);
|
split(type, "\n", filter);
|
||||||
for(int i = 0; i < count(type); i++) {
|
for(int i = 0; i < count(type); i++) {
|
||||||
split(part, ";", type[i]);
|
split(part, "\t", type[i]);
|
||||||
if(count(part) != 2)continue;
|
if(count(part) != 2) continue;
|
||||||
|
|
||||||
strcat(f, part[0]);
|
strcat(f, part[0]);
|
||||||
strcat(f, " (");
|
strcat(f, " (");
|
||||||
strcat(f, part[1]);
|
strcat(f, part[1]);
|
||||||
strcat(f, ")|");
|
strcat(f, ")\t");
|
||||||
replace(part[1], ",", ";");
|
replace(part[1], ",", ";");
|
||||||
strcat(f, part[1]);
|
strcat(f, part[1]);
|
||||||
strcat(f, "|");
|
strcat(f, "\t");
|
||||||
}
|
}
|
||||||
|
|
||||||
char *pf = f();
|
utf16 wfilter(f);
|
||||||
for(int i = strlen(pf) - 1; i >= 0; i--) {
|
utf16 wdir(dir);
|
||||||
if(pf[i] == '|') pf[i] = '\0';
|
wchar_t wfilename[_MAX_PATH] = L"";
|
||||||
|
|
||||||
|
wchar_t *p = wfilter;
|
||||||
|
while(*p != L'\0') {
|
||||||
|
if(*p == L'\t') *p = L'\0';
|
||||||
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
OPENFILENAME ofn;
|
OPENFILENAME ofn;
|
||||||
@@ -173,21 +191,23 @@ bool pHiro::file_save(Window *focus, char *filename, const char *path, const cha
|
|||||||
memset(&ofn, 0, sizeof(ofn));
|
memset(&ofn, 0, sizeof(ofn));
|
||||||
ofn.lStructSize = sizeof(ofn);
|
ofn.lStructSize = sizeof(ofn);
|
||||||
ofn.hwndOwner = focus ? focus->p.hwnd : 0;
|
ofn.hwndOwner = focus ? focus->p.hwnd : 0;
|
||||||
ofn.lpstrFilter = pf;
|
ofn.lpstrFilter = wfilter;
|
||||||
ofn.lpstrInitialDir = dir;
|
ofn.lpstrInitialDir = wdir;
|
||||||
ofn.lpstrFile = filename;
|
ofn.lpstrFile = wfilename;
|
||||||
ofn.nMaxFile = MAX_PATH;
|
ofn.nMaxFile = MAX_PATH;
|
||||||
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST;
|
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST;
|
||||||
ofn.lpstrDefExt = "";
|
ofn.lpstrDefExt = L"";
|
||||||
|
|
||||||
return GetSaveFileName(&ofn);
|
bool result = GetSaveFileName(&ofn);
|
||||||
|
strcpy(filename, utf8(wfilename));
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,17 +233,17 @@ pHiro& phiro() {
|
|||||||
|
|
||||||
/* internal */
|
/* internal */
|
||||||
|
|
||||||
HFONT pHiro::create_font(const char *name, uint size) {
|
HFONT pHiro::create_font(const char *name, unsigned size) {
|
||||||
HDC hdc = GetDC(0);
|
return CreateFont(
|
||||||
HFONT font = CreateFont(-MulDiv(size, GetDeviceCaps(hdc, LOGPIXELSY), 72),
|
-(size * 96.0 / 72.0 + 0.5), //96 = DPI
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, name);
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
ReleaseDC(0, hdc);
|
utf16(name)
|
||||||
return font;
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
@@ -256,38 +276,38 @@ 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_keydown) w.on_keydown(event_t(event_t::KeyDown, translate_key(wparam), &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_keyup) w.on_keyup(event_t(event_t::KeyUp, translate_key(wparam), &w));
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case WM_ERASEBKGND: {
|
case WM_ERASEBKGND: {
|
||||||
if(!p) break;
|
if(!p) break;
|
||||||
HBRUSH brush = 0;
|
HBRUSH brush = 0;
|
||||||
if(p->self.type == Widget::WindowType) brush = ((pWindow*)p)->background;
|
if(p->self.type == Widget::WindowType) brush = ((pWindow*)p)->background;
|
||||||
if(p->self.type == Widget::CanvasType) brush = phiro().black_brush;
|
if(p->self.type == Widget::CanvasType) brush = phiro().black_brush;
|
||||||
if(!brush) break;
|
if(!brush) break;
|
||||||
RECT rc;
|
RECT rc;
|
||||||
GetClientRect(hwnd, &rc);
|
GetClientRect(hwnd, &rc);
|
||||||
PAINTSTRUCT ps;
|
PAINTSTRUCT ps;
|
||||||
BeginPaint(hwnd, &ps);
|
BeginPaint(hwnd, &ps);
|
||||||
FillRect(ps.hdc, &rc, brush);
|
FillRect(ps.hdc, &rc, brush);
|
||||||
EndPaint(hwnd, &ps);
|
EndPaint(hwnd, &ps);
|
||||||
@@ -295,43 +315,49 @@ LRESULT pHiro::wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case WM_PAINT: {
|
case WM_PAINT: {
|
||||||
if(p && p->self.type == Widget::CanvasType) ((pCanvas*)p)->blit();
|
if(p && p->self.type == Widget::CanvasType) ((pCanvas*)p)->redraw();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case WM_COMMAND: {
|
case WM_COMMAND: {
|
||||||
Widget *widget = get_widget(LOWORD(wparam));
|
Widget *widget = get_widget(LOWORD(wparam));
|
||||||
if(!widget) break;
|
if(!widget) break;
|
||||||
|
|
||||||
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_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();
|
||||||
w.check();
|
w.check();
|
||||||
|
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_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();
|
||||||
w.check();
|
w.check();
|
||||||
|
if(!checked && w.on_tick) w.on_tick(event_t(event_t::Tick, w.checked(), &w));
|
||||||
} break;
|
} 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;
|
||||||
}
|
}
|
||||||
@@ -339,33 +365,33 @@ LRESULT pHiro::wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
|||||||
|
|
||||||
case WM_HSCROLL:
|
case WM_HSCROLL:
|
||||||
case WM_VSCROLL: {
|
case WM_VSCROLL: {
|
||||||
Widget *widget = get_widget(GetDlgCtrlID((HWND)lparam));
|
Widget *widget = get_widget(GetDlgCtrlID((HWND)lparam));
|
||||||
if(!widget) break;
|
if(!widget) break;
|
||||||
|
|
||||||
switch(widget->type) {
|
switch(widget->type) {
|
||||||
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;
|
||||||
|
|
||||||
case WM_NOTIFY: {
|
case WM_NOTIFY: {
|
||||||
Widget *widget = get_widget(LOWORD(wparam));
|
Widget *widget = get_widget(LOWORD(wparam));
|
||||||
if(!widget) break;
|
if(!widget) break;
|
||||||
|
|
||||||
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
|
if(((LPNMHDR)lparam)->code == LVN_ITEMCHANGED
|
||||||
&& ((LPNMLISTVIEW)lparam)->uChanged & LVIF_STATE
|
&& ((LPNMLISTVIEW)lparam)->uChanged & LVIF_STATE
|
||||||
&& ListView_GetItemState(listbox.p.hwnd, ((LPNMLISTVIEW)lparam)->iItem, LVIS_FOCUSED)
|
&& ListView_GetItemState(listbox.p.hwnd, ((LPNMLISTVIEW)lparam)->iItem, LVIS_FOCUSED)
|
||||||
&& ListView_GetItemState(listbox.p.hwnd, ((LPNMLISTVIEW)lparam)->iItem, LVIS_SELECTED)
|
&& ListView_GetItemState(listbox.p.hwnd, ((LPNMLISTVIEW)lparam)->iItem, LVIS_SELECTED)
|
||||||
) {
|
) {
|
||||||
if(listbox.on_change) listbox.on_change(Event(Event::Change, listbox.get_selection(), &listbox));
|
if(listbox.on_change) listbox.on_change(event_t(event_t::Change, listbox.get_selection(), &listbox));
|
||||||
} else if(((LPNMHDR)lparam)->code == LVN_ITEMACTIVATE) {
|
} else if(((LPNMHDR)lparam)->code == LVN_ITEMACTIVATE) {
|
||||||
if(listbox.on_activate) listbox.on_activate(Event(Event::Activate, listbox.get_selection(), &listbox));
|
if(listbox.on_activate) listbox.on_activate(event_t(event_t::Activate, listbox.get_selection(), &listbox));
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
#define _WIN32_IE 0x0600
|
#define _WIN32_IE 0x0600
|
||||||
#define NOMINMAX
|
#define NOMINMAX
|
||||||
|
|
||||||
|
#define UNICODE
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <commctrl.h>
|
#include <commctrl.h>
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
@@ -50,8 +51,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();
|
||||||
@@ -65,12 +66,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;
|
||||||
|
|
||||||
@@ -30,6 +30,13 @@ uint16_t pHiro::translate_key(uint key) {
|
|||||||
case '8': return keyboard::num_8;
|
case '8': return keyboard::num_8;
|
||||||
case '9': return keyboard::num_9;
|
case '9': return keyboard::num_9;
|
||||||
|
|
||||||
|
case VK_INSERT: return keyboard::insert;
|
||||||
|
case VK_DELETE: return keyboard::delete_;
|
||||||
|
case VK_HOME: return keyboard::home;
|
||||||
|
case VK_END: return keyboard::end;
|
||||||
|
case VK_PRIOR: return keyboard::page_up;
|
||||||
|
case VK_NEXT: return keyboard::page_down;
|
||||||
|
|
||||||
case 'A': return keyboard::a;
|
case 'A': return keyboard::a;
|
||||||
case 'B': return keyboard::b;
|
case 'B': return keyboard::b;
|
||||||
case 'C': return keyboard::c;
|
case 'C': return keyboard::c;
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
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("STATIC", text ? 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);
|
||||||
SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0);
|
SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pLabel::set_text(const char *text) {
|
void pLabel::set_text(const char *text) {
|
||||||
SetWindowText(hwnd, text ? text : "");
|
SetWindowText(hwnd, utf16(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
pLabel::pLabel(Label &self_) : pFormControl(self_), self(self_) {
|
pLabel::pLabel(Label &self_) : pFormControl(self_), self(self_) {
|
||||||
|
@@ -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,12 +1,12 @@
|
|||||||
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;
|
||||||
uint hscroll = (style & Listbox::HorizontalScrollAlways) ? WS_HSCROLL :
|
unsigned hscroll = (style & Listbox::HorizontalScrollAlways) ? WS_HSCROLL :
|
||||||
(style & Listbox::HorizontalScrollNever) ? 0 :
|
(style & Listbox::HorizontalScrollNever) ? 0 :
|
||||||
0;
|
0;
|
||||||
uint vscroll = (style & Listbox::VerticalScrollAlways) ? WS_VSCROLL :
|
unsigned vscroll = (style & Listbox::VerticalScrollAlways) ? WS_VSCROLL :
|
||||||
(style & Listbox::VerticalScrollNever) ? 0 :
|
(style & Listbox::VerticalScrollNever) ? 0 :
|
||||||
0;
|
0;
|
||||||
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, "",
|
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, WC_LISTVIEW, L"",
|
||||||
WS_CHILD | WS_TABSTOP | WS_VISIBLE |
|
WS_CHILD | WS_TABSTOP | WS_VISIBLE |
|
||||||
LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | vscroll | hscroll |
|
LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | vscroll | hscroll |
|
||||||
(header ? 0 : LVS_NOCOLUMNHEADER),
|
(header ? 0 : LVS_NOCOLUMNHEADER),
|
||||||
@@ -15,70 +15,74 @@ uint vscroll = (style & Listbox::VerticalScrollAlways) ? WS_VSCROLL :
|
|||||||
SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0);
|
SendMessage(hwnd, WM_SETFONT, (WPARAM)phiro().default_font, 0);
|
||||||
ListView_SetExtendedListViewStyle(hwnd, LVS_EX_FULLROWSELECT);
|
ListView_SetExtendedListViewStyle(hwnd, LVS_EX_FULLROWSELECT);
|
||||||
|
|
||||||
lstring list;
|
lstring list;
|
||||||
split(list, "\t", columns ? columns : "");
|
split(list, "\t", columns ? columns : "");
|
||||||
column_count = count(list);
|
column_count = count(list);
|
||||||
for(uint i = 0; i < count(list); i++) {
|
for(unsigned i = 0; i < count(list); i++) {
|
||||||
LVCOLUMN column;
|
LVCOLUMN column;
|
||||||
column.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM;
|
column.mask = LVCF_FMT | LVCF_TEXT | LVCF_SUBITEM;
|
||||||
column.fmt = LVCFMT_LEFT;
|
column.fmt = LVCFMT_LEFT;
|
||||||
column.iSubItem = count(list);
|
column.iSubItem = count(list);
|
||||||
column.pszText = (LPSTR)list[i]();
|
utf16 ulist(list[i]);
|
||||||
|
column.pszText = ulist;
|
||||||
ListView_InsertColumn(hwnd, i, &column);
|
ListView_InsertColumn(hwnd, i, &column);
|
||||||
}
|
}
|
||||||
|
|
||||||
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]);
|
||||||
}
|
}
|
||||||
autosize_columns();
|
autosize_columns();
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListbox::autosize_columns() {
|
void pListbox::autosize_columns() {
|
||||||
for(uint i = 0; i < column_count; i++) {
|
for(unsigned i = 0; i < column_count; i++) {
|
||||||
ListView_SetColumnWidth(hwnd, i, LVSCW_AUTOSIZE_USEHEADER);
|
ListView_SetColumnWidth(hwnd, i, LVSCW_AUTOSIZE_USEHEADER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListbox::add_item(const char *text) {
|
void pListbox::add_item(const char *text) {
|
||||||
lstring list;
|
lstring list;
|
||||||
split(list, "\t", text ? text : "");
|
split(list, "\t", text ? text : "");
|
||||||
LVITEM item;
|
LVITEM item;
|
||||||
uint pos = ListView_GetItemCount(hwnd);
|
unsigned pos = ListView_GetItemCount(hwnd);
|
||||||
item.mask = LVIF_TEXT;
|
item.mask = LVIF_TEXT;
|
||||||
item.iItem = pos;
|
item.iItem = pos;
|
||||||
item.iSubItem = 0;
|
item.iSubItem = 0;
|
||||||
item.pszText = (LPSTR)list[0]();
|
utf16 wtext(list[0]);
|
||||||
|
item.pszText = wtext;
|
||||||
ListView_InsertItem(hwnd, &item);
|
ListView_InsertItem(hwnd, &item);
|
||||||
|
|
||||||
for(uint i = 1; i < count(list); i++) {
|
for(unsigned i = 1; i < count(list); i++) {
|
||||||
ListView_SetItemText(hwnd, pos, i, (LPSTR)list[i]());
|
utf16 wtext(list[i]);
|
||||||
|
ListView_SetItemText(hwnd, pos, i, wtext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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(uint i = 0; i < count(list); i++) {
|
for(unsigned i = 0; i < count(list); i++) {
|
||||||
ListView_SetItemText(hwnd, index, i, list[i]());
|
utf16 wtext(list[i]);
|
||||||
|
ListView_SetItemText(hwnd, index, i, wtext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int pListbox::get_selection() {
|
int pListbox::get_selection() {
|
||||||
uint count = ListView_GetItemCount(hwnd);
|
unsigned count = ListView_GetItemCount(hwnd);
|
||||||
for(uint i = 0; i < count; i++) {
|
for(unsigned i = 0; i < count; i++) {
|
||||||
if(ListView_GetItemState(hwnd, i, LVIS_SELECTED)) return i;
|
if(ListView_GetItemState(hwnd, i, LVIS_SELECTED)) return i;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListbox::set_selection(int index) {
|
void pListbox::set_selection(int index) {
|
||||||
uint count = ListView_GetItemCount(hwnd);
|
unsigned count = ListView_GetItemCount(hwnd);
|
||||||
for(uint i = 0; i < count; i++) {
|
for(unsigned i = 0; i < count; i++) {
|
||||||
ListView_SetItemState(hwnd, i, LVIS_FOCUSED, (i == index) ? LVIS_FOCUSED : 0);
|
ListView_SetItemState(hwnd, i, LVIS_FOCUSED, (i == index) ? LVIS_FOCUSED : 0);
|
||||||
ListView_SetItemState(hwnd, i, LVIS_SELECTED, (i == index) ? LVIS_SELECTED : 0);
|
ListView_SetItemState(hwnd, i, LVIS_SELECTED, (i == index) ? LVIS_SELECTED : 0);
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user