Compare commits

...

9 Commits
v062 ... v063

Author SHA1 Message Date
byuu
27c24bc8a6 Update to bsnes v063 release.
Time for another (hopefully) stable release. The changelog has all updates since the last stable release.
Most notably, this release features substantial accuracy improvements all around. Almost all of them represent brand new findings never before seen in any SNES emulator.
Changelog:
    - fixed off-by-one buffer size issue in S-PPU RTO calculations [PiCiJi]
    - added XML parser
    - added XML-based memory mapping system
    - moved header-based memory mapping code into snesreader library
    - added some linker flags for Fedora [belegdol]
    - added cheat code database; with codes for over 1,500 games [mightymo]
    - fixed a bug where S-CPU IRQs were being tested one cycle early on direct page indexed read opcodes
    - added global cheat system enable/disable checkbox to cheat code editor
    - fixed bug in overflow calculation of S-CPU ADC and SBC opcodes in BCD mode [blargg]
    - emulated the S-CPU ALU MUL and DIV hardware delays with partial result calculation steps [blargg]
    - controller port read now returns real-time results of B button when strobe latch is raised
    - major improvements to emulation of the S-SMP TEST register [blargg, byuu]
    - fixed DSP2 memory map [Overload]
    - "Apply Patch" checkbox will now scan UPS patch folder if one is set in the paths section
    - fixed S-CPU TSC negative flag calculation in emulation mode [address]
    - added "make uninstall" command to Makefile for Linux users
    - S-CPU (H)DMA now updates the S-CPU MDR; fixes a freeze in Speedy Gonzales - Stage 6-1
    - very substantial code cleanups and optimizations as a result of moving from C++98 to C++0x
2010-03-28 15:46:44 +00:00
byuu
fac95dfec5 Update to bsnes v062r10 release.
Added make uninstall, and fixed up nall::function to also bind lambdas
that don't yet exist in GCC 4.4.

Spent most of tonight rewriting the standalone UPS patcher.
2010-03-24 14:19:38 +00:00
byuu
362542924e Update to bsnes v062r09 release.
Mostly minor stuff again.

Fixes:
array, linear_vector and pointer_vector need to set source.pool = 0
before calling reset() to avoid destroying the object we're trying to
move.
All of nall::string is inside namespace nall now. No idea what I was
trying to do before with the half-global approach.
nall::function gains a reset() function, more obvious than func =
(void*)0;
The movie file loader wasn't binding the right action when changing
files and clicking load, can't believe nobody noticed that one.
2010-03-23 12:12:10 +00:00
byuu
4179282244 Update to bsnes v062r08 release.
This WIP has bsnes.exe, snesreader.dll, and src/. If you need anything
else, get it from past releases, please.

I fixed TSC negative flag calculation in emulation mode. Will pass
this test now:
http://blargg.parodius.com/snes-tests/snes_test_tsc.zip

_Way_ too obscure to affect anything, but definitely good to get it
right.

Also rewrote nall/function.hpp to use C++0x variadic templates. New
version is ~85 lines instead of ~190, 40% smaller, doesn't require
recursively including itself, doesn't require the C preprocessor,
evaluates to ensure the member function pointer is big enough to hold
what you're assigning statically (at compile time) instead of
dynamically (at run time), and supports infinite arguments instead of
zero to eight now.
2010-03-21 07:36:46 +00:00
byuu
02820ef2e9 Update to bsnes v062r07 release.
This is source code only, no binaries. Sorry, worn out after spending
four hours straight writing crazy ass Julian<>Gregorian date
functions. Holy fucking hell that is crazy shit. Tell me, how many
days have passed since 01-01-4731 BC on the Julian calendar?

Okay, this really was just about taking advantage of vectors inside of
vectors. I've updated the XML parser to use vectors of actual objects
instead of pointers. This makes cleanup free, and turns countless ->'s
into .'s -- much nicer to look at. I may take advantage of overloaded
operators for something now, not sure yet.
2010-03-19 12:50:55 +00:00
byuu
0ecce7b93d Update to bsnes v062r06 release.
You'll need snesreader's DLL from my last WIP post to use the above.

This initializes mode, region and ram_size again in Cartridge::load()
to stop the phantom SRAM files from being generated.
This fixes DSP-2 mapping to match Overload's findings (which requires
an unposted snesreader, so Dungeon Master won't run for you guys yet.)
This removes nall/traits.hpp and uses std::tr1::type_traits instead.
It also drops move, forward and identity in favor of those from
std::tr1::utility*.
This fixes linear_vector and pointer_vector to not crash when using
vectors of vectors and copying them.
This fixed linear_vector, pointer_vector and array to initialize all
internal variables for all constructors.
This fixes the file browser to look for patches in your patch
directory, so the "Apply Patch" box should work correctly now.

* I have no objection to using functions from the C++ standard library
when they don't suck.
2010-03-18 15:32:55 +00:00
byuu
f94fcd6f30 Update to bsnes v062r05 release.
To run this, you'll need the DLLs from v062r04's public beta, and the
updated snesreader.dll in the same folder as the WIP. No profiling.

This fixes UPS patching, and it also modifies snesreader to generate
the XML map separately, so that the map can be generated post-
patching.
The new enum classes weren't attaching properly to the config file, so
the input settings, expansion port and region settings are saved
again.
It also converts the S-SMP timers back to unsigned integers instead of
using floating point, no accuracy improvement but much more in line
with hardware.
Lastly, it makes the div register shift left 16 places and pre-shifts
on divide, which is just for aesthetics.

And I'll wait on your tests, FitzRoy. I really hope that Big Run
Jaleco Rally is correct, because I don't have the first idea how to
debug that one. Speedy I can probably handle.
2010-03-17 12:58:18 +00:00
byuu
57f903630a Update to bsnes v062r04 release.
I suppose I should start calling these nightlies, heh. blargg went ahead and verified every last possible edge case with regards to the S-CPU MUL / DIV registers. It uncovered a few errors in my implementation, which have since been corrected. The design used now should be a direct reflection of the hardware implementation: no actual multiplication, no actual division, and no variable-length bit-shifting.
We also spent about eight hours straight hammering away at the S-SMP test register. We have a partial understanding of TEST.d3 and TEST.d0, and a complete understanding of the other six bits. All of this has been implemented as well.
Lastly, snesreader gets a tiny update to fix Test Drive II, which broke due to a slight regression when porting the mapping code to XML.
2010-03-15 23:24:58 +00:00
byuu
9329de0a8d Update to bsnes v062r03 release.
blargg and I sat around for a good 8+ hours today hacking away at the
S-SMP Pandora's Box: the TEST register. What better way to spend Pi
Day, right?

We came up with the following tests:
http://byuusan.kuro-hitsuji.net/blargg_2010-03-14.zip

First, controller_strobebehavior.smc improves emulation of $4016. When
the joypad strobe latch = 1, reading $4016 returns the current value
of the B button. As in, you can keep reading it over and over. It
won't increment the shift register, and it will keep telling you the
actual current state of the button. This is very much like the NES
behavior. One more TODO in the S-CPU code taken care of.

Next, all kinds of S-SMP TEST register improvements. Turns out d7-d6
alone controls the actual S-SMP clock rate. 0 = 100%, 1 = 50%, 2 = 0%
(locks the S-SMP forever), 3 = 10%. Wild stuff, you can actually
permanently slow the S-SMP relative to the S-CPU.

d6-d5 is a timer tick control, but it actually uses d7-d4 overlaid.
The algorithm is fucking nuts, and is really my only contribution to
today's work. The rest was all blargg's research.

We had d2 wrong, it's not MMIO disable, it's RAM disable. As in,
disable read and write. Returns 0x5a on regular SNES, 0xff on mini-
SNES. 0x5a is not the S-SMP MDR. IPLROM is still readable when RAM is
disabled. d1 was correct, just RAM write disable. Can still write to
$f8 and $f9, of course. But it won't go through to RAM.

d3 and d0, we are still a little unsure on. The T0-T2 timers seem to
have a low and high phase, and if you strobe them you can force ticks
of stage 2 to happen, and you can disable them in such a manner than
stage 2 never ticks at all.

blargg is still uncovering all sorts of crazy things in $xB mode, so
emulation of these two bits is not perfect.

But overall we are leaps and bounds further now toward complete
emulation. I'd say we went from 10% to 80% with today's work. But
we'll have to see how deep the rabbit hole goes on d3+d0 first.

Current register map:

    case 0xf0: {  //TEST
    if(regs.p.p) break;  //writes only valid when P flag is clear

    status.clock_speed     = (data >> 6) & 3;  //100%, 50%, 0%, 10%
    status.timer_speed     = (data >> 4) & 3;  //100%, ...
    status.timers_enabled  = data & 0x08;
    status.ram_disabled    = data & 0x04;
    status.ram_writable    = data & 0x02;
    status.timers_disabled = data & 0x01;

    unsigned base = 1 + (1 << status.clock_speed);
    unsigned step = base + (15 >> (3 - status.timer_speed));
    status.timer_step = 1.0 / (3.0 / step);

    t0.sync_stage1();
    t1.sync_stage1();
    t2.sync_stage1();
    } break;


Fairly confident that no emulator prior to this WIP could pass any of
blargg's tests, so this is all brand new information. Fun stuff :)
2010-03-15 15:20:52 +00:00
149 changed files with 2119 additions and 2683 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
bsnes.exe

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -2,8 +2,8 @@
#define NALL_ANY_HPP
#include <typeinfo>
#include <type_traits>
#include <nall/static.hpp>
#include <nall/traits.hpp>
namespace nall {
class any {
@@ -13,8 +13,8 @@ namespace nall {
template<typename T> any& operator=(const T& value_) {
typedef typename static_if<
is_array<T>::value,
typename remove_extent<typename add_const<T>::type>::type*,
std::is_array<T>::value,
typename std::remove_extent<typename std::add_const<T>::type>::type*,
T
>::type auto_t;
@@ -49,13 +49,13 @@ namespace nall {
};
template<typename T> T any_cast(any &value) {
typedef typename remove_reference<T>::type nonref;
typedef typename std::remove_reference<T>::type nonref;
if(value.type() != typeid(nonref)) throw;
return static_cast<any::holder<nonref>*>(value.container)->value;
}
template<typename T> T any_cast(const any &value) {
typedef const typename remove_reference<T>::type nonref;
typedef const typename std::remove_reference<T>::type nonref;
if(value.type() != typeid(nonref)) throw;
return static_cast<any::holder<nonref>*>(value.container)->value;
}

View File

@@ -3,10 +3,11 @@
#include <stdlib.h>
#include <initializer_list>
#include <type_traits>
#include <utility>
#include <nall/algorithm.hpp>
#include <nall/bit.hpp>
#include <nall/concept.hpp>
#include <nall/traits.hpp>
namespace nall {
//dynamic vector array
@@ -81,7 +82,7 @@ namespace nall {
return *this;
}
array(const array &source) : pool(0) {
array(const array &source) : pool(0), poolsize(0), buffersize(0) {
operator=(source);
}
@@ -92,11 +93,12 @@ namespace nall {
poolsize = source.poolsize;
buffersize = source.buffersize;
source.pool = 0;
source.reset();
return *this;
}
array(array &&source) {
operator=(move(source));
array(array &&source) : pool(0), poolsize(0), buffersize(0) {
operator=(std::move(source));
}
//index

View File

@@ -6,9 +6,9 @@
for(unsigned foreach_counter = 0, foreach_limit = foreach_size(object), foreach_once = 0, foreach_broken = 0; foreach_counter < foreach_limit && foreach_broken == 0; foreach_counter++, foreach_once = 0) \
for(auto &iter = object[foreach_counter]; foreach_once == 0 && (foreach_broken = 1); foreach_once++, foreach_broken = 0)
#include <type_traits>
#include <nall/concept.hpp>
#include <nall/static.hpp>
#include <nall/traits.hpp>
namespace nall {
template<typename T> unsigned foreach_size(const T& object, typename mp_enable_if<has_count<T>>::type = 0) {
@@ -23,8 +23,8 @@ namespace nall {
return object.size();
}
template<typename T> unsigned foreach_size(const T& object, typename mp_enable_if<is_array<T>>::type = 0) {
return sizeof(T) / sizeof(typename remove_extent<T>::type);
template<typename T> unsigned foreach_size(const T& object, typename mp_enable_if<std::is_array<T>>::type = 0) {
return sizeof(T) / sizeof(typename std::remove_extent<T>::type);
}
}

View File

@@ -1,190 +1,102 @@
#ifndef NALL_FUNCTION_HPP
#define NALL_FUNCTION_HPP
#include <assert.h>
//prologue
#define TN typename
#include <functional>
#include <type_traits>
namespace nall {
template<typename T> class function;
}
//parameters = 0
#define cat(n) n
#define TL typename R
#define PL
#define CL
#include "function.hpp"
//parameters = 1
#define cat(n) , n
#define TL TN R, TN P1
#define PL P1 p1
#define CL p1
#include "function.hpp"
//parameters = 2
#define cat(n) , n
#define TL TN R, TN P1, TN P2
#define PL P1 p1, P2 p2
#define CL p1, p2
#include "function.hpp"
//parameters = 3
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3
#define PL P1 p1, P2 p2, P3 p3
#define CL p1, p2, p3
#include "function.hpp"
//parameters = 4
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4
#define PL P1 p1, P2 p2, P3 p3, P4 p4
#define CL p1, p2, p3, p4
#include "function.hpp"
//parameters = 5
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5
#define CL p1, p2, p3, p4, p5
#include "function.hpp"
//parameters = 6
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6
#define CL p1, p2, p3, p4, p5, p6
#include "function.hpp"
//parameters = 7
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6, TN P7
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7
#define CL p1, p2, p3, p4, p5, p6, p7
#include "function.hpp"
//parameters = 8
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6, TN P7, TN P8
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8
#define CL p1, p2, p3, p4, p5, p6, p7, p8
#include "function.hpp"
//epilogue
#undef TN
#define NALL_FUNCTION_T
#elif !defined(NALL_FUNCTION_T)
//function implementation template class
namespace nall {
template<TL>
class function<R (PL)> {
template<typename R, typename... P>
class function<R (P...)> {
private:
struct base1 { virtual void func1(PL) {} };
struct base2 { virtual void func2(PL) {} };
struct base1 { virtual void func1(P...) {} };
struct base2 { virtual void func2(P...) {} };
struct derived : base1, virtual base2 {};
struct data_t {
R (*fn_call)(const data_t& cat(PL));
R (*callback)(const data_t&, P...);
union {
R (*fn_global)(PL);
R (*callback_global)(P...);
struct {
R (derived::*fn_member)(PL);
R (derived::*callback_member)(P...);
void *object;
};
};
} data;
static R fn_call_global(const data_t &d cat(PL)) {
return d.fn_global(CL);
static R callback_global(const data_t &data, P... p) {
return data.callback_global(p...);
}
template<typename C>
static R fn_call_member(const data_t &d cat(PL)) {
return (((C*)d.object)->*((R (C::*&)(PL))d.fn_member))(CL);
static R callback_member(const data_t &data, P... p) {
return (((C*)data.object)->*((R (C::*&)(P...))data.callback_member))(p...);
}
public:
R operator()(PL) const { return data.fn_call(data cat(CL)); }
operator bool() const { return data.fn_call; }
R operator()(P... p) const { return data.callback(data, p...); }
operator bool() const { return data.callback; }
void reset() { data.callback = 0; }
function() { data.fn_call = 0; }
function(void *fn) {
data.fn_call = fn ? &fn_call_global : 0;
data.fn_global = (R (*)(PL))fn;
}
function(R (*fn)(PL)) {
data.fn_call = &fn_call_global;
data.fn_global = fn;
}
template<typename C>
function(R (C::*fn)(PL), C *obj) {
data.fn_call = &fn_call_member<C>;
(R (C::*&)(PL))data.fn_member = fn;
assert(sizeof data.fn_member >= sizeof fn);
data.object = obj;
}
template<typename C>
function(R (C::*fn)(PL) const, C *obj) {
data.fn_call = &fn_call_member<C>;
(R (C::*&)(PL))data.fn_member = (R (C::*&)(PL))fn;
assert(sizeof data.fn_member >= sizeof fn);
data.object = obj;
}
function& operator=(void *fn) { return operator=(function(fn)); }
function& operator=(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); return *this; }
function(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); }
function(const function &source) { operator=(source); }
//no pointer
function() {
data.callback = 0;
}
//symbolic link pointer (nall/dl.hpp::sym, etc)
function(void *callback) {
data.callback = callback ? &callback_global : 0;
data.callback_global = (R (*)(P...))callback;
}
//global function pointer
function(R (*callback)(P...)) {
data.callback = &callback_global;
data.callback_global = callback;
}
//member function pointer
template<typename C>
function(R (C::*callback)(P...), C *object) {
static_assert(sizeof data.callback_member >= sizeof callback, "callback_member is too small");
data.callback = &callback_member<C>;
(R (C::*&)(P...))data.callback_member = callback;
data.object = object;
}
//const member function pointer
template<typename C>
function(R (C::*callback)(P...) const, C *object) {
static_assert(sizeof data.callback_member >= sizeof callback, "callback_member is too small");
data.callback = &callback_member<C>;
(R (C::*&)(P...))data.callback_member = (R (C::*&)(P...))callback;
data.object = object;
}
//lambda function pointer
template<typename T>
function(T callback) {
static_assert(std::is_same<R, typename std::result_of<T(P...)>::type>::value, "lambda mismatch");
data.callback = &callback_global;
data.callback_global = (R (*)(P...))callback;
}
};
template<TL>
function<R (PL)> bind(R (*fn)(PL)) {
return function<R (PL)>(fn);
//bind functions to ease construction and assignment of function() with more than one argument
template<typename C, typename R, typename... P>
function<R (P...)> bind(R (C::*callback)(P...), C *object) {
return function<R (P...)>(callback, object);
}
template<typename C, TL>
function<R (PL)> bind(R (C::*fn)(PL), C *obj) {
return function<R (PL)>(fn, obj);
}
template<typename C, TL>
function<R (PL)> bind(R (C::*fn)(PL) const, C *obj) {
return function<R (PL)>(fn, obj);
template<typename C, typename R, typename... P>
function<R (P...)> bind(R (C::*callback)(P...) const, C *object) {
return function<R (P...)>(callback, object);
}
}
#undef cat
#undef TL
#undef PL
#undef CL
#endif

View File

@@ -1,8 +1,9 @@
#ifndef NALL_SERIALIZER_HPP
#define NALL_SERIALIZER_HPP
#include <type_traits>
#include <utility>
#include <nall/stdint.hpp>
#include <nall/traits.hpp>
#include <nall/utility.hpp>
namespace nall {
@@ -16,6 +17,7 @@ namespace nall {
//caveats:
//- only plain-old-data can be stored. complex classes must provide serialize(serializer&);
//- floating-point usage is not portable across platforms
class serializer {
public:
enum mode_t { Load, Save, Size };
@@ -51,7 +53,7 @@ namespace nall {
}
template<typename T> void integer(T &value) {
enum { size = is_bool<T>::value ? 1 : sizeof(T) };
enum { size = std::is_same<bool, T>::value ? 1 : sizeof(T) };
if(imode == Save) {
for(unsigned n = 0; n < size; n++) idata[isize++] = value >> (n << 3);
} else if(imode == Load) {
@@ -63,7 +65,7 @@ namespace nall {
}
template<typename T> void array(T &array) {
enum { size = sizeof(T) / sizeof(typename remove_extent<T>::type) };
enum { size = sizeof(T) / sizeof(typename std::remove_extent<T>::type) };
for(unsigned n = 0; n < size; n++) integer(array[n]);
}
@@ -102,7 +104,7 @@ namespace nall {
}
serializer(serializer &&s) {
operator=(move(s));
operator=(std::move(s));
}
//construction

View File

@@ -10,42 +10,13 @@
#include <nall/utf8.hpp>
#include <nall/vector.hpp>
inline char chrlower(char c);
inline char chrupper(char c);
inline int stricmp(const char *dest, const char *src);
inline int strpos (const char *str, const char *key);
inline int qstrpos(const char *str, const char *key);
inline bool strbegin (const char *str, const char *key);
inline bool stribegin(const char *str, const char *key);
inline bool strend (const char *str, const char *key);
inline bool striend(const char *str, const char *key);
inline char* strlower(char *str);
inline char* strupper(char *str);
inline char* strtr(char *dest, const char *before, const char *after);
inline uintmax_t strhex (const char *str);
inline intmax_t strsigned (const char *str);
inline uintmax_t strunsigned(const char *str);
inline uintmax_t strbin (const char *str);
inline double strdouble (const char *str);
inline bool match(const char *pattern, const char *str);
inline bool strint (const char *str, int &result);
inline bool strmath(const char *str, int &result);
inline size_t strlcpy(char *dest, const char *src, size_t length);
inline size_t strlcat(char *dest, const char *src, size_t length);
inline char* ltrim(char *str, const char *key = " ");
inline char* rtrim(char *str, const char *key = " ");
inline char* trim (char *str, const char *key = " ");
inline char* ltrim_once(char *str, const char *key = " ");
inline char* rtrim_once(char *str, const char *key = " ");
inline char* trim_once (char *str, const char *key = " ");
namespace nall {
class string;
template<typename T> inline string to_string(T);
class string {
public:
inline void reserve(size_t);
inline void reserve(unsigned);
inline unsigned length() const;
inline string& assign(const char*);
@@ -78,7 +49,7 @@ namespace nall {
protected:
char *data;
size_t size;
unsigned size;
#if defined(QT_CORE_LIB)
public:
@@ -98,29 +69,69 @@ namespace nall {
lstring(std::initializer_list<string>);
};
template<typename... Args> inline string sprint(const char *s, Args... args);
template<typename... Args> inline void print(const char *s, Args... args);
//compare.hpp
inline char chrlower(char c);
inline char chrupper(char c);
inline int stricmp(const char *dest, const char *src);
inline int strpos (const char *str, const char *key);
inline int qstrpos(const char *str, const char *key);
inline bool strbegin (const char *str, const char *key);
inline bool stribegin(const char *str, const char *key);
inline bool strend (const char *str, const char *key);
inline bool striend(const char *str, const char *key);
//convert.hpp
inline char* strlower(char *str);
inline char* strupper(char *str);
inline char* strtr(char *dest, const char *before, const char *after);
inline uintmax_t strhex (const char *str);
inline intmax_t strsigned (const char *str);
inline uintmax_t strunsigned(const char *str);
inline uintmax_t strbin (const char *str);
inline double strdouble (const char *str);
//match.hpp
inline bool match(const char *pattern, const char *str);
//math.hpp
inline bool strint (const char *str, int &result);
inline bool strmath(const char *str, int &result);
//strl.hpp
inline unsigned strlcpy(char *dest, const char *src, unsigned length);
inline unsigned strlcat(char *dest, const char *src, unsigned length);
//trim.hpp
inline char* ltrim(char *str, const char *key = " ");
inline char* rtrim(char *str, const char *key = " ");
inline char* trim (char *str, const char *key = " ");
inline char* ltrim_once(char *str, const char *key = " ");
inline char* rtrim_once(char *str, const char *key = " ");
inline char* trim_once (char *str, const char *key = " ");
//utility.hpp
inline unsigned strlcpy(string &dest, const char *src, unsigned length);
inline unsigned strlcat(string &dest, const char *src, unsigned length);
inline string substr(const char *src, unsigned start = 0, unsigned length = 0);
inline string& strlower(string &str);
inline string& strupper(string &str);
inline string& strtr(string &dest, const char *before, const char *after);
inline string& ltrim(string &str, const char *key = " ");
inline string& rtrim(string &str, const char *key = " ");
inline string& trim (string &str, const char *key = " ");
inline string& ltrim_once(string &str, const char *key = " ");
inline string& rtrim_once(string &str, const char *key = " ");
inline string& trim_once (string &str, const char *key = " ");
template<unsigned length = 0, char padding = '0'> inline string strhex(uintmax_t value);
template<unsigned length = 0, char padding = '0'> inline string strsigned(intmax_t value);
template<unsigned length = 0, char padding = '0'> inline string strunsigned(uintmax_t value);
template<unsigned length = 0, char padding = '0'> inline string strbin(uintmax_t value);
inline unsigned strdouble(char *str, double value);
inline string strdouble(double value);
//variadic.hpp
template<typename... Args> inline string sprint(Args... args);
template<typename... Args> inline void print(Args... args);
};
inline size_t strlcpy(nall::string &dest, const char *src, size_t length);
inline size_t strlcat(nall::string &dest, const char *src, size_t length);
inline nall::string& strlower(nall::string &str);
inline nall::string& strupper(nall::string &str);
inline nall::string& strtr(nall::string &dest, const char *before, const char *after);
inline nall::string& ltrim(nall::string &str, const char *key = " ");
inline nall::string& rtrim(nall::string &str, const char *key = " ");
inline nall::string& trim (nall::string &str, const char *key = " ");
inline nall::string& ltrim_once(nall::string &str, const char *key = " ");
inline nall::string& rtrim_once(nall::string &str, const char *key = " ");
inline nall::string& trim_once (nall::string &str, const char *key = " ");
inline nall::string substr(const char *src, size_t start = 0, size_t length = 0);
template<unsigned length = 0, char padding = '0'> inline nall::string strhex(uintmax_t value);
template<unsigned length = 0, char padding = '0'> inline nall::string strsigned(intmax_t value);
template<unsigned length = 0, char padding = '0'> inline nall::string strunsigned(uintmax_t value);
template<unsigned length = 0, char padding = '0'> inline nall::string strbin(uintmax_t value);
inline size_t strdouble(char *str, double value);
inline nall::string strdouble(double value);
#endif

View File

@@ -2,28 +2,31 @@
#define NALL_STRING_CAST_HPP
namespace nall {
//this is needed, as C++0x does not support explicit template specialization inside classes
template<> inline string to_string<bool> (bool v) { return v ? "true" : "false"; }
template<> inline string to_string<signed int> (signed int v) { return strsigned(v); }
template<> inline string to_string<unsigned int> (unsigned int v) { return strunsigned(v); }
template<> inline string to_string<double> (double v) { return strdouble(v); }
template<> inline string to_string<char*> (char *v) { return v; }
template<> inline string to_string<const char*> (const char *v) { return v; }
template<> inline string to_string<string> (string v) { return v; }
template<> inline string to_string<const string&>(const string &v) { return v; }
template<typename T> string& string::operator= (T value) { return assign(to_string<T>(value)); }
template<typename T> string& string::operator<<(T value) { return append(to_string<T>(value)); }
//this is needed, as C++0x does not support explicit template specialization inside classes
template<> inline string to_string<bool> (bool v) { return v ? "true" : "false"; }
template<> inline string to_string<signed int> (signed int v) { return strsigned(v); }
template<> inline string to_string<unsigned int> (unsigned int v) { return strunsigned(v); }
template<> inline string to_string<double> (double v) { return strdouble(v); }
template<> inline string to_string<char*> (char *v) { return v; }
template<> inline string to_string<const char*> (const char *v) { return v; }
template<> inline string to_string<string> (string v) { return v; }
template<> inline string to_string<const string&>(const string &v) { return v; }
template<typename T> lstring& lstring::operator<<(T value) {
operator[](size()).assign(to_string<T>(value));
return *this;
}
template<typename T> string& string::operator= (T value) { return assign(to_string<T>(value)); }
template<typename T> string& string::operator<<(T value) { return append(to_string<T>(value)); }
template<typename T> lstring& lstring::operator<<(T value) {
operator[](size()).assign(to_string<T>(value));
return *this;
}
#if defined(QT_CORE_LIB)
template<> inline string to_string<QString>(QString v) { return v.toUtf8().constData(); }
template<> inline string to_string<const QString&>(const QString &v) { return v.toUtf8().constData(); }
string::operator QString() const { return QString::fromUtf8(*this); }
#endif
#if defined(QT_CORE_LIB)
template<> inline string to_string<const QString&>(const QString &v) { return v.toUtf8().constData(); }
string::operator QString() const { return QString::fromUtf8(*this); }
#endif
}
#endif

View File

@@ -1,6 +1,8 @@
#ifndef NALL_STRING_COMPARE_HPP
#define NALL_STRING_COMPARE_HPP
namespace nall {
char chrlower(char c) {
return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c;
}
@@ -97,4 +99,6 @@ bool striend(const char *str, const char *key) {
return true;
}
}
#endif

View File

@@ -1,6 +1,8 @@
#ifndef NALL_STRING_CONVERT_HPP
#define NALL_STRING_CONVERT_HPP
namespace nall {
char* strlower(char *str) {
if(!str) return 0;
int i = 0;
@@ -146,4 +148,6 @@ double strdouble(const char *str) {
return !negate ? result : -result;
}
}
#endif

View File

@@ -3,7 +3,7 @@
namespace nall {
void string::reserve(size_t size_) {
void string::reserve(unsigned size_) {
if(size_ > size) {
size = size_;
data = (char*)realloc(data, size + 1);
@@ -81,6 +81,7 @@ string& string::operator=(string &&source) {
size = source.size;
data = source.data;
source.data = 0;
source.size = 0;
return *this;
}
@@ -94,12 +95,12 @@ bool string::readfile(const char *filename) {
#if !defined(_WIN32)
FILE *fp = fopen(filename, "rb");
#else
FILE *fp = _wfopen(nall::utf16_t(filename), L"rb");
FILE *fp = _wfopen(utf16_t(filename), L"rb");
#endif
if(!fp) return false;
fseek(fp, 0, SEEK_END);
size_t size = ftell(fp);
unsigned size = ftell(fp);
rewind(fp);
char *fdata = new char[size + 1];
unsigned unused = fread(fdata, 1, size, fp);

View File

@@ -2,59 +2,60 @@
#define NALL_FILENAME_HPP
namespace nall {
// "foo/bar.c" -> "foo/", "bar.c" -> "./"
inline string dir(char const *name) {
string result = name;
for(signed i = strlen(result); i >= 0; i--) {
if(result[i] == '/' || result[i] == '\\') {
result[i + 1] = 0;
break;
}
if(i == 0) result = "./";
}
return result;
}
// "foo/bar.c" -> "bar.c"
inline string notdir(char const *name) {
for(signed i = strlen(name); i >= 0; i--) {
if(name[i] == '/' || name[i] == '\\') {
name += i + 1;
break;
}
// "foo/bar.c" -> "foo/", "bar.c" -> "./"
inline string dir(char const *name) {
string result = name;
for(signed i = strlen(result); i >= 0; i--) {
if(result[i] == '/' || result[i] == '\\') {
result[i + 1] = 0;
break;
}
string result = name;
return result;
if(i == 0) result = "./";
}
return result;
}
// "foo/bar.c" -> "foo/bar"
inline string basename(char const *name) {
string result = name;
for(signed i = strlen(result); i >= 0; i--) {
if(result[i] == '/' || result[i] == '\\') {
//file has no extension
break;
}
if(result[i] == '.') {
result[i] = 0;
break;
}
// "foo/bar.c" -> "bar.c"
inline string notdir(char const *name) {
for(signed i = strlen(name); i >= 0; i--) {
if(name[i] == '/' || name[i] == '\\') {
name += i + 1;
break;
}
return result;
}
string result = name;
return result;
}
// "foo/bar.c" -> "c"
inline string extension(char const *name) {
for(signed i = strlen(name); i >= 0; i--) {
if(name[i] == '.') {
name += i + 1;
break;
}
// "foo/bar.c" -> "foo/bar"
inline string basename(char const *name) {
string result = name;
for(signed i = strlen(result); i >= 0; i--) {
if(result[i] == '/' || result[i] == '\\') {
//file has no extension
break;
}
if(result[i] == '.') {
result[i] = 0;
break;
}
string result = name;
return result;
}
return result;
}
// "foo/bar.c" -> "c"
inline string extension(char const *name) {
for(signed i = strlen(name); i >= 0; i--) {
if(name[i] == '.') {
name += i + 1;
break;
}
}
string result = name;
return result;
}
}
#endif

View File

@@ -1,6 +1,8 @@
#ifndef NALL_STRING_MATCH_HPP
#define NALL_STRING_MATCH_HPP
namespace nall {
bool match(const char *p, const char *s) {
const char *p_ = 0, *s_ = 0;
@@ -69,4 +71,6 @@ bool match(const char *p, const char *s) {
}
}
}
#endif

View File

@@ -1,6 +1,8 @@
#ifndef NALL_STRING_MATH_HPP
#define NALL_STRING_MATH_HPP
namespace nall {
static int eval_integer(const char *&s) {
if(!*s) throw "unrecognized_integer";
int value = 0, x = *s, y = *(s + 1);
@@ -157,4 +159,6 @@ bool strmath(const char *s, int &result) {
}
}
}
#endif

View File

@@ -1,13 +1,15 @@
#ifndef NALL_STRING_STRL_HPP
#define NALL_STRING_STRL_HPP
namespace nall {
//strlcpy, strlcat based on OpenBSD implementation by Todd C. Miller
//return = strlen(src)
size_t strlcpy(char *dest, const char *src, size_t length) {
unsigned strlcpy(char *dest, const char *src, unsigned length) {
char *d = dest;
const char *s = src;
size_t n = length;
unsigned n = length;
if(n) {
while(--n && (*d++ = *s++)); //copy as many bytes as possible, or until null terminator reached
@@ -22,13 +24,13 @@ size_t strlcpy(char *dest, const char *src, size_t length) {
}
//return = strlen(src) + min(length, strlen(dest))
size_t strlcat(char *dest, const char *src, size_t length) {
unsigned strlcat(char *dest, const char *src, unsigned length) {
char *d = dest;
const char *s = src;
size_t n = length;
unsigned n = length;
while(n-- && *d) d++; //find end of dest
size_t dlength = d - dest;
unsigned dlength = d - dest;
n = length - dlength; //subtract length of dest from maximum string length
if(!n) return dlength + strlen(s);
@@ -45,4 +47,6 @@ size_t strlcat(char *dest, const char *src, size_t length) {
return dlength + (s - src); //return length of resulting string, sans null terminator
}
}
#endif

View File

@@ -1,6 +1,8 @@
#ifndef NALL_STRING_TRIM_HPP
#define NALL_STRING_TRIM_HPP
namespace nall {
char* ltrim(char *str, const char *key) {
if(!key || !*key) return str;
while(strbegin(str, key)) {
@@ -47,4 +49,6 @@ char* trim_once(char *str, const char *key) {
return ltrim_once(rtrim_once(str, key), key);
}
}
#endif

View File

@@ -1,18 +1,20 @@
#ifndef NALL_STRING_UTILITY_HPP
#define NALL_STRING_UTILITY_HPP
size_t strlcpy(nall::string &dest, const char *src, size_t length) {
namespace nall {
unsigned strlcpy(string &dest, const char *src, unsigned length) {
dest.reserve(length);
return strlcpy(dest(), src, length);
}
size_t strlcat(nall::string &dest, const char *src, size_t length) {
unsigned strlcat(string &dest, const char *src, unsigned length) {
dest.reserve(length);
return strlcat(dest(), src, length);
}
nall::string substr(const char *src, size_t start, size_t length) {
nall::string dest;
string substr(const char *src, unsigned start, unsigned length) {
string dest;
if(length == 0) {
//copy entire string
dest = src + start;
@@ -23,22 +25,22 @@ nall::string substr(const char *src, size_t start, size_t length) {
return dest;
}
/* very simplistic wrappers to return nall::string& instead of char* type */
/* very simplistic wrappers to return string& instead of char* type */
nall::string& strlower(nall::string &str) { strlower(str()); return str; }
nall::string& strupper(nall::string &str) { strupper(str()); return str; }
nall::string& strtr(nall::string &dest, const char *before, const char *after) { strtr(dest(), before, after); return dest; }
nall::string& ltrim(nall::string &str, const char *key) { ltrim(str(), key); return str; }
nall::string& rtrim(nall::string &str, const char *key) { rtrim(str(), key); return str; }
nall::string& trim (nall::string &str, const char *key) { trim (str(), key); return str; }
nall::string& ltrim_once(nall::string &str, const char *key) { ltrim_once(str(), key); return str; }
nall::string& rtrim_once(nall::string &str, const char *key) { rtrim_once(str(), key); return str; }
nall::string& trim_once (nall::string &str, const char *key) { trim_once (str(), key); return str; }
string& strlower(string &str) { strlower(str()); return str; }
string& strupper(string &str) { strupper(str()); return str; }
string& strtr(string &dest, const char *before, const char *after) { strtr(dest(), before, after); return dest; }
string& ltrim(string &str, const char *key) { ltrim(str(), key); return str; }
string& rtrim(string &str, const char *key) { rtrim(str(), key); return str; }
string& trim (string &str, const char *key) { trim (str(), key); return str; }
string& ltrim_once(string &str, const char *key) { ltrim_once(str(), key); return str; }
string& rtrim_once(string &str, const char *key) { rtrim_once(str(), key); return str; }
string& trim_once (string &str, const char *key) { trim_once (str(), key); return str; }
/* arithmetic <> string */
template<unsigned length, char padding> nall::string strhex(uintmax_t value) {
nall::string output;
template<unsigned length, char padding> string strhex(uintmax_t value) {
string output;
unsigned offset = 0;
//render string backwards, as we do not know its length yet
@@ -61,8 +63,8 @@ template<unsigned length, char padding> nall::string strhex(uintmax_t value) {
return output;
}
template<unsigned length, char padding> nall::string strsigned(intmax_t value) {
nall::string output;
template<unsigned length, char padding> string strsigned(intmax_t value) {
string output;
unsigned offset = 0;
bool negative = value < 0;
@@ -87,8 +89,8 @@ template<unsigned length, char padding> nall::string strsigned(intmax_t value) {
return output;
}
template<unsigned length, char padding> nall::string strunsigned(uintmax_t value) {
nall::string output;
template<unsigned length, char padding> string strunsigned(uintmax_t value) {
string output;
unsigned offset = 0;
do {
@@ -109,8 +111,8 @@ template<unsigned length, char padding> nall::string strunsigned(uintmax_t value
return output;
}
template<unsigned length, char padding> nall::string strbin(uintmax_t value) {
nall::string output;
template<unsigned length, char padding> string strbin(uintmax_t value) {
string output;
unsigned offset = 0;
do {
@@ -134,7 +136,7 @@ template<unsigned length, char padding> nall::string strbin(uintmax_t value) {
//using sprintf is certainly not the most ideal method to convert
//a double to a string ... but attempting to parse a double by
//hand, digit-by-digit, results in subtle rounding errors.
size_t strdouble(char *str, double value) {
unsigned strdouble(char *str, double value) {
char buffer[256];
sprintf(buffer, "%f", value);
@@ -155,11 +157,13 @@ size_t strdouble(char *str, double value) {
return length + 1;
}
nall::string strdouble(double value) {
nall::string temp;
string strdouble(double value) {
string temp;
temp.reserve(strdouble(0, value));
strdouble(temp(), value);
return temp;
}
}
#endif

View File

@@ -2,36 +2,26 @@
#define NALL_STRING_VARIADIC_HPP
namespace nall {
static void sprint(string &output, unsigned &offset, const char *&s) {
while(*s) output[offset++] = *s++;
}
template<typename T, typename... Args>
static void sprint(string &output, unsigned &offset, const char *&s, T value, Args... args) {
while(*s) {
if(*s == '$') {
string data = to_string<T>(value);
unsigned i = 0;
while(data[i]) output[offset++] = data[i++];
sprint(output, offset, ++s, args...);
return;
} else {
output[offset++] = *s++;
}
}
}
static void isprint(string &output) {
}
template<typename... Args> inline string sprint(const char *s, Args... args) {
string output;
unsigned offset = 0;
sprint(output, offset, s, args...);
output[offset] = 0;
return output;
}
template<typename T, typename... Args>
static void isprint(string &output, T value, Args... args) {
output << to_string<T>(value);
isprint(output, args...);
}
template<typename... Args> inline string sprint(Args... args) {
string output;
isprint(output, args...);
return output;
}
template<typename... Args> inline void print(Args... args) {
printf("%s", (const char*)sprint(args...));
}
template<typename... Args> inline void print(const char *s, Args... args) {
printf("%s", (const char*)sprint(s, args...));
}
}
#endif

View File

@@ -2,9 +2,7 @@
#define NALL_STRING_XML_HPP
//XML subset parser
//version 0.04
#include <nall/array.hpp>
//version 0.05
namespace nall {
@@ -16,15 +14,14 @@ struct xml_attribute {
struct xml_element : xml_attribute {
string parse() const;
array<xml_attribute*> attribute;
array<xml_element*> element;
~xml_element();
linear_vector<xml_attribute> attribute;
linear_vector<xml_element> element;
protected:
void parse_doctype(const char *&data);
bool parse_head(string data);
bool parse_body(const char *&data);
friend xml_element *xml_parse(const char *data);
friend xml_element xml_parse(const char *data);
};
inline string xml_attribute::parse() const {
@@ -134,11 +131,11 @@ inline bool xml_element::parse_head(string data) {
side.qsplit("=", part[i]);
if(side.size() != 2) throw "...";
xml_attribute *attr = new xml_attribute;
attr->name = side[0];
attr->content = side[1];
if(strbegin(attr->content, "\"") && strend(attr->content, "\"")) trim_once(attr->content, "\"");
else if(strbegin(attr->content, "'") && strend(attr->content, "'")) trim_once(attr->content, "'");
xml_attribute attr;
attr.name = side[0];
attr.content = side[1];
if(strbegin(attr.content, "\"") && strend(attr.content, "\"")) trim_once(attr.content, "\"");
else if(strbegin(attr.content, "'") && strend(attr.content, "'")) trim_once(attr.content, "'");
else throw "...";
attribute.add(attr);
}
@@ -191,10 +188,8 @@ inline bool xml_element::parse_body(const char *&data) {
while(*data) {
unsigned index = element.size();
xml_element *elem = new xml_element;
if(elem->parse_body(data) == false) {
delete elem;
xml_element node;
if(node.parse_body(data) == false) {
if(*data == '/') {
signed length = data - content_begin - 1;
if(length > 0) content = substr(content_begin, 0, length);
@@ -216,23 +211,18 @@ inline bool xml_element::parse_body(const char *&data) {
return true;
}
} else {
element.add(elem);
element.add(node);
}
}
}
}
inline xml_element::~xml_element() {
for(unsigned i = 0; i < attribute.size(); i++) delete attribute[i];
for(unsigned i = 0; i < element.size(); i++) delete element[i];
}
//ensure there is only one root element
inline bool xml_validate(xml_element *document) {
inline bool xml_validate(xml_element &document) {
unsigned root_counter = 0;
for(unsigned i = 0; i < document->element.size(); i++) {
string &name = document->element[i]->name;
for(unsigned i = 0; i < document.element.size(); i++) {
string &name = document.element[i].name;
if(strbegin(name, "?")) continue;
if(strbegin(name, "!")) continue;
if(++root_counter > 1) return false;
@@ -241,25 +231,24 @@ inline bool xml_validate(xml_element *document) {
return true;
}
inline xml_element* xml_parse(const char *data) {
xml_element *self = new xml_element;
inline xml_element xml_parse(const char *data) {
xml_element self;
try {
while(*data) {
xml_element *elem = new xml_element;
if(elem->parse_body(data) == false) {
delete elem;
xml_element node;
if(node.parse_body(data) == false) {
break;
} else {
self->element.add(elem);
self.element.add(node);
}
}
if(xml_validate(self) == false) throw "...";
return self;
} catch(const char*) {
delete self;
return 0;
xml_element empty;
return empty;
}
}

View File

@@ -1,97 +0,0 @@
#ifndef NALL_TRAITS_HPP
#define NALL_TRAITS_HPP
namespace nall {
//==
//is
//==
template<typename T> struct is_integral { enum { value = false }; };
template<> struct is_integral<bool> { enum { value = true }; };
template<> struct is_integral<char> { enum { value = true }; };
template<> struct is_integral<signed char> { enum { value = true }; };
template<> struct is_integral<unsigned char> { enum { value = true }; };
template<> struct is_integral<wchar_t> { enum { value = true }; };
template<> struct is_integral<short> { enum { value = true }; };
template<> struct is_integral<unsigned short> { enum { value = true }; };
template<> struct is_integral<long> { enum { value = true }; };
template<> struct is_integral<unsigned long> { enum { value = true }; };
template<> struct is_integral<long long> { enum { value = true }; };
template<> struct is_integral<unsigned long long> { enum { value = true }; };
template<> struct is_integral<int> { enum { value = true }; };
template<> struct is_integral<unsigned int> { enum { value = true }; };
template<typename T> struct is_floating_point { enum { value = false }; };
template<> struct is_floating_point<float> { enum { value = true }; };
template<> struct is_floating_point<double> { enum { value = true }; };
template<> struct is_floating_point<long double> { enum { value = true }; };
template<typename T> struct is_bool { enum { value = false }; };
template<> struct is_bool<bool> { enum { value = true }; };
template<typename T> struct is_void { enum { value = false }; };
template<> struct is_void<void> { enum { value = true }; };
template<typename T> struct is_arithmetic {
enum { value = is_integral<T>::value || is_floating_point<T>::value };
};
template<typename T> struct is_fundamental {
enum { value = is_integral<T>::value || is_floating_point<T>::value || is_void<T>::value };
};
template<typename T> struct is_compound {
enum { value = !is_fundamental<T>::value };
};
template<typename T> struct is_array { enum { value = false }; };
template<typename T> struct is_array<T[]> { enum { value = true }; };
template<typename T, int N> struct is_array<T[N]> { enum { value = true }; };
template<typename T> struct is_const { enum { value = false }; };
template<typename T> struct is_const<const T> { enum { value = true }; };
template<typename T> struct is_const<const T&> { enum { value = true }; };
template<typename T> struct is_pointer { enum { value = false }; };
template<typename T> struct is_pointer<T*> { enum { value = true }; };
template<typename T> struct is_reference { enum { value = false }; };
template<typename T> struct is_reference<T&> { enum { value = true }; };
template<typename T, typename U> struct is_same { enum { value = false }; };
template<typename T> struct is_same<T, T> { enum { value = true }; };
//===
//add
//===
template<typename T> struct add_const { typedef const T type; };
template<typename T> struct add_const<const T> { typedef const T type; };
template<typename T> struct add_const<const T&> { typedef const T& type; };
template<typename T> struct add_pointer { typedef T* type; };
template<typename T> struct add_pointer<T*> { typedef T** type; };
template<typename T> struct add_reference { typedef T& type; };
template<typename T> struct add_reference<T&> { typedef T& type; };
//======
//remove
//======
template<typename T> struct remove_const { typedef T type; };
template<typename T> struct remove_const<const T> { typedef T type; };
template<typename T> struct remove_const<const T&> { typedef T type; };
template<typename T> struct remove_extent { typedef T type; };
template<typename T> struct remove_extent<T[]> { typedef T type; };
template<typename T, int N> struct remove_extent<T[N]> { typedef T type; };
template<typename T> struct remove_pointer { typedef T type; };
template<typename T> struct remove_pointer<T*> { typedef T type; };
template<typename T> struct remove_reference { typedef T type; };
template<typename T> struct remove_reference<T&> { typedef T type; };
}
#endif

View File

@@ -1,29 +1,18 @@
#ifndef NALL_UTILITY_HPP
#define NALL_UTILITY_HPP
#include <nall/traits.hpp>
#include <type_traits>
#include <utility>
namespace nall {
template<typename T> struct identity {
typedef T type;
};
template<typename T> typename remove_reference<T>::type&& move(T &&value) {
return value;
}
template<typename T> T&& forward(typename identity<T>::type &&value) {
return value;
}
template<bool C, typename T = bool> struct enable_if { typedef T type; };
template<typename T> struct enable_if<false, T> {};
template<typename C, typename T = bool> struct mp_enable_if : enable_if<C::value, T> {};
template<typename T> inline void swap(T &x, T &y) {
T temp(move(x));
x = move(y);
y = move(temp);
T temp(std::move(x));
x = std::move(y);
y = std::move(temp);
}
template<typename T> struct base_from_member {

View File

@@ -3,10 +3,11 @@
#include <initializer_list>
#include <new>
#include <type_traits>
#include <utility>
#include <nall/algorithm.hpp>
#include <nall/bit.hpp>
#include <nall/concept.hpp>
#include <nall/traits.hpp>
#include <nall/utility.hpp>
namespace nall {
@@ -86,11 +87,12 @@ namespace nall {
inline linear_vector<T>& operator=(const linear_vector<T> &source) {
reset();
reserve(source.capacity());
for(unsigned i = 0; i < source.size(); i++) add(source[i]);
resize(source.size());
for(unsigned i = 0; i < source.size(); i++) operator[](i) = source.operator[](i);
return *this;
}
linear_vector(const linear_vector<T> &source) {
linear_vector(const linear_vector<T> &source) : pool(0), poolsize(0), objectsize(0) {
operator=(source);
}
@@ -101,11 +103,12 @@ namespace nall {
poolsize = source.poolsize;
objectsize = source.objectsize;
source.pool = 0;
source.reset();
return *this;
}
linear_vector(linear_vector<T> &&source) {
operator=(move(source));
linear_vector(linear_vector<T> &&source) : pool(0), poolsize(0), objectsize(0) {
operator=(std::move(source));
}
//construction
@@ -193,11 +196,12 @@ namespace nall {
inline pointer_vector<T>& operator=(const pointer_vector<T> &source) {
reset();
reserve(source.capacity());
for(unsigned i = 0; i < source.size(); i++) add(source[i]);
resize(source.size());
for(unsigned i = 0; i < source.size(); i++) operator[](i) = source.operator[](i);
return *this;
}
pointer_vector(const pointer_vector<T> &source) {
pointer_vector(const pointer_vector<T> &source) : pool(0), poolsize(0), objectsize(0) {
operator=(source);
}
@@ -208,11 +212,12 @@ namespace nall {
poolsize = source.poolsize;
objectsize = source.objectsize;
source.pool = 0;
source.reset();
return *this;
}
pointer_vector(pointer_vector<T> &&source) {
operator=(move(source));
pointer_vector(pointer_vector<T> &&source) : pool(0), poolsize(0), objectsize(0) {
operator=(std::move(source));
}
//construction

Binary file not shown.

View File

@@ -59,7 +59,6 @@ $(foreach f,$(moc_objects), \
$(eval $f: $(__file)) \
)
##################
### snesreader ###
##################

View File

@@ -2,8 +2,8 @@
#define NALL_ANY_HPP
#include <typeinfo>
#include <type_traits>
#include <nall/static.hpp>
#include <nall/traits.hpp>
namespace nall {
class any {
@@ -13,8 +13,8 @@ namespace nall {
template<typename T> any& operator=(const T& value_) {
typedef typename static_if<
is_array<T>::value,
typename remove_extent<typename add_const<T>::type>::type*,
std::is_array<T>::value,
typename std::remove_extent<typename std::add_const<T>::type>::type*,
T
>::type auto_t;
@@ -49,13 +49,13 @@ namespace nall {
};
template<typename T> T any_cast(any &value) {
typedef typename remove_reference<T>::type nonref;
typedef typename std::remove_reference<T>::type nonref;
if(value.type() != typeid(nonref)) throw;
return static_cast<any::holder<nonref>*>(value.container)->value;
}
template<typename T> T any_cast(const any &value) {
typedef const typename remove_reference<T>::type nonref;
typedef const typename std::remove_reference<T>::type nonref;
if(value.type() != typeid(nonref)) throw;
return static_cast<any::holder<nonref>*>(value.container)->value;
}

View File

@@ -3,10 +3,11 @@
#include <stdlib.h>
#include <initializer_list>
#include <type_traits>
#include <utility>
#include <nall/algorithm.hpp>
#include <nall/bit.hpp>
#include <nall/concept.hpp>
#include <nall/traits.hpp>
namespace nall {
//dynamic vector array
@@ -81,7 +82,7 @@ namespace nall {
return *this;
}
array(const array &source) : pool(0) {
array(const array &source) : pool(0), poolsize(0), buffersize(0) {
operator=(source);
}
@@ -92,11 +93,12 @@ namespace nall {
poolsize = source.poolsize;
buffersize = source.buffersize;
source.pool = 0;
source.reset();
return *this;
}
array(array &&source) {
operator=(move(source));
array(array &&source) : pool(0), poolsize(0), buffersize(0) {
operator=(std::move(source));
}
//index

View File

@@ -6,9 +6,9 @@
for(unsigned foreach_counter = 0, foreach_limit = foreach_size(object), foreach_once = 0, foreach_broken = 0; foreach_counter < foreach_limit && foreach_broken == 0; foreach_counter++, foreach_once = 0) \
for(auto &iter = object[foreach_counter]; foreach_once == 0 && (foreach_broken = 1); foreach_once++, foreach_broken = 0)
#include <type_traits>
#include <nall/concept.hpp>
#include <nall/static.hpp>
#include <nall/traits.hpp>
namespace nall {
template<typename T> unsigned foreach_size(const T& object, typename mp_enable_if<has_count<T>>::type = 0) {
@@ -23,8 +23,8 @@ namespace nall {
return object.size();
}
template<typename T> unsigned foreach_size(const T& object, typename mp_enable_if<is_array<T>>::type = 0) {
return sizeof(T) / sizeof(typename remove_extent<T>::type);
template<typename T> unsigned foreach_size(const T& object, typename mp_enable_if<std::is_array<T>>::type = 0) {
return sizeof(T) / sizeof(typename std::remove_extent<T>::type);
}
}

View File

@@ -1,190 +1,102 @@
#ifndef NALL_FUNCTION_HPP
#define NALL_FUNCTION_HPP
#include <assert.h>
//prologue
#define TN typename
#include <functional>
#include <type_traits>
namespace nall {
template<typename T> class function;
}
//parameters = 0
#define cat(n) n
#define TL typename R
#define PL
#define CL
#include "function.hpp"
//parameters = 1
#define cat(n) , n
#define TL TN R, TN P1
#define PL P1 p1
#define CL p1
#include "function.hpp"
//parameters = 2
#define cat(n) , n
#define TL TN R, TN P1, TN P2
#define PL P1 p1, P2 p2
#define CL p1, p2
#include "function.hpp"
//parameters = 3
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3
#define PL P1 p1, P2 p2, P3 p3
#define CL p1, p2, p3
#include "function.hpp"
//parameters = 4
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4
#define PL P1 p1, P2 p2, P3 p3, P4 p4
#define CL p1, p2, p3, p4
#include "function.hpp"
//parameters = 5
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5
#define CL p1, p2, p3, p4, p5
#include "function.hpp"
//parameters = 6
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6
#define CL p1, p2, p3, p4, p5, p6
#include "function.hpp"
//parameters = 7
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6, TN P7
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7
#define CL p1, p2, p3, p4, p5, p6, p7
#include "function.hpp"
//parameters = 8
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6, TN P7, TN P8
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8
#define CL p1, p2, p3, p4, p5, p6, p7, p8
#include "function.hpp"
//epilogue
#undef TN
#define NALL_FUNCTION_T
#elif !defined(NALL_FUNCTION_T)
//function implementation template class
namespace nall {
template<TL>
class function<R (PL)> {
template<typename R, typename... P>
class function<R (P...)> {
private:
struct base1 { virtual void func1(PL) {} };
struct base2 { virtual void func2(PL) {} };
struct base1 { virtual void func1(P...) {} };
struct base2 { virtual void func2(P...) {} };
struct derived : base1, virtual base2 {};
struct data_t {
R (*fn_call)(const data_t& cat(PL));
R (*callback)(const data_t&, P...);
union {
R (*fn_global)(PL);
R (*callback_global)(P...);
struct {
R (derived::*fn_member)(PL);
R (derived::*callback_member)(P...);
void *object;
};
};
} data;
static R fn_call_global(const data_t &d cat(PL)) {
return d.fn_global(CL);
static R callback_global(const data_t &data, P... p) {
return data.callback_global(p...);
}
template<typename C>
static R fn_call_member(const data_t &d cat(PL)) {
return (((C*)d.object)->*((R (C::*&)(PL))d.fn_member))(CL);
static R callback_member(const data_t &data, P... p) {
return (((C*)data.object)->*((R (C::*&)(P...))data.callback_member))(p...);
}
public:
R operator()(PL) const { return data.fn_call(data cat(CL)); }
operator bool() const { return data.fn_call; }
R operator()(P... p) const { return data.callback(data, p...); }
operator bool() const { return data.callback; }
void reset() { data.callback = 0; }
function() { data.fn_call = 0; }
function(void *fn) {
data.fn_call = fn ? &fn_call_global : 0;
data.fn_global = (R (*)(PL))fn;
}
function(R (*fn)(PL)) {
data.fn_call = &fn_call_global;
data.fn_global = fn;
}
template<typename C>
function(R (C::*fn)(PL), C *obj) {
data.fn_call = &fn_call_member<C>;
(R (C::*&)(PL))data.fn_member = fn;
assert(sizeof data.fn_member >= sizeof fn);
data.object = obj;
}
template<typename C>
function(R (C::*fn)(PL) const, C *obj) {
data.fn_call = &fn_call_member<C>;
(R (C::*&)(PL))data.fn_member = (R (C::*&)(PL))fn;
assert(sizeof data.fn_member >= sizeof fn);
data.object = obj;
}
function& operator=(void *fn) { return operator=(function(fn)); }
function& operator=(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); return *this; }
function(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); }
function(const function &source) { operator=(source); }
//no pointer
function() {
data.callback = 0;
}
//symbolic link pointer (nall/dl.hpp::sym, etc)
function(void *callback) {
data.callback = callback ? &callback_global : 0;
data.callback_global = (R (*)(P...))callback;
}
//global function pointer
function(R (*callback)(P...)) {
data.callback = &callback_global;
data.callback_global = callback;
}
//member function pointer
template<typename C>
function(R (C::*callback)(P...), C *object) {
static_assert(sizeof data.callback_member >= sizeof callback, "callback_member is too small");
data.callback = &callback_member<C>;
(R (C::*&)(P...))data.callback_member = callback;
data.object = object;
}
//const member function pointer
template<typename C>
function(R (C::*callback)(P...) const, C *object) {
static_assert(sizeof data.callback_member >= sizeof callback, "callback_member is too small");
data.callback = &callback_member<C>;
(R (C::*&)(P...))data.callback_member = (R (C::*&)(P...))callback;
data.object = object;
}
//lambda function pointer
template<typename T>
function(T callback) {
static_assert(std::is_same<R, typename std::result_of<T(P...)>::type>::value, "lambda mismatch");
data.callback = &callback_global;
data.callback_global = (R (*)(P...))callback;
}
};
template<TL>
function<R (PL)> bind(R (*fn)(PL)) {
return function<R (PL)>(fn);
//bind functions to ease construction and assignment of function() with more than one argument
template<typename C, typename R, typename... P>
function<R (P...)> bind(R (C::*callback)(P...), C *object) {
return function<R (P...)>(callback, object);
}
template<typename C, TL>
function<R (PL)> bind(R (C::*fn)(PL), C *obj) {
return function<R (PL)>(fn, obj);
}
template<typename C, TL>
function<R (PL)> bind(R (C::*fn)(PL) const, C *obj) {
return function<R (PL)>(fn, obj);
template<typename C, typename R, typename... P>
function<R (P...)> bind(R (C::*callback)(P...) const, C *object) {
return function<R (P...)>(callback, object);
}
}
#undef cat
#undef TL
#undef PL
#undef CL
#endif

View File

@@ -1,8 +1,9 @@
#ifndef NALL_SERIALIZER_HPP
#define NALL_SERIALIZER_HPP
#include <type_traits>
#include <utility>
#include <nall/stdint.hpp>
#include <nall/traits.hpp>
#include <nall/utility.hpp>
namespace nall {
@@ -16,6 +17,7 @@ namespace nall {
//caveats:
//- only plain-old-data can be stored. complex classes must provide serialize(serializer&);
//- floating-point usage is not portable across platforms
class serializer {
public:
enum mode_t { Load, Save, Size };
@@ -51,7 +53,7 @@ namespace nall {
}
template<typename T> void integer(T &value) {
enum { size = is_bool<T>::value ? 1 : sizeof(T) };
enum { size = std::is_same<bool, T>::value ? 1 : sizeof(T) };
if(imode == Save) {
for(unsigned n = 0; n < size; n++) idata[isize++] = value >> (n << 3);
} else if(imode == Load) {
@@ -63,7 +65,7 @@ namespace nall {
}
template<typename T> void array(T &array) {
enum { size = sizeof(T) / sizeof(typename remove_extent<T>::type) };
enum { size = sizeof(T) / sizeof(typename std::remove_extent<T>::type) };
for(unsigned n = 0; n < size; n++) integer(array[n]);
}
@@ -102,7 +104,7 @@ namespace nall {
}
serializer(serializer &&s) {
operator=(move(s));
operator=(std::move(s));
}
//construction

View File

@@ -10,42 +10,13 @@
#include <nall/utf8.hpp>
#include <nall/vector.hpp>
inline char chrlower(char c);
inline char chrupper(char c);
inline int stricmp(const char *dest, const char *src);
inline int strpos (const char *str, const char *key);
inline int qstrpos(const char *str, const char *key);
inline bool strbegin (const char *str, const char *key);
inline bool stribegin(const char *str, const char *key);
inline bool strend (const char *str, const char *key);
inline bool striend(const char *str, const char *key);
inline char* strlower(char *str);
inline char* strupper(char *str);
inline char* strtr(char *dest, const char *before, const char *after);
inline uintmax_t strhex (const char *str);
inline intmax_t strsigned (const char *str);
inline uintmax_t strunsigned(const char *str);
inline uintmax_t strbin (const char *str);
inline double strdouble (const char *str);
inline bool match(const char *pattern, const char *str);
inline bool strint (const char *str, int &result);
inline bool strmath(const char *str, int &result);
inline size_t strlcpy(char *dest, const char *src, size_t length);
inline size_t strlcat(char *dest, const char *src, size_t length);
inline char* ltrim(char *str, const char *key = " ");
inline char* rtrim(char *str, const char *key = " ");
inline char* trim (char *str, const char *key = " ");
inline char* ltrim_once(char *str, const char *key = " ");
inline char* rtrim_once(char *str, const char *key = " ");
inline char* trim_once (char *str, const char *key = " ");
namespace nall {
class string;
template<typename T> inline string to_string(T);
class string {
public:
inline void reserve(size_t);
inline void reserve(unsigned);
inline unsigned length() const;
inline string& assign(const char*);
@@ -78,7 +49,7 @@ namespace nall {
protected:
char *data;
size_t size;
unsigned size;
#if defined(QT_CORE_LIB)
public:
@@ -98,29 +69,69 @@ namespace nall {
lstring(std::initializer_list<string>);
};
template<typename... Args> inline string sprint(const char *s, Args... args);
template<typename... Args> inline void print(const char *s, Args... args);
//compare.hpp
inline char chrlower(char c);
inline char chrupper(char c);
inline int stricmp(const char *dest, const char *src);
inline int strpos (const char *str, const char *key);
inline int qstrpos(const char *str, const char *key);
inline bool strbegin (const char *str, const char *key);
inline bool stribegin(const char *str, const char *key);
inline bool strend (const char *str, const char *key);
inline bool striend(const char *str, const char *key);
//convert.hpp
inline char* strlower(char *str);
inline char* strupper(char *str);
inline char* strtr(char *dest, const char *before, const char *after);
inline uintmax_t strhex (const char *str);
inline intmax_t strsigned (const char *str);
inline uintmax_t strunsigned(const char *str);
inline uintmax_t strbin (const char *str);
inline double strdouble (const char *str);
//match.hpp
inline bool match(const char *pattern, const char *str);
//math.hpp
inline bool strint (const char *str, int &result);
inline bool strmath(const char *str, int &result);
//strl.hpp
inline unsigned strlcpy(char *dest, const char *src, unsigned length);
inline unsigned strlcat(char *dest, const char *src, unsigned length);
//trim.hpp
inline char* ltrim(char *str, const char *key = " ");
inline char* rtrim(char *str, const char *key = " ");
inline char* trim (char *str, const char *key = " ");
inline char* ltrim_once(char *str, const char *key = " ");
inline char* rtrim_once(char *str, const char *key = " ");
inline char* trim_once (char *str, const char *key = " ");
//utility.hpp
inline unsigned strlcpy(string &dest, const char *src, unsigned length);
inline unsigned strlcat(string &dest, const char *src, unsigned length);
inline string substr(const char *src, unsigned start = 0, unsigned length = 0);
inline string& strlower(string &str);
inline string& strupper(string &str);
inline string& strtr(string &dest, const char *before, const char *after);
inline string& ltrim(string &str, const char *key = " ");
inline string& rtrim(string &str, const char *key = " ");
inline string& trim (string &str, const char *key = " ");
inline string& ltrim_once(string &str, const char *key = " ");
inline string& rtrim_once(string &str, const char *key = " ");
inline string& trim_once (string &str, const char *key = " ");
template<unsigned length = 0, char padding = '0'> inline string strhex(uintmax_t value);
template<unsigned length = 0, char padding = '0'> inline string strsigned(intmax_t value);
template<unsigned length = 0, char padding = '0'> inline string strunsigned(uintmax_t value);
template<unsigned length = 0, char padding = '0'> inline string strbin(uintmax_t value);
inline unsigned strdouble(char *str, double value);
inline string strdouble(double value);
//variadic.hpp
template<typename... Args> inline string sprint(Args... args);
template<typename... Args> inline void print(Args... args);
};
inline size_t strlcpy(nall::string &dest, const char *src, size_t length);
inline size_t strlcat(nall::string &dest, const char *src, size_t length);
inline nall::string& strlower(nall::string &str);
inline nall::string& strupper(nall::string &str);
inline nall::string& strtr(nall::string &dest, const char *before, const char *after);
inline nall::string& ltrim(nall::string &str, const char *key = " ");
inline nall::string& rtrim(nall::string &str, const char *key = " ");
inline nall::string& trim (nall::string &str, const char *key = " ");
inline nall::string& ltrim_once(nall::string &str, const char *key = " ");
inline nall::string& rtrim_once(nall::string &str, const char *key = " ");
inline nall::string& trim_once (nall::string &str, const char *key = " ");
inline nall::string substr(const char *src, size_t start = 0, size_t length = 0);
template<unsigned length = 0, char padding = '0'> inline nall::string strhex(uintmax_t value);
template<unsigned length = 0, char padding = '0'> inline nall::string strsigned(intmax_t value);
template<unsigned length = 0, char padding = '0'> inline nall::string strunsigned(uintmax_t value);
template<unsigned length = 0, char padding = '0'> inline nall::string strbin(uintmax_t value);
inline size_t strdouble(char *str, double value);
inline nall::string strdouble(double value);
#endif

View File

@@ -2,28 +2,31 @@
#define NALL_STRING_CAST_HPP
namespace nall {
//this is needed, as C++0x does not support explicit template specialization inside classes
template<> inline string to_string<bool> (bool v) { return v ? "true" : "false"; }
template<> inline string to_string<signed int> (signed int v) { return strsigned(v); }
template<> inline string to_string<unsigned int> (unsigned int v) { return strunsigned(v); }
template<> inline string to_string<double> (double v) { return strdouble(v); }
template<> inline string to_string<char*> (char *v) { return v; }
template<> inline string to_string<const char*> (const char *v) { return v; }
template<> inline string to_string<string> (string v) { return v; }
template<> inline string to_string<const string&>(const string &v) { return v; }
template<typename T> string& string::operator= (T value) { return assign(to_string<T>(value)); }
template<typename T> string& string::operator<<(T value) { return append(to_string<T>(value)); }
//this is needed, as C++0x does not support explicit template specialization inside classes
template<> inline string to_string<bool> (bool v) { return v ? "true" : "false"; }
template<> inline string to_string<signed int> (signed int v) { return strsigned(v); }
template<> inline string to_string<unsigned int> (unsigned int v) { return strunsigned(v); }
template<> inline string to_string<double> (double v) { return strdouble(v); }
template<> inline string to_string<char*> (char *v) { return v; }
template<> inline string to_string<const char*> (const char *v) { return v; }
template<> inline string to_string<string> (string v) { return v; }
template<> inline string to_string<const string&>(const string &v) { return v; }
template<typename T> lstring& lstring::operator<<(T value) {
operator[](size()).assign(to_string<T>(value));
return *this;
}
template<typename T> string& string::operator= (T value) { return assign(to_string<T>(value)); }
template<typename T> string& string::operator<<(T value) { return append(to_string<T>(value)); }
template<typename T> lstring& lstring::operator<<(T value) {
operator[](size()).assign(to_string<T>(value));
return *this;
}
#if defined(QT_CORE_LIB)
template<> inline string to_string<QString>(QString v) { return v.toUtf8().constData(); }
template<> inline string to_string<const QString&>(const QString &v) { return v.toUtf8().constData(); }
string::operator QString() const { return QString::fromUtf8(*this); }
#endif
#if defined(QT_CORE_LIB)
template<> inline string to_string<const QString&>(const QString &v) { return v.toUtf8().constData(); }
string::operator QString() const { return QString::fromUtf8(*this); }
#endif
}
#endif

View File

@@ -1,6 +1,8 @@
#ifndef NALL_STRING_COMPARE_HPP
#define NALL_STRING_COMPARE_HPP
namespace nall {
char chrlower(char c) {
return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c;
}
@@ -97,4 +99,6 @@ bool striend(const char *str, const char *key) {
return true;
}
}
#endif

View File

@@ -1,6 +1,8 @@
#ifndef NALL_STRING_CONVERT_HPP
#define NALL_STRING_CONVERT_HPP
namespace nall {
char* strlower(char *str) {
if(!str) return 0;
int i = 0;
@@ -146,4 +148,6 @@ double strdouble(const char *str) {
return !negate ? result : -result;
}
}
#endif

View File

@@ -3,7 +3,7 @@
namespace nall {
void string::reserve(size_t size_) {
void string::reserve(unsigned size_) {
if(size_ > size) {
size = size_;
data = (char*)realloc(data, size + 1);
@@ -81,6 +81,7 @@ string& string::operator=(string &&source) {
size = source.size;
data = source.data;
source.data = 0;
source.size = 0;
return *this;
}
@@ -94,12 +95,12 @@ bool string::readfile(const char *filename) {
#if !defined(_WIN32)
FILE *fp = fopen(filename, "rb");
#else
FILE *fp = _wfopen(nall::utf16_t(filename), L"rb");
FILE *fp = _wfopen(utf16_t(filename), L"rb");
#endif
if(!fp) return false;
fseek(fp, 0, SEEK_END);
size_t size = ftell(fp);
unsigned size = ftell(fp);
rewind(fp);
char *fdata = new char[size + 1];
unsigned unused = fread(fdata, 1, size, fp);

View File

@@ -2,59 +2,60 @@
#define NALL_FILENAME_HPP
namespace nall {
// "foo/bar.c" -> "foo/", "bar.c" -> "./"
inline string dir(char const *name) {
string result = name;
for(signed i = strlen(result); i >= 0; i--) {
if(result[i] == '/' || result[i] == '\\') {
result[i + 1] = 0;
break;
}
if(i == 0) result = "./";
}
return result;
}
// "foo/bar.c" -> "bar.c"
inline string notdir(char const *name) {
for(signed i = strlen(name); i >= 0; i--) {
if(name[i] == '/' || name[i] == '\\') {
name += i + 1;
break;
}
// "foo/bar.c" -> "foo/", "bar.c" -> "./"
inline string dir(char const *name) {
string result = name;
for(signed i = strlen(result); i >= 0; i--) {
if(result[i] == '/' || result[i] == '\\') {
result[i + 1] = 0;
break;
}
string result = name;
return result;
if(i == 0) result = "./";
}
return result;
}
// "foo/bar.c" -> "foo/bar"
inline string basename(char const *name) {
string result = name;
for(signed i = strlen(result); i >= 0; i--) {
if(result[i] == '/' || result[i] == '\\') {
//file has no extension
break;
}
if(result[i] == '.') {
result[i] = 0;
break;
}
// "foo/bar.c" -> "bar.c"
inline string notdir(char const *name) {
for(signed i = strlen(name); i >= 0; i--) {
if(name[i] == '/' || name[i] == '\\') {
name += i + 1;
break;
}
return result;
}
string result = name;
return result;
}
// "foo/bar.c" -> "c"
inline string extension(char const *name) {
for(signed i = strlen(name); i >= 0; i--) {
if(name[i] == '.') {
name += i + 1;
break;
}
// "foo/bar.c" -> "foo/bar"
inline string basename(char const *name) {
string result = name;
for(signed i = strlen(result); i >= 0; i--) {
if(result[i] == '/' || result[i] == '\\') {
//file has no extension
break;
}
if(result[i] == '.') {
result[i] = 0;
break;
}
string result = name;
return result;
}
return result;
}
// "foo/bar.c" -> "c"
inline string extension(char const *name) {
for(signed i = strlen(name); i >= 0; i--) {
if(name[i] == '.') {
name += i + 1;
break;
}
}
string result = name;
return result;
}
}
#endif

View File

@@ -1,6 +1,8 @@
#ifndef NALL_STRING_MATCH_HPP
#define NALL_STRING_MATCH_HPP
namespace nall {
bool match(const char *p, const char *s) {
const char *p_ = 0, *s_ = 0;
@@ -69,4 +71,6 @@ bool match(const char *p, const char *s) {
}
}
}
#endif

View File

@@ -1,6 +1,8 @@
#ifndef NALL_STRING_MATH_HPP
#define NALL_STRING_MATH_HPP
namespace nall {
static int eval_integer(const char *&s) {
if(!*s) throw "unrecognized_integer";
int value = 0, x = *s, y = *(s + 1);
@@ -157,4 +159,6 @@ bool strmath(const char *s, int &result) {
}
}
}
#endif

View File

@@ -1,13 +1,15 @@
#ifndef NALL_STRING_STRL_HPP
#define NALL_STRING_STRL_HPP
namespace nall {
//strlcpy, strlcat based on OpenBSD implementation by Todd C. Miller
//return = strlen(src)
size_t strlcpy(char *dest, const char *src, size_t length) {
unsigned strlcpy(char *dest, const char *src, unsigned length) {
char *d = dest;
const char *s = src;
size_t n = length;
unsigned n = length;
if(n) {
while(--n && (*d++ = *s++)); //copy as many bytes as possible, or until null terminator reached
@@ -22,13 +24,13 @@ size_t strlcpy(char *dest, const char *src, size_t length) {
}
//return = strlen(src) + min(length, strlen(dest))
size_t strlcat(char *dest, const char *src, size_t length) {
unsigned strlcat(char *dest, const char *src, unsigned length) {
char *d = dest;
const char *s = src;
size_t n = length;
unsigned n = length;
while(n-- && *d) d++; //find end of dest
size_t dlength = d - dest;
unsigned dlength = d - dest;
n = length - dlength; //subtract length of dest from maximum string length
if(!n) return dlength + strlen(s);
@@ -45,4 +47,6 @@ size_t strlcat(char *dest, const char *src, size_t length) {
return dlength + (s - src); //return length of resulting string, sans null terminator
}
}
#endif

View File

@@ -1,6 +1,8 @@
#ifndef NALL_STRING_TRIM_HPP
#define NALL_STRING_TRIM_HPP
namespace nall {
char* ltrim(char *str, const char *key) {
if(!key || !*key) return str;
while(strbegin(str, key)) {
@@ -47,4 +49,6 @@ char* trim_once(char *str, const char *key) {
return ltrim_once(rtrim_once(str, key), key);
}
}
#endif

View File

@@ -1,18 +1,20 @@
#ifndef NALL_STRING_UTILITY_HPP
#define NALL_STRING_UTILITY_HPP
size_t strlcpy(nall::string &dest, const char *src, size_t length) {
namespace nall {
unsigned strlcpy(string &dest, const char *src, unsigned length) {
dest.reserve(length);
return strlcpy(dest(), src, length);
}
size_t strlcat(nall::string &dest, const char *src, size_t length) {
unsigned strlcat(string &dest, const char *src, unsigned length) {
dest.reserve(length);
return strlcat(dest(), src, length);
}
nall::string substr(const char *src, size_t start, size_t length) {
nall::string dest;
string substr(const char *src, unsigned start, unsigned length) {
string dest;
if(length == 0) {
//copy entire string
dest = src + start;
@@ -23,22 +25,22 @@ nall::string substr(const char *src, size_t start, size_t length) {
return dest;
}
/* very simplistic wrappers to return nall::string& instead of char* type */
/* very simplistic wrappers to return string& instead of char* type */
nall::string& strlower(nall::string &str) { strlower(str()); return str; }
nall::string& strupper(nall::string &str) { strupper(str()); return str; }
nall::string& strtr(nall::string &dest, const char *before, const char *after) { strtr(dest(), before, after); return dest; }
nall::string& ltrim(nall::string &str, const char *key) { ltrim(str(), key); return str; }
nall::string& rtrim(nall::string &str, const char *key) { rtrim(str(), key); return str; }
nall::string& trim (nall::string &str, const char *key) { trim (str(), key); return str; }
nall::string& ltrim_once(nall::string &str, const char *key) { ltrim_once(str(), key); return str; }
nall::string& rtrim_once(nall::string &str, const char *key) { rtrim_once(str(), key); return str; }
nall::string& trim_once (nall::string &str, const char *key) { trim_once (str(), key); return str; }
string& strlower(string &str) { strlower(str()); return str; }
string& strupper(string &str) { strupper(str()); return str; }
string& strtr(string &dest, const char *before, const char *after) { strtr(dest(), before, after); return dest; }
string& ltrim(string &str, const char *key) { ltrim(str(), key); return str; }
string& rtrim(string &str, const char *key) { rtrim(str(), key); return str; }
string& trim (string &str, const char *key) { trim (str(), key); return str; }
string& ltrim_once(string &str, const char *key) { ltrim_once(str(), key); return str; }
string& rtrim_once(string &str, const char *key) { rtrim_once(str(), key); return str; }
string& trim_once (string &str, const char *key) { trim_once (str(), key); return str; }
/* arithmetic <> string */
template<unsigned length, char padding> nall::string strhex(uintmax_t value) {
nall::string output;
template<unsigned length, char padding> string strhex(uintmax_t value) {
string output;
unsigned offset = 0;
//render string backwards, as we do not know its length yet
@@ -61,8 +63,8 @@ template<unsigned length, char padding> nall::string strhex(uintmax_t value) {
return output;
}
template<unsigned length, char padding> nall::string strsigned(intmax_t value) {
nall::string output;
template<unsigned length, char padding> string strsigned(intmax_t value) {
string output;
unsigned offset = 0;
bool negative = value < 0;
@@ -87,8 +89,8 @@ template<unsigned length, char padding> nall::string strsigned(intmax_t value) {
return output;
}
template<unsigned length, char padding> nall::string strunsigned(uintmax_t value) {
nall::string output;
template<unsigned length, char padding> string strunsigned(uintmax_t value) {
string output;
unsigned offset = 0;
do {
@@ -109,8 +111,8 @@ template<unsigned length, char padding> nall::string strunsigned(uintmax_t value
return output;
}
template<unsigned length, char padding> nall::string strbin(uintmax_t value) {
nall::string output;
template<unsigned length, char padding> string strbin(uintmax_t value) {
string output;
unsigned offset = 0;
do {
@@ -134,7 +136,7 @@ template<unsigned length, char padding> nall::string strbin(uintmax_t value) {
//using sprintf is certainly not the most ideal method to convert
//a double to a string ... but attempting to parse a double by
//hand, digit-by-digit, results in subtle rounding errors.
size_t strdouble(char *str, double value) {
unsigned strdouble(char *str, double value) {
char buffer[256];
sprintf(buffer, "%f", value);
@@ -155,11 +157,13 @@ size_t strdouble(char *str, double value) {
return length + 1;
}
nall::string strdouble(double value) {
nall::string temp;
string strdouble(double value) {
string temp;
temp.reserve(strdouble(0, value));
strdouble(temp(), value);
return temp;
}
}
#endif

View File

@@ -2,36 +2,26 @@
#define NALL_STRING_VARIADIC_HPP
namespace nall {
static void sprint(string &output, unsigned &offset, const char *&s) {
while(*s) output[offset++] = *s++;
}
template<typename T, typename... Args>
static void sprint(string &output, unsigned &offset, const char *&s, T value, Args... args) {
while(*s) {
if(*s == '$') {
string data = to_string<T>(value);
unsigned i = 0;
while(data[i]) output[offset++] = data[i++];
sprint(output, offset, ++s, args...);
return;
} else {
output[offset++] = *s++;
}
}
}
static void isprint(string &output) {
}
template<typename... Args> inline string sprint(const char *s, Args... args) {
string output;
unsigned offset = 0;
sprint(output, offset, s, args...);
output[offset] = 0;
return output;
}
template<typename T, typename... Args>
static void isprint(string &output, T value, Args... args) {
output << to_string<T>(value);
isprint(output, args...);
}
template<typename... Args> inline string sprint(Args... args) {
string output;
isprint(output, args...);
return output;
}
template<typename... Args> inline void print(Args... args) {
printf("%s", (const char*)sprint(args...));
}
template<typename... Args> inline void print(const char *s, Args... args) {
printf("%s", (const char*)sprint(s, args...));
}
}
#endif

View File

@@ -2,9 +2,7 @@
#define NALL_STRING_XML_HPP
//XML subset parser
//version 0.04
#include <nall/array.hpp>
//version 0.05
namespace nall {
@@ -16,15 +14,14 @@ struct xml_attribute {
struct xml_element : xml_attribute {
string parse() const;
array<xml_attribute*> attribute;
array<xml_element*> element;
~xml_element();
linear_vector<xml_attribute> attribute;
linear_vector<xml_element> element;
protected:
void parse_doctype(const char *&data);
bool parse_head(string data);
bool parse_body(const char *&data);
friend xml_element *xml_parse(const char *data);
friend xml_element xml_parse(const char *data);
};
inline string xml_attribute::parse() const {
@@ -134,11 +131,11 @@ inline bool xml_element::parse_head(string data) {
side.qsplit("=", part[i]);
if(side.size() != 2) throw "...";
xml_attribute *attr = new xml_attribute;
attr->name = side[0];
attr->content = side[1];
if(strbegin(attr->content, "\"") && strend(attr->content, "\"")) trim_once(attr->content, "\"");
else if(strbegin(attr->content, "'") && strend(attr->content, "'")) trim_once(attr->content, "'");
xml_attribute attr;
attr.name = side[0];
attr.content = side[1];
if(strbegin(attr.content, "\"") && strend(attr.content, "\"")) trim_once(attr.content, "\"");
else if(strbegin(attr.content, "'") && strend(attr.content, "'")) trim_once(attr.content, "'");
else throw "...";
attribute.add(attr);
}
@@ -191,10 +188,8 @@ inline bool xml_element::parse_body(const char *&data) {
while(*data) {
unsigned index = element.size();
xml_element *elem = new xml_element;
if(elem->parse_body(data) == false) {
delete elem;
xml_element node;
if(node.parse_body(data) == false) {
if(*data == '/') {
signed length = data - content_begin - 1;
if(length > 0) content = substr(content_begin, 0, length);
@@ -216,23 +211,18 @@ inline bool xml_element::parse_body(const char *&data) {
return true;
}
} else {
element.add(elem);
element.add(node);
}
}
}
}
inline xml_element::~xml_element() {
for(unsigned i = 0; i < attribute.size(); i++) delete attribute[i];
for(unsigned i = 0; i < element.size(); i++) delete element[i];
}
//ensure there is only one root element
inline bool xml_validate(xml_element *document) {
inline bool xml_validate(xml_element &document) {
unsigned root_counter = 0;
for(unsigned i = 0; i < document->element.size(); i++) {
string &name = document->element[i]->name;
for(unsigned i = 0; i < document.element.size(); i++) {
string &name = document.element[i].name;
if(strbegin(name, "?")) continue;
if(strbegin(name, "!")) continue;
if(++root_counter > 1) return false;
@@ -241,25 +231,24 @@ inline bool xml_validate(xml_element *document) {
return true;
}
inline xml_element* xml_parse(const char *data) {
xml_element *self = new xml_element;
inline xml_element xml_parse(const char *data) {
xml_element self;
try {
while(*data) {
xml_element *elem = new xml_element;
if(elem->parse_body(data) == false) {
delete elem;
xml_element node;
if(node.parse_body(data) == false) {
break;
} else {
self->element.add(elem);
self.element.add(node);
}
}
if(xml_validate(self) == false) throw "...";
return self;
} catch(const char*) {
delete self;
return 0;
xml_element empty;
return empty;
}
}

View File

@@ -1,97 +0,0 @@
#ifndef NALL_TRAITS_HPP
#define NALL_TRAITS_HPP
namespace nall {
//==
//is
//==
template<typename T> struct is_integral { enum { value = false }; };
template<> struct is_integral<bool> { enum { value = true }; };
template<> struct is_integral<char> { enum { value = true }; };
template<> struct is_integral<signed char> { enum { value = true }; };
template<> struct is_integral<unsigned char> { enum { value = true }; };
template<> struct is_integral<wchar_t> { enum { value = true }; };
template<> struct is_integral<short> { enum { value = true }; };
template<> struct is_integral<unsigned short> { enum { value = true }; };
template<> struct is_integral<long> { enum { value = true }; };
template<> struct is_integral<unsigned long> { enum { value = true }; };
template<> struct is_integral<long long> { enum { value = true }; };
template<> struct is_integral<unsigned long long> { enum { value = true }; };
template<> struct is_integral<int> { enum { value = true }; };
template<> struct is_integral<unsigned int> { enum { value = true }; };
template<typename T> struct is_floating_point { enum { value = false }; };
template<> struct is_floating_point<float> { enum { value = true }; };
template<> struct is_floating_point<double> { enum { value = true }; };
template<> struct is_floating_point<long double> { enum { value = true }; };
template<typename T> struct is_bool { enum { value = false }; };
template<> struct is_bool<bool> { enum { value = true }; };
template<typename T> struct is_void { enum { value = false }; };
template<> struct is_void<void> { enum { value = true }; };
template<typename T> struct is_arithmetic {
enum { value = is_integral<T>::value || is_floating_point<T>::value };
};
template<typename T> struct is_fundamental {
enum { value = is_integral<T>::value || is_floating_point<T>::value || is_void<T>::value };
};
template<typename T> struct is_compound {
enum { value = !is_fundamental<T>::value };
};
template<typename T> struct is_array { enum { value = false }; };
template<typename T> struct is_array<T[]> { enum { value = true }; };
template<typename T, int N> struct is_array<T[N]> { enum { value = true }; };
template<typename T> struct is_const { enum { value = false }; };
template<typename T> struct is_const<const T> { enum { value = true }; };
template<typename T> struct is_const<const T&> { enum { value = true }; };
template<typename T> struct is_pointer { enum { value = false }; };
template<typename T> struct is_pointer<T*> { enum { value = true }; };
template<typename T> struct is_reference { enum { value = false }; };
template<typename T> struct is_reference<T&> { enum { value = true }; };
template<typename T, typename U> struct is_same { enum { value = false }; };
template<typename T> struct is_same<T, T> { enum { value = true }; };
//===
//add
//===
template<typename T> struct add_const { typedef const T type; };
template<typename T> struct add_const<const T> { typedef const T type; };
template<typename T> struct add_const<const T&> { typedef const T& type; };
template<typename T> struct add_pointer { typedef T* type; };
template<typename T> struct add_pointer<T*> { typedef T** type; };
template<typename T> struct add_reference { typedef T& type; };
template<typename T> struct add_reference<T&> { typedef T& type; };
//======
//remove
//======
template<typename T> struct remove_const { typedef T type; };
template<typename T> struct remove_const<const T> { typedef T type; };
template<typename T> struct remove_const<const T&> { typedef T type; };
template<typename T> struct remove_extent { typedef T type; };
template<typename T> struct remove_extent<T[]> { typedef T type; };
template<typename T, int N> struct remove_extent<T[N]> { typedef T type; };
template<typename T> struct remove_pointer { typedef T type; };
template<typename T> struct remove_pointer<T*> { typedef T type; };
template<typename T> struct remove_reference { typedef T type; };
template<typename T> struct remove_reference<T&> { typedef T type; };
}
#endif

View File

@@ -1,29 +1,18 @@
#ifndef NALL_UTILITY_HPP
#define NALL_UTILITY_HPP
#include <nall/traits.hpp>
#include <type_traits>
#include <utility>
namespace nall {
template<typename T> struct identity {
typedef T type;
};
template<typename T> typename remove_reference<T>::type&& move(T &&value) {
return value;
}
template<typename T> T&& forward(typename identity<T>::type &&value) {
return value;
}
template<bool C, typename T = bool> struct enable_if { typedef T type; };
template<typename T> struct enable_if<false, T> {};
template<typename C, typename T = bool> struct mp_enable_if : enable_if<C::value, T> {};
template<typename T> inline void swap(T &x, T &y) {
T temp(move(x));
x = move(y);
y = move(temp);
T temp(std::move(x));
x = std::move(y);
y = std::move(temp);
}
template<typename T> struct base_from_member {

View File

@@ -3,10 +3,11 @@
#include <initializer_list>
#include <new>
#include <type_traits>
#include <utility>
#include <nall/algorithm.hpp>
#include <nall/bit.hpp>
#include <nall/concept.hpp>
#include <nall/traits.hpp>
#include <nall/utility.hpp>
namespace nall {
@@ -86,11 +87,12 @@ namespace nall {
inline linear_vector<T>& operator=(const linear_vector<T> &source) {
reset();
reserve(source.capacity());
for(unsigned i = 0; i < source.size(); i++) add(source[i]);
resize(source.size());
for(unsigned i = 0; i < source.size(); i++) operator[](i) = source.operator[](i);
return *this;
}
linear_vector(const linear_vector<T> &source) {
linear_vector(const linear_vector<T> &source) : pool(0), poolsize(0), objectsize(0) {
operator=(source);
}
@@ -101,11 +103,12 @@ namespace nall {
poolsize = source.poolsize;
objectsize = source.objectsize;
source.pool = 0;
source.reset();
return *this;
}
linear_vector(linear_vector<T> &&source) {
operator=(move(source));
linear_vector(linear_vector<T> &&source) : pool(0), poolsize(0), objectsize(0) {
operator=(std::move(source));
}
//construction
@@ -193,11 +196,12 @@ namespace nall {
inline pointer_vector<T>& operator=(const pointer_vector<T> &source) {
reset();
reserve(source.capacity());
for(unsigned i = 0; i < source.size(); i++) add(source[i]);
resize(source.size());
for(unsigned i = 0; i < source.size(); i++) operator[](i) = source.operator[](i);
return *this;
}
pointer_vector(const pointer_vector<T> &source) {
pointer_vector(const pointer_vector<T> &source) : pool(0), poolsize(0), objectsize(0) {
operator=(source);
}
@@ -208,11 +212,12 @@ namespace nall {
poolsize = source.poolsize;
objectsize = source.objectsize;
source.pool = 0;
source.reset();
return *this;
}
pointer_vector(pointer_vector<T> &&source) {
operator=(move(source));
pointer_vector(pointer_vector<T> &&source) : pool(0), poolsize(0), objectsize(0) {
operator=(std::move(source));
}
//construction

View File

@@ -194,9 +194,8 @@ bool snesreader_load_jma(const char *filename, uint8_t *&data, unsigned &size) {
}
}
dllexport bool snesreader_load(string &filename, string &xmldata, uint8_t *&data, unsigned &size) {
dllexport bool snesreader_load(string &filename, uint8_t *&data, unsigned &size) {
if(file::exists(filename) == false) return false;
xmldata = "";
bool success = false;
if(striend(filename, ".zip")
@@ -226,6 +225,11 @@ dllexport bool snesreader_load(string &filename, string &xmldata, uint8_t *&data
//remove copier header, if it exists
if((size & 0x7fff) == 512) memmove(data, data + 512, size -= 512);
return true;
}
dllexport bool snesreader_map(string &xmldata, const uint8_t *data, unsigned size) {
xmldata = "";
xml.generate(xmldata, data, size);
return true;
}

View File

@@ -3,5 +3,6 @@ namespace nall { class string; }
extern "C" {
const char* snesreader_supported();
bool snesreader_load(nall::string &filename, nall::string &xml, uint8_t *&data, unsigned &size);
bool snesreader_load(nall::string &filename, uint8_t *&data, unsigned &size);
bool snesreader_map(nall::string &xml, const uint8_t *data, unsigned size);
}

View File

@@ -56,30 +56,6 @@ void XML::generate(string &xml, const uint8_t *data, unsigned size) {
xml << " <map address='80-bf:6000-7fff'/>\n";
xml << " </mmio>\n";
xml << " </supergameboy>\n";
} else if(has_sdd1) {
xml << " <rom>\n";
xml << " <map mode='linear' address='00-3f:8000-ffff'/>\n";
xml << " <map mode='linear' address='40-7f:0000-ffff'/>\n";
xml << " <map mode='linear' address='80-bf:8000-ffff'/>\n";
xml << " </rom>\n";
if(ram_size > 0) {
xml << " <ram size='" << strhex(ram_size) << "'>\n";
xml << " <map mode='linear' address='20-3f:6000-7fff'/>\n";
xml << " <map mode='linear' address='a0-bf:6000-7fff'/>\n";
xml << " <map mode='linear' address='70-7f:0000-7fff'/>\n";
xml << " </ram>\n";
}
xml << " <sdd1>\n";
xml << " <mcu>\n";
xml << " <map address='c0-ff:0000-ffff'/>\n";
xml << " </mcu>\n";
xml << " <mmio>\n";
xml << " <map address='00-3f:4800-4807'/>\n";
xml << " <map address='80-bf:4800-4807'/>\n";
xml << " </mmio>\n";
xml << " </sdd1>\n";
} else if(has_spc7110) {
xml << " <rom>\n";
xml << " <map mode='shadow' address='00-0f:8000-ffff'/>\n";
@@ -147,6 +123,20 @@ void XML::generate(string &xml, const uint8_t *data, unsigned size) {
}
xml << " </ram>\n";
}
} else if(mapper == ExLoROM) {
xml << " <rom>\n";
xml << " <map mode='linear' address='00-3f:8000-ffff'/>\n";
xml << " <map mode='linear' address='40-7f:0000-ffff'/>\n";
xml << " <map mode='linear' address='80-bf:8000-ffff'/>\n";
xml << " </rom>\n";
if(ram_size > 0) {
xml << " <ram size='" << strhex(ram_size) << "'>\n";
xml << " <map mode='linear' address='20-3f:6000-7fff'/>\n";
xml << " <map mode='linear' address='a0-bf:6000-7fff'/>\n";
xml << " <map mode='linear' address='70-7f:0000-7fff'/>\n";
xml << " </ram>\n";
}
} else if(mapper == ExHiROM) {
xml << " <rom>\n";
xml << " <map mode='shadow' address='00-3f:8000-ffff' offset='400000'/>\n";
@@ -290,6 +280,18 @@ void XML::generate(string &xml, const uint8_t *data, unsigned size) {
xml << " </srtc>\n";
}
if(has_sdd1) {
xml << " <sdd1>\n";
xml << " <mcu>\n";
xml << " <map address='c0-ff:0000-ffff'/>\n";
xml << " </mcu>\n";
xml << " <mmio>\n";
xml << " <map address='00-3f:4800-4807'/>\n";
xml << " <map address='80-bf:4800-4807'/>\n";
xml << " </mmio>\n";
xml << " </sdd1>\n";
}
if(has_cx4) {
xml << " <cx4>\n";
xml << " <mmio>\n";
@@ -335,12 +337,12 @@ void XML::generate(string &xml, const uint8_t *data, unsigned size) {
if(has_dsp2) {
xml << " <necdsp program='DSP-2'>\n";
xml << " <dr>\n";
xml << " <map address='20-3f:6000-6fff'/>\n";
xml << " <map address='a0-bf:6000-6fff'/>\n";
xml << " </dr>\n";
xml << " <sr>\n";
xml << " <map address='20-3f:8000-bfff'/>\n";
xml << " <map address='a0-bf:8000-bfff'/>\n";
xml << " </dr>\n";
xml << " <sr>\n";
xml << " <map address='20-3f:c000-ffff'/>\n";
xml << " <map address='a0-bf:c000-ffff'/>\n";
xml << " </sr>\n";
xml << " </necdsp>\n";
}

View File

@@ -42,7 +42,6 @@ else ifeq ($(platform),win)
link += -mwindows -mthreads
# link += -mconsole -mthreads
link += -s -luuid -lkernel32 -luser32 -lgdi32 -lshell32
# statically link Qt for Windows build
link += -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc
ruby := video.direct3d video.wgl video.directdraw video.gdi video.qtraster
@@ -206,6 +205,11 @@ install:
install -D -m 644 data/bsnes.png $(DESTDIR)$(prefix)/share/pixmaps/bsnes.png
install -D -m 644 data/bsnes.desktop $(DESTDIR)$(prefix)/share/applications/bsnes.desktop
uninstall:
rm $(DESTDIR)$(prefix)/bin/bsnes
rm $(DESTDIR)$(prefix)/share/pixmaps/bsnes.png
rm $(DESTDIR)$(prefix)/share/applications/bsnes.desktop
clean: ui_clean
-@$(call delete,obj/*.o)
-@$(call delete,*.res)
@@ -214,18 +218,3 @@ clean: ui_clean
-@$(call delete,*.ilk)
-@$(call delete,*.pdb)
-@$(call delete,*.manifest)
help:
@echo "Usage: $(MAKE) platform=(os) compiler=(cc) [options]"
@echo ""
@echo "Supported platforms:"
@echo " x - Linux / BSD (x86, x86-64)"
@echo " win - Windows (x86, x86-64)"
@echo ""
@echo "Supported compilers:"
@echo " gcc - GCC compiler"
@echo " mingw32-gcc - MinGW compiler"
@echo " i586-mingw32-gcc - MinGW cross compiler"
@echo ""
@echo "Example: $(MAKE) platform=x compiler=gcc"
@echo ""

View File

@@ -1,6 +1,6 @@
static const char bsnesVersion[] = "062";
static const char bsnesVersion[] = "063";
static const char bsnesTitle[] = "bsnes";
static const unsigned bsnesSerializerVersion = 6;
static const unsigned bsnesSerializerVersion = 8;
//S-DSP can be encapsulated into a state machine using #define magic
//this avoids ~2.048m co_switch() calls per second (~5% speedup)
@@ -35,13 +35,4 @@ static const unsigned bsnesSerializerVersion = 6;
#include <nall/vector.hpp>
using namespace nall;
typedef int8_t int8;
typedef int16_t int16;
typedef int32_t int32;
typedef int64_t int64;
typedef uint8_t uint8;
typedef uint16_t uint16;
typedef uint32_t uint32;
typedef uint64_t uint64;
#include "interface.hpp"

View File

@@ -19,6 +19,9 @@ namespace memory {
Cartridge cartridge;
void Cartridge::load(Mode cartridge_mode, const lstring &xml_list) {
mode = Mode::Normal;
region = Region::NTSC;
ram_size = 0;
spc7110_data_rom_offset = 0x100000;
supergameboy_version = SuperGameBoyVersion::Version1;
supergameboy_ram_size = 0;

View File

@@ -79,22 +79,22 @@ private:
void parse_xml_sufami_turbo(const char*, bool);
void parse_xml_gameboy(const char*);
void xml_parse_rom(xml_element*);
void xml_parse_ram(xml_element*);
void xml_parse_superfx(xml_element*);
void xml_parse_sa1(xml_element*);
void xml_parse_bsx(xml_element*);
void xml_parse_sufamiturbo(xml_element*);
void xml_parse_supergameboy(xml_element*);
void xml_parse_srtc(xml_element*);
void xml_parse_sdd1(xml_element*);
void xml_parse_spc7110(xml_element*);
void xml_parse_cx4(xml_element*);
void xml_parse_necdsp(xml_element*);
void xml_parse_obc1(xml_element*);
void xml_parse_setadsp(xml_element*);
void xml_parse_setarisc(xml_element*);
void xml_parse_msu1(xml_element*);
void xml_parse_rom(xml_element&);
void xml_parse_ram(xml_element&);
void xml_parse_superfx(xml_element&);
void xml_parse_sa1(xml_element&);
void xml_parse_bsx(xml_element&);
void xml_parse_sufamiturbo(xml_element&);
void xml_parse_supergameboy(xml_element&);
void xml_parse_srtc(xml_element&);
void xml_parse_sdd1(xml_element&);
void xml_parse_spc7110(xml_element&);
void xml_parse_cx4(xml_element&);
void xml_parse_necdsp(xml_element&);
void xml_parse_obc1(xml_element&);
void xml_parse_setadsp(xml_element&);
void xml_parse_setarisc(xml_element&);
void xml_parse_msu1(xml_element&);
void xml_parse_address(Mapping&, const string&);
void xml_parse_mode(Mapping&, const string&);

View File

@@ -17,35 +17,35 @@ void Cartridge::parse_xml(const lstring &list) {
}
void Cartridge::parse_xml_cartridge(const char *data) {
xml_element *document = xml_parse(data);
if(document == 0) return;
xml_element document = xml_parse(data);
if(document.element.size() == 0) return;
foreach(head, document->element) {
if(head->name == "cartridge") {
foreach(attr, head->attribute) {
if(attr->name == "region") {
if(attr->content == "NTSC") region = Region::NTSC;
if(attr->content == "PAL") region = Region::PAL;
foreach(head, document.element) {
if(head.name == "cartridge") {
foreach(attr, head.attribute) {
if(attr.name == "region") {
if(attr.content == "NTSC") region = Region::NTSC;
if(attr.content == "PAL") region = Region::PAL;
}
}
foreach(node, head->element) {
if(node->name == "rom") xml_parse_rom(node);
if(node->name == "ram") xml_parse_ram(node);
if(node->name == "superfx") xml_parse_superfx(node);
if(node->name == "sa1") xml_parse_sa1(node);
if(node->name == "bsx") xml_parse_bsx(node);
if(node->name == "sufamiturbo") xml_parse_sufamiturbo(node);
if(node->name == "supergameboy") xml_parse_supergameboy(node);
if(node->name == "srtc") xml_parse_srtc(node);
if(node->name == "sdd1") xml_parse_sdd1(node);
if(node->name == "spc7110") xml_parse_spc7110(node);
if(node->name == "cx4") xml_parse_cx4(node);
if(node->name == "necdsp") xml_parse_necdsp(node);
if(node->name == "obc1") xml_parse_obc1(node);
if(node->name == "setadsp") xml_parse_setadsp(node);
if(node->name == "setarisc") xml_parse_setarisc(node);
if(node->name == "msu1") xml_parse_msu1(node);
foreach(node, head.element) {
if(node.name == "rom") xml_parse_rom(node);
if(node.name == "ram") xml_parse_ram(node);
if(node.name == "superfx") xml_parse_superfx(node);
if(node.name == "sa1") xml_parse_sa1(node);
if(node.name == "bsx") xml_parse_bsx(node);
if(node.name == "sufamiturbo") xml_parse_sufamiturbo(node);
if(node.name == "supergameboy") xml_parse_supergameboy(node);
if(node.name == "srtc") xml_parse_srtc(node);
if(node.name == "sdd1") xml_parse_sdd1(node);
if(node.name == "spc7110") xml_parse_spc7110(node);
if(node.name == "cx4") xml_parse_cx4(node);
if(node.name == "necdsp") xml_parse_necdsp(node);
if(node.name == "obc1") xml_parse_obc1(node);
if(node.name == "setadsp") xml_parse_setadsp(node);
if(node.name == "setarisc") xml_parse_setarisc(node);
if(node.name == "msu1") xml_parse_msu1(node);
}
}
}
@@ -58,106 +58,104 @@ void Cartridge::parse_xml_sufami_turbo(const char *data, bool slot) {
}
void Cartridge::parse_xml_gameboy(const char *data) {
xml_element *document = xml_parse(data);
if(document == 0) return;
xml_element document = xml_parse(data);
if(document.element.size() == 0) return;
foreach(head, document->element) {
if(head->name == "cartridge") {
foreach(attr, head->attribute) {
if(attr->name == "rtc") {
supergameboy_rtc_size = (attr->content == "true") ? 4 : 0;
foreach(head, document.element) {
if(head.name == "cartridge") {
foreach(attr, head.attribute) {
if(attr.name == "rtc") {
supergameboy_rtc_size = (attr.content == "true") ? 4 : 0;
}
}
foreach(leaf, head->element) {
if(leaf->name == "ram") {
foreach(attr, leaf->attribute) {
if(attr->name == "size") {
supergameboy_ram_size = strhex(attr->content);
foreach(leaf, head.element) {
if(leaf.name == "ram") {
foreach(attr, leaf.attribute) {
if(attr.name == "size") {
supergameboy_ram_size = strhex(attr.content);
}
}
}
}
}
}
delete document;
}
void Cartridge::xml_parse_rom(xml_element *root) {
foreach(leaf, root->element) {
if(leaf->name == "map") {
void Cartridge::xml_parse_rom(xml_element &root) {
foreach(leaf, root.element) {
if(leaf.name == "map") {
Mapping m(memory::cartrom);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "mode") xml_parse_mode(m, attr->content);
if(attr->name == "offset") m.offset = strhex(attr->content);
if(attr->name == "size") m.size = strhex(attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
if(attr.name == "mode") xml_parse_mode(m, attr.content);
if(attr.name == "offset") m.offset = strhex(attr.content);
if(attr.name == "size") m.size = strhex(attr.content);
}
mapping.add(m);
}
}
}
void Cartridge::xml_parse_ram(xml_element *root) {
foreach(attr, root->attribute) {
if(attr->name == "size") ram_size = strhex(attr->content);
void Cartridge::xml_parse_ram(xml_element &root) {
foreach(attr, root.attribute) {
if(attr.name == "size") ram_size = strhex(attr.content);
}
foreach(leaf, root->element) {
if(leaf->name == "map") {
foreach(leaf, root.element) {
if(leaf.name == "map") {
Mapping m(memory::cartram);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "mode") xml_parse_mode(m, attr->content);
if(attr->name == "offset") m.offset = strhex(attr->content);
if(attr->name == "size") m.size = strhex(attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
if(attr.name == "mode") xml_parse_mode(m, attr.content);
if(attr.name == "offset") m.offset = strhex(attr.content);
if(attr.name == "size") m.size = strhex(attr.content);
}
mapping.add(m);
}
}
}
void Cartridge::xml_parse_superfx(xml_element *root) {
void Cartridge::xml_parse_superfx(xml_element &root) {
has_superfx = true;
foreach(node, root->element) {
if(node->name == "rom") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
foreach(node, root.element) {
if(node.name == "rom") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(memory::fxrom);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "mode") xml_parse_mode(m, attr->content);
if(attr->name == "offset") m.offset = strhex(attr->content);
if(attr->name == "size") m.size = strhex(attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
if(attr.name == "mode") xml_parse_mode(m, attr.content);
if(attr.name == "offset") m.offset = strhex(attr.content);
if(attr.name == "size") m.size = strhex(attr.content);
}
mapping.add(m);
}
}
} else if(node->name == "ram") {
foreach(attr, node->attribute) {
if(attr->name == "size") ram_size = strhex(attr->content);
} else if(node.name == "ram") {
foreach(attr, node.attribute) {
if(attr.name == "size") ram_size = strhex(attr.content);
}
foreach(leaf, node->element) {
if(leaf->name == "map") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(memory::fxram);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "mode") xml_parse_mode(m, attr->content);
if(attr->name == "offset") m.offset = strhex(attr->content);
if(attr->name == "size") m.size = strhex(attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
if(attr.name == "mode") xml_parse_mode(m, attr.content);
if(attr.name == "offset") m.offset = strhex(attr.content);
if(attr.name == "size") m.size = strhex(attr.content);
}
mapping.add(m);
}
}
} else if(node->name == "mmio") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
} else if(node.name == "mmio") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(superfx);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
}
mapping.add(m);
}
@@ -166,59 +164,59 @@ void Cartridge::xml_parse_superfx(xml_element *root) {
}
}
void Cartridge::xml_parse_sa1(xml_element *root) {
void Cartridge::xml_parse_sa1(xml_element &root) {
has_sa1 = true;
foreach(node, root->element) {
if(node->name == "rom") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
foreach(node, root.element) {
if(node.name == "rom") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(memory::vsprom);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "mode") xml_parse_mode(m, attr->content);
if(attr->name == "offset") m.offset = strhex(attr->content);
if(attr->name == "size") m.size = strhex(attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
if(attr.name == "mode") xml_parse_mode(m, attr.content);
if(attr.name == "offset") m.offset = strhex(attr.content);
if(attr.name == "size") m.size = strhex(attr.content);
}
mapping.add(m);
}
}
} else if(node->name == "iram") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
} else if(node.name == "iram") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(memory::cpuiram);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "mode") xml_parse_mode(m, attr->content);
if(attr->name == "offset") m.offset = strhex(attr->content);
if(attr->name == "size") m.size = strhex(attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
if(attr.name == "mode") xml_parse_mode(m, attr.content);
if(attr.name == "offset") m.offset = strhex(attr.content);
if(attr.name == "size") m.size = strhex(attr.content);
}
mapping.add(m);
}
}
} else if(node->name == "bwram") {
foreach(attr, node->attribute) {
if(attr->name == "size") ram_size = strhex(attr->content);
} else if(node.name == "bwram") {
foreach(attr, node.attribute) {
if(attr.name == "size") ram_size = strhex(attr.content);
}
foreach(leaf, node->element) {
if(leaf->name == "map") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(memory::cc1bwram);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "mode") xml_parse_mode(m, attr->content);
if(attr->name == "offset") m.offset = strhex(attr->content);
if(attr->name == "size") m.size = strhex(attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
if(attr.name == "mode") xml_parse_mode(m, attr.content);
if(attr.name == "offset") m.offset = strhex(attr.content);
if(attr.name == "size") m.size = strhex(attr.content);
}
mapping.add(m);
}
}
} else if(node->name == "mmio") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
} else if(node.name == "mmio") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(sa1);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
}
mapping.add(m);
}
@@ -227,27 +225,27 @@ void Cartridge::xml_parse_sa1(xml_element *root) {
}
}
void Cartridge::xml_parse_bsx(xml_element *root) {
foreach(node, root->element) {
if(node->name == "slot") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
void Cartridge::xml_parse_bsx(xml_element &root) {
foreach(node, root.element) {
if(node.name == "slot") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(memory::bsxflash);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "mode") xml_parse_mode(m, attr->content);
if(attr->name == "offset") m.offset = strhex(attr->content);
if(attr->name == "size") m.size = strhex(attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
if(attr.name == "mode") xml_parse_mode(m, attr.content);
if(attr.name == "offset") m.offset = strhex(attr.content);
if(attr.name == "size") m.size = strhex(attr.content);
}
mapping.add(m);
}
}
} else if(node->name == "mmio") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
} else if(node.name == "mmio") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(bsxcart);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
}
mapping.add(m);
}
@@ -256,40 +254,40 @@ void Cartridge::xml_parse_bsx(xml_element *root) {
}
}
void Cartridge::xml_parse_sufamiturbo(xml_element *root) {
foreach(node, root->element) {
if(node->name == "slot") {
void Cartridge::xml_parse_sufamiturbo(xml_element &root) {
foreach(node, root.element) {
if(node.name == "slot") {
bool slotid = 0;
foreach(attr, node->attribute) {
if(attr->name == "id") {
if(attr->content == "A") slotid = 0;
if(attr->content == "B") slotid = 1;
foreach(attr, node.attribute) {
if(attr.name == "id") {
if(attr.content == "A") slotid = 0;
if(attr.content == "B") slotid = 1;
}
}
foreach(slot, node->element) {
if(slot->name == "rom") {
foreach(leaf, slot->element) {
if(leaf->name == "map") {
foreach(slot, node.element) {
if(slot.name == "rom") {
foreach(leaf, slot.element) {
if(leaf.name == "map") {
Mapping m(slotid == 0 ? memory::stArom : memory::stBrom);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "mode") xml_parse_mode(m, attr->content);
if(attr->name == "offset") m.offset = strhex(attr->content);
if(attr->name == "size") m.size = strhex(attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
if(attr.name == "mode") xml_parse_mode(m, attr.content);
if(attr.name == "offset") m.offset = strhex(attr.content);
if(attr.name == "size") m.size = strhex(attr.content);
}
if(m.memory->size() > 0) mapping.add(m);
}
}
} else if(slot->name == "ram") {
foreach(leaf, slot->element) {
if(leaf->name == "map") {
} else if(slot.name == "ram") {
foreach(leaf, slot.element) {
if(leaf.name == "map") {
Mapping m(slotid == 0 ? memory::stAram : memory::stBram);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "mode") xml_parse_mode(m, attr->content);
if(attr->name == "offset") m.offset = strhex(attr->content);
if(attr->name == "size") m.size = strhex(attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
if(attr.name == "mode") xml_parse_mode(m, attr.content);
if(attr.name == "offset") m.offset = strhex(attr.content);
if(attr.name == "size") m.size = strhex(attr.content);
}
if(m.memory->size() > 0) mapping.add(m);
}
@@ -300,21 +298,21 @@ void Cartridge::xml_parse_sufamiturbo(xml_element *root) {
}
}
void Cartridge::xml_parse_supergameboy(xml_element *root) {
foreach(attr, root->attribute) {
if(attr->name == "revision") {
if(attr->content == "1") supergameboy_version = SuperGameBoyVersion::Version1;
if(attr->content == "2") supergameboy_version = SuperGameBoyVersion::Version2;
void Cartridge::xml_parse_supergameboy(xml_element &root) {
foreach(attr, root.attribute) {
if(attr.name == "revision") {
if(attr.content == "1") supergameboy_version = SuperGameBoyVersion::Version1;
if(attr.content == "2") supergameboy_version = SuperGameBoyVersion::Version2;
}
}
foreach(node, root->element) {
if(node->name == "mmio") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
foreach(node, root.element) {
if(node.name == "mmio") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m((Memory&)supergameboy);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
}
mapping.add(m);
}
@@ -323,16 +321,16 @@ void Cartridge::xml_parse_supergameboy(xml_element *root) {
}
}
void Cartridge::xml_parse_srtc(xml_element *root) {
void Cartridge::xml_parse_srtc(xml_element &root) {
has_srtc = true;
foreach(node, root->element) {
if(node->name == "mmio") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
foreach(node, root.element) {
if(node.name == "mmio") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(srtc);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
}
mapping.add(m);
}
@@ -341,26 +339,26 @@ void Cartridge::xml_parse_srtc(xml_element *root) {
}
}
void Cartridge::xml_parse_sdd1(xml_element *root) {
void Cartridge::xml_parse_sdd1(xml_element &root) {
has_sdd1 = true;
foreach(node, root->element) {
if(node->name == "mcu") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
foreach(node, root.element) {
if(node.name == "mcu") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m((Memory&)sdd1);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
}
mapping.add(m);
}
}
} else if(node->name == "mmio") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
} else if(node.name == "mmio") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m((MMIO&)sdd1);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
}
mapping.add(m);
}
@@ -369,66 +367,66 @@ void Cartridge::xml_parse_sdd1(xml_element *root) {
}
}
void Cartridge::xml_parse_spc7110(xml_element *root) {
void Cartridge::xml_parse_spc7110(xml_element &root) {
has_spc7110 = true;
foreach(node, root->element) {
if(node->name == "dcu") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
foreach(node, root.element) {
if(node.name == "dcu") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(spc7110dcu);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
}
mapping.add(m);
}
}
} else if(node->name == "mcu") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
} else if(node.name == "mcu") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(spc7110mcu);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "offset") spc7110_data_rom_offset = strhex(attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
if(attr.name == "offset") spc7110_data_rom_offset = strhex(attr.content);
}
mapping.add(m);
}
}
} else if(node->name == "mmio") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
} else if(node.name == "mmio") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(spc7110);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
}
mapping.add(m);
}
}
} else if(node->name == "ram") {
foreach(attr, node->attribute) {
if(attr->name == "size") ram_size = strhex(attr->content);
} else if(node.name == "ram") {
foreach(attr, node.attribute) {
if(attr.name == "size") ram_size = strhex(attr.content);
}
foreach(leaf, node->element) {
if(leaf->name == "map") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(spc7110ram);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
if(attr->name == "mode") xml_parse_mode(m, attr->content);
if(attr->name == "offset") m.offset = strhex(attr->content);
if(attr->name == "size") m.size = strhex(attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
if(attr.name == "mode") xml_parse_mode(m, attr.content);
if(attr.name == "offset") m.offset = strhex(attr.content);
if(attr.name == "size") m.size = strhex(attr.content);
}
mapping.add(m);
}
}
} else if(node->name == "rtc") {
} else if(node.name == "rtc") {
has_spc7110rtc = true;
foreach(leaf, node->element) {
if(leaf->name == "map") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(spc7110);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
}
mapping.add(m);
}
@@ -437,16 +435,16 @@ void Cartridge::xml_parse_spc7110(xml_element *root) {
}
}
void Cartridge::xml_parse_cx4(xml_element *root) {
void Cartridge::xml_parse_cx4(xml_element &root) {
has_cx4 = true;
foreach(node, root->element) {
if(node->name == "mmio") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
foreach(node, root.element) {
if(node.name == "mmio") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(cx4);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
}
mapping.add(m);
}
@@ -455,47 +453,47 @@ void Cartridge::xml_parse_cx4(xml_element *root) {
}
}
void Cartridge::xml_parse_necdsp(xml_element *root) {
void Cartridge::xml_parse_necdsp(xml_element &root) {
unsigned program = 0;
foreach(attr, root->attribute) {
if(attr->name == "program") {
if(attr->content == "DSP-1" || attr->content == "DSP-1A" || attr->content == "DSP-1B") {
foreach(attr, root.attribute) {
if(attr.name == "program") {
if(attr.content == "DSP-1" || attr.content == "DSP-1A" || attr.content == "DSP-1B") {
program = 1;
has_dsp1 = true;
} else if(attr->content == "DSP-2") {
} else if(attr.content == "DSP-2") {
program = 2;
has_dsp2 = true;
} else if(attr->content == "DSP-3") {
} else if(attr.content == "DSP-3") {
program = 3;
has_dsp3 = true;
} else if(attr->content == "DSP-4") {
} else if(attr.content == "DSP-4") {
program = 4;
has_dsp4 = true;
}
}
}
Memory *dr[5] = { 0, &dsp1dr, &dsp2, &dsp3, &dsp4 };
Memory *sr[5] = { 0, &dsp1sr, &dsp2, &dsp3, &dsp4 };
Memory *dr[5] = { 0, &dsp1dr, &dsp2dr, &dsp3, &dsp4 };
Memory *sr[5] = { 0, &dsp1sr, &dsp2sr, &dsp3, &dsp4 };
foreach(node, root->element) {
if(node->name == "dr" && dr[program]) {
foreach(leaf, node->element) {
if(leaf->name == "map") {
foreach(node, root.element) {
if(node.name == "dr" && dr[program]) {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(*dr[program]);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
}
mapping.add(m);
}
}
} else if(node->name == "sr" && sr[program]) {
foreach(leaf, node->element) {
if(leaf->name == "map") {
} else if(node.name == "sr" && sr[program]) {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(*sr[program]);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
}
mapping.add(m);
}
@@ -504,16 +502,16 @@ void Cartridge::xml_parse_necdsp(xml_element *root) {
}
}
void Cartridge::xml_parse_obc1(xml_element *root) {
void Cartridge::xml_parse_obc1(xml_element &root) {
has_obc1 = true;
foreach(node, root->element) {
if(node->name == "mmio") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
foreach(node, root.element) {
if(node.name == "mmio") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(obc1);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
}
mapping.add(m);
}
@@ -522,15 +520,15 @@ void Cartridge::xml_parse_obc1(xml_element *root) {
}
}
void Cartridge::xml_parse_setadsp(xml_element *root) {
void Cartridge::xml_parse_setadsp(xml_element &root) {
unsigned program = 0;
foreach(attr, root->attribute) {
if(attr->name == "program") {
if(attr->content == "ST-0010") {
foreach(attr, root.attribute) {
if(attr.name == "program") {
if(attr.content == "ST-0010") {
program = 1;
has_st0010 = true;
} else if(attr->content == "ST-0011") {
} else if(attr.content == "ST-0011") {
program = 2;
has_st0011 = true;
}
@@ -539,13 +537,13 @@ void Cartridge::xml_parse_setadsp(xml_element *root) {
Memory *map[3] = { 0, &st0010, 0 };
foreach(node, root->element) {
if(node->name == "mmio" && map[program]) {
foreach(leaf, node->element) {
if(leaf->name == "map") {
foreach(node, root.element) {
if(node.name == "mmio" && map[program]) {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(*map[program]);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
}
mapping.add(m);
}
@@ -554,12 +552,12 @@ void Cartridge::xml_parse_setadsp(xml_element *root) {
}
}
void Cartridge::xml_parse_setarisc(xml_element *root) {
void Cartridge::xml_parse_setarisc(xml_element &root) {
unsigned program = 0;
foreach(attr, root->attribute) {
if(attr->name == "program") {
if(attr->content == "ST-0018") {
foreach(attr, root.attribute) {
if(attr.name == "program") {
if(attr.content == "ST-0018") {
program = 1;
has_st0018 = true;
}
@@ -568,13 +566,13 @@ void Cartridge::xml_parse_setarisc(xml_element *root) {
MMIO *map[2] = { 0, &st0018 };
foreach(node, root->element) {
if(node->name == "mmio" && map[program]) {
foreach(leaf, node->element) {
if(leaf->name == "map") {
foreach(node, root.element) {
if(node.name == "mmio" && map[program]) {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(*map[program]);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
}
mapping.add(m);
}
@@ -583,16 +581,16 @@ void Cartridge::xml_parse_setarisc(xml_element *root) {
}
}
void Cartridge::xml_parse_msu1(xml_element *root) {
void Cartridge::xml_parse_msu1(xml_element &root) {
has_msu1 = true;
foreach(node, root->element) {
if(node->name == "mmio") {
foreach(leaf, node->element) {
if(leaf->name == "map") {
foreach(node, root.element) {
if(node.name == "mmio") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(msu1);
foreach(attr, leaf->attribute) {
if(attr->name == "address") xml_parse_address(m, attr->content);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
}
mapping.add(m);
}

View File

@@ -125,7 +125,7 @@ bool Cheat::encode(string &s, unsigned addr, uint8 data, Type type) {
char t[16];
if(type == Type::ProActionReplay) {
s = sprint("$$", strhex<6>(addr), strhex<2>(data));
s = sprint(strhex<6>(addr), strhex<2>(data));
return true;
} else if(type == Type::GameGenie) {
unsigned r = addr;
@@ -141,7 +141,7 @@ bool Cheat::encode(string &s, unsigned addr, uint8 data, Type type) {
| (!!(r & 0x080000) << 5) | (!!(r & 0x040000) << 4)
| (!!(r & 0x020000) << 3) | (!!(r & 0x010000) << 2)
| (!!(r & 0x000800) << 1) | (!!(r & 0x000400) << 0);
s = sprint("$$-$", strhex<2>(data), strhex<2>(addr >> 16), strhex<4>(addr & 0xffff));
s = sprint(strhex<2>(data), strhex<2>(addr >> 16), "-", strhex<4>(addr & 0xffff));
strtr(s, "0123456789abcdef", "df4709156bc8a23e");
return true;
} else {

View File

@@ -30,4 +30,4 @@ void DSP1DR::write(unsigned addr, uint8 data) { dsp1.dsp1.setDr(data); }
uint8 DSP1SR::read(unsigned addr) { return dsp1.dsp1.getSr(); }
void DSP1SR::write(unsigned addr, uint8 data) {}
};
}

View File

@@ -4,6 +4,8 @@
namespace SNES {
DSP2 dsp2;
DSP2DR dsp2dr;
DSP2SR dsp2sr;
#include "serialization.cpp"
#include "opcodes.cpp"
@@ -141,5 +143,11 @@ void DSP2::write(unsigned addr, uint8 data) {
DSP2::DSP2() {}
DSP2::~DSP2() {}
};
uint8 DSP2DR::read(unsigned addr) { return dsp2.read(addr); }
void DSP2DR::write(unsigned addr, uint8 data) { dsp2.write(addr, data); }
uint8 DSP2SR::read(unsigned addr) { return 0x00; }
void DSP2SR::write(unsigned addr, uint8 data) {}
}

View File

@@ -1,4 +1,4 @@
class DSP2 : public Memory {
class DSP2 {
public:
struct {
bool waiting_for_command;
@@ -42,4 +42,16 @@ protected:
void op0d();
};
class DSP2DR : public Memory {
uint8 read(unsigned addr);
void write(unsigned addr, uint8 data);
};
class DSP2SR : public Memory {
uint8 read(unsigned addr);
void write(unsigned addr, uint8 data);
};
extern DSP2 dsp2;
extern DSP2DR dsp2dr;
extern DSP2SR dsp2sr;

View File

@@ -174,8 +174,6 @@ public:
template<int, int> void op_transfer_w();
void op_tcs_e();
void op_tcs_n();
void op_tsc_e();
void op_tsc_n();
void op_tsx_b();
void op_tsx_w();
void op_txs_e();

View File

@@ -153,20 +153,6 @@ L op_io_irq();
regs.s.w = regs.a.w;
}
void CPUcore::op_tsc_e() {
L op_io_irq();
regs.a.w = regs.s.w;
regs.p.n = (regs.a.l & 0x80);
regs.p.z = (regs.a.l == 0);
}
void CPUcore::op_tsc_n() {
L op_io_irq();
regs.a.w = regs.s.w;
regs.p.n = (regs.a.w & 0x8000);
regs.p.z = (regs.a.w == 0);
}
void CPUcore::op_tsx_b() {
L op_io_irq();
regs.x.l = regs.s.l;

View File

@@ -76,7 +76,7 @@ void CPUcore::initialize_opcode_table() {
opAII(0x38, flag, 0x01, 0x01)
opMF (0x39, read_addry, and)
opMII(0x3a, adjust_imm, A, -1)
opE (0x3b, tsc)
opAII(0x3b, transfer_w, S, A)
opMF (0x3c, read_addrx, bit)
opMF (0x3d, read_addrx, and)
opMF (0x3e, adjust_addrx, rol)

View File

@@ -4,11 +4,11 @@ bool CPUDebugger::property(unsigned id, string &name, string &value) {
unsigned n = 0;
//internal
if(id == n++) { name = "S-CPU MDR"; value = sprint("0x$", strhex<2>(mdr())); return true; }
if(id == n++) { name = "S-CPU MDR"; value = sprint("0x", strhex<2>(mdr())); return true; }
//$2181-2183
if(id == n++) { name = "$2181-$2183"; value = ""; return true; }
if(id == n++) { name = "WRAM Address"; value = sprint("0x$", strhex<6>(wram_address())); return true; }
if(id == n++) { name = "WRAM Address"; value = sprint("0x", strhex<6>(wram_address())); return true; }
//$4016
if(id == n++) { name = "$4016"; value = ""; return true; }
@@ -23,39 +23,39 @@ bool CPUDebugger::property(unsigned id, string &name, string &value) {
//$4201
if(id == n++) { name = "$4201"; value = ""; return true; }
if(id == n++) { name = "PIO"; value = sprint("0x$", strhex<2>(pio_bits())); return true; }
if(id == n++) { name = "PIO"; value = sprint("0x", strhex<2>(pio_bits())); return true; }
//$4202
if(id == n++) { name = "$4202"; value = ""; return true; }
if(id == n++) { name = "Multiplicand"; value = sprint("0x$", strhex<2>(multiplicand())); return true; }
if(id == n++) { name = "Multiplicand"; value = sprint("0x", strhex<2>(multiplicand())); return true; }
//$4203
if(id == n++) { name = "$4203"; value = ""; return true; }
if(id == n++) { name = "Multiplier"; value = sprint("0x$", strhex<2>(multiplier())); return true; }
if(id == n++) { name = "Multiplier"; value = sprint("0x", strhex<2>(multiplier())); return true; }
//$4204-$4205
if(id == n++) { name = "$4204-$4205"; value = ""; return true; }
if(id == n++) { name = "Dividend"; value = sprint("0x$", strhex<4>(dividend())); return true; }
if(id == n++) { name = "Dividend"; value = sprint("0x", strhex<4>(dividend())); return true; }
//$4206
if(id == n++) { name = "$4206"; value = ""; return true; }
if(id == n++) { name = "Divisor"; value = sprint("0x$", strhex<2>(divisor())); return true; }
if(id == n++) { name = "Divisor"; value = sprint("0x", strhex<2>(divisor())); return true; }
//$4207-$4208
if(id == n++) { name = "$4207-$4208"; value = ""; return true; }
if(id == n++) { name = "H-Time"; value = sprint("0x$", strhex<4>(htime())); return true; }
if(id == n++) { name = "H-Time"; value = sprint("0x", strhex<4>(htime())); return true; }
//$4209-$420a
if(id == n++) { name = "$4209-$420a"; value = ""; return true; }
if(id == n++) { name = "V-Time"; value = sprint("0x$", strhex<4>(vtime())); return true; }
if(id == n++) { name = "V-Time"; value = sprint("0x", strhex<4>(vtime())); return true; }
//$420b
if(id == n++) { name = "$420b"; value = ""; return true; }
if(id == n++) { name = "DMA Enable"; value = sprint("0x$", strhex<2>(dma_enable())); return true; }
if(id == n++) { name = "DMA Enable"; value = sprint("0x", strhex<2>(dma_enable())); return true; }
//$420c
if(id == n++) { name = "$420c"; value = ""; return true; }
if(id == n++) { name = "HDMA Enable"; value = sprint("0x$", strhex<2>(hdma_enable())); return true; }
if(id == n++) { name = "HDMA Enable"; value = sprint("0x", strhex<2>(hdma_enable())); return true; }
//$420d
if(id == n++) { name = "$420d"; value = ""; return true; }
@@ -72,25 +72,25 @@ bool CPUDebugger::property(unsigned id, string &name, string &value) {
if(id == n++) { name = "Transfer Mode"; value = dma_transfer_mode(i); return true; }
//$43x1
if(id == n++) { name = "B-Bus Address"; value = sprint("0x$", strhex<4>(dma_bbus_address(i))); return true; }
if(id == n++) { name = "B-Bus Address"; value = sprint("0x", strhex<4>(dma_bbus_address(i))); return true; }
//$43x2-$43x3
if(id == n++) { name = "A-Bus Address"; value = sprint("0x$", strhex<4>(dma_abus_address(i))); return true; }
if(id == n++) { name = "A-Bus Address"; value = sprint("0x", strhex<4>(dma_abus_address(i))); return true; }
//$43x4
if(id == n++) { name = "A-Bus Bank"; value = sprint("0x$", strhex<2>(dma_abus_bank(i))); return true; }
if(id == n++) { name = "A-Bus Bank"; value = sprint("0x", strhex<2>(dma_abus_bank(i))); return true; }
//$43x5-$43x6
if(id == n++) { name = "Transfer Size / Indirect Address"; value = sprint("0x$", strhex<4>(dma_transfer_size(i))); return true; }
if(id == n++) { name = "Transfer Size / Indirect Address"; value = sprint("0x", strhex<4>(dma_transfer_size(i))); return true; }
//$43x7
if(id == n++) { name = "Indirect Bank"; value = sprint("0x$", strhex<2>(dma_indirect_bank(i))); return true; }
if(id == n++) { name = "Indirect Bank"; value = sprint("0x", strhex<2>(dma_indirect_bank(i))); return true; }
//$43x8-$43x9
if(id == n++) { name = "Table Address"; value = sprint("0x$", strhex<4>(dma_table_address(i))); return true; }
if(id == n++) { name = "Table Address"; value = sprint("0x", strhex<4>(dma_table_address(i))); return true; }
//$43xa
if(id == n++) { name = "Line Counter"; value = sprint("0x$", strhex<2>(dma_line_counter(i))); return true; }
if(id == n++) { name = "Line Counter"; value = sprint("0x", strhex<2>(dma_line_counter(i))); return true; }
}
return false;

View File

@@ -17,8 +17,8 @@ bool sCPU::dma_addr_valid(uint32 abus) {
}
uint8 sCPU::dma_read(uint32 abus) {
if(dma_addr_valid(abus) == false) return 0x00; //does not return S-CPU MDR
return bus.read(abus);
if(dma_addr_valid(abus) == false) return regs.mdr = 0x00;
return regs.mdr = bus.read(abus);
}
void sCPU::dma_transfer(bool direction, uint8 bbus, uint32 abus) {
@@ -106,17 +106,17 @@ uint8 sCPU::dma_enabled_channels() {
void sCPU::dma_run() {
dma_add_clocks(8);
cycle_edge();
dma_edge();
for(unsigned i = 0; i < 8; i++) {
if(channel[i].dma_enabled == false) continue;
dma_add_clocks(8);
cycle_edge();
dma_edge();
unsigned index = 0;
do {
dma_transfer(channel[i].direction, dma_bbus(i, index++), dma_addr(i));
cycle_edge();
dma_edge();
} while(channel[i].dma_enabled && --channel[i].xfersize);
channel[i].dma_enabled = false;

View File

@@ -2,22 +2,25 @@
void sCPU::op_io() {
status.clock_count = 6;
cycle_edge();
dma_edge();
add_clocks(6);
alu_edge();
}
uint8 sCPU::op_read(uint32 addr) {
status.clock_count = speed(addr);
cycle_edge();
dma_edge();
add_clocks(status.clock_count - 4);
regs.mdr = bus.read(addr);
add_clocks(4);
alu_edge();
return regs.mdr;
}
void sCPU::op_write(uint32 addr, uint8 data) {
alu_edge();
status.clock_count = speed(addr);
cycle_edge();
dma_edge();
add_clocks(status.clock_count);
bus.write(addr, regs.mdr = data);
}

View File

@@ -39,9 +39,11 @@ void sCPU::mmio_w2183(uint8 data) {
//strobing $4016.d0 affects both controller port latches.
//$4017 bit 0 writes are ignored.
void sCPU::mmio_w4016(uint8 data) {
status.joypad_strobe_latch = !!(data & 1);
bool old_latch = status.joypad_strobe_latch;
bool new_latch = data & 1;
status.joypad_strobe_latch = new_latch;
if(status.joypad_strobe_latch == 1) {
if(old_latch != new_latch) {
input.poll();
}
}
@@ -49,9 +51,6 @@ void sCPU::mmio_w4016(uint8 data) {
//JOYSER0
//7-2 = MDR
//1-0 = Joypad serial data
//
//TODO: test whether strobe latch of zero returns
//realtime or buffered status of joypadN.b
uint8 sCPU::mmio_r4016() {
uint8 r = regs.mdr & 0xfc;
r |= input.port_read(0) & 3;
@@ -89,12 +88,14 @@ void sCPU::mmio_w4202(uint8 data) {
//WRMPYB
void sCPU::mmio_w4203(uint8 data) {
status.wrmpyb = data;
status.r4216 = 0;
status.rdmpy = 0;
if(alu.mpyctr || alu.divctr) return;
//perform multiplication over the next 8 cycles (+1 to skip this cycle)
status.wrmpyctr = 9;
status.wrdivctr = 0;
status.wrmpyb = data;
status.rddiv = (status.wrmpyb << 8) | status.wrmpya;
alu.mpyctr = 8; //perform multiplication over the next eight cycles
alu.shift = status.wrmpyb;
}
//WRDIVL
@@ -109,12 +110,13 @@ void sCPU::mmio_w4205(uint8 data) {
//WRDIVB
void sCPU::mmio_w4206(uint8 data) {
status.wrdivb = data;
status.r4216 = status.wrdiva;
status.rdmpy = status.wrdiva;
if(alu.mpyctr || alu.divctr) return;
//perform division over the next 16 cycles (+1 to skip this cycle)
status.wrdivctr = 17;
status.wrmpyctr = 0;
status.wrdivb = data;
alu.divctr = 16; //perform division over the next sixteen cycles
alu.shift = status.wrdivb << 16;
}
//HTIMEL
@@ -209,22 +211,22 @@ uint8 sCPU::mmio_r4213() {
//RDDIVL
uint8 sCPU::mmio_r4214() {
return status.r4214;
return status.rddiv;
}
//RDDIVH
uint8 sCPU::mmio_r4215() {
return status.r4214 >> 8;
return status.rddiv >> 8;
}
//RDMPYL
uint8 sCPU::mmio_r4216() {
return status.r4216;
return status.rdmpy;
}
//RDMPYH
uint8 sCPU::mmio_r4217() {
return status.r4216 >> 8;
return status.rdmpy >> 8;
}
//TODO: handle reads during joypad polling (v=225-227)
@@ -390,12 +392,10 @@ void sCPU::mmio_reset() {
//$4202-$4203
status.wrmpya = 0xff;
status.wrmpyb = 0xff;
status.wrmpyctr = 0;
//$4204-$4206
status.wrdiva = 0xffff;
status.wrdivb = 0xff;
status.wrdivctr = 0;
//$4207-$420a
status.hirq_pos = 0x01ff;
@@ -405,8 +405,8 @@ void sCPU::mmio_reset() {
status.rom_speed = 8;
//$4214-$4217
status.r4214 = 0x0000;
status.r4216 = 0x0000;
status.rddiv = 0x0000;
status.rdmpy = 0x0000;
//$4218-$421f
status.joy1l = 0x00;
@@ -417,19 +417,24 @@ void sCPU::mmio_reset() {
status.joy3h = 0x00;
status.joy4l = 0x00;
status.joy4h = 0x00;
//ALU
alu.mpyctr = 0;
alu.divctr = 0;
alu.shift = 0;
}
uint8 sCPU::mmio_read(unsigned addr) {
addr &= 0xffff;
//APU
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
scheduler.sync_cpusmp();
return smp.port_read(addr & 3);
}
//DMA
if((addr & 0xff80) == 0x4300) { //$4300-$437f
if((addr & 0xff80) == 0x4300) { //$4300-$437f
unsigned i = (addr >> 4) & 7;
switch(addr & 0xf) {
case 0x0: return mmio_r43x0(i);
@@ -444,10 +449,10 @@ uint8 sCPU::mmio_read(unsigned addr) {
case 0x9: return mmio_r43x9(i);
case 0xa: return mmio_r43xa(i);
case 0xb: return mmio_r43xb(i);
case 0xc: return regs.mdr; //unmapped
case 0xd: return regs.mdr; //unmapped
case 0xe: return regs.mdr; //unmapped
case 0xf: return mmio_r43xb(i); //mirror of $43xb
case 0xc: return regs.mdr; //unmapped
case 0xd: return regs.mdr; //unmapped
case 0xe: return regs.mdr; //unmapped
case 0xf: return mmio_r43xb(i); //mirror of $43xb
}
}
@@ -480,14 +485,14 @@ void sCPU::mmio_write(unsigned addr, uint8 data) {
addr &= 0xffff;
//APU
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
if((addr & 0xffc0) == 0x2140) { //$2140-$217f
scheduler.sync_cpusmp();
port_write(addr & 3, data);
return;
}
//DMA
if((addr & 0xff80) == 0x4300) { //$4300-$437f
if((addr & 0xff80) == 0x4300) { //$4300-$437f
unsigned i = (addr >> 4) & 7;
switch(addr & 0xf) {
case 0x0: mmio_w43x0(i, data); return;
@@ -502,10 +507,10 @@ void sCPU::mmio_write(unsigned addr, uint8 data) {
case 0x9: mmio_w43x9(i, data); return;
case 0xa: mmio_w43xa(i, data); return;
case 0xb: mmio_w43xb(i, data); return;
case 0xc: return; //unmapped
case 0xd: return; //unmapped
case 0xe: return; //unmapped
case 0xf: mmio_w43xb(i, data); return; //mirror of $43xb
case 0xc: return; //unmapped
case 0xd: return; //unmapped
case 0xe: return; //unmapped
case 0xf: mmio_w43xb(i, data); return; //mirror of $43xb
}
}
@@ -515,7 +520,7 @@ void sCPU::mmio_write(unsigned addr, uint8 data) {
case 0x2182: mmio_w2182(data); return;
case 0x2183: mmio_w2183(data); return;
case 0x4016: mmio_w4016(data); return;
case 0x4017: return; //unmapped
case 0x4017: return; //unmapped
case 0x4200: mmio_w4200(data); return;
case 0x4201: mmio_w4201(data); return;
case 0x4202: mmio_w4202(data); return;

View File

@@ -19,7 +19,10 @@ public:
unsigned clock_count;
unsigned line_clocks;
//======
//timing
//======
bool irq_lock;
unsigned dram_refresh_position;
@@ -37,7 +40,10 @@ public:
bool reset_pending;
//===
//DMA
//===
bool dma_active;
unsigned dma_counter;
unsigned dma_clocks;
@@ -45,7 +51,9 @@ public:
bool hdma_pending;
bool hdma_mode; //0 = init, 1 = run
//====
//MMIO
//====
//$2181-$2183
uint32 wram_addr;
@@ -66,12 +74,10 @@ public:
//$4202-$4203
uint8 wrmpya;
uint8 wrmpyb;
unsigned wrmpyctr;
//$4204-$4206
uint16 wrdiva;
uint8 wrdivb;
unsigned wrdivctr;
//$4207-$420a
uint16 hirq_pos, virq_pos;
@@ -80,8 +86,8 @@ public:
unsigned rom_speed;
//$4214-$4217
uint16 r4214;
uint16 r4216;
uint16 rddiv;
uint16 rdmpy;
//$4218-$421f
uint8 joy1l, joy1h;
@@ -90,6 +96,12 @@ public:
uint8 joy4l, joy4h;
} status;
struct ALU {
unsigned mpyctr;
unsigned divctr;
unsigned shift;
} alu;
void power();
void reset();

View File

@@ -51,19 +51,17 @@ void sCPU::serialize(serializer &s) {
s.integer(status.wrmpya);
s.integer(status.wrmpyb);
s.integer(status.wrmpyctr);
s.integer(status.wrdiva);
s.integer(status.wrdivb);
s.integer(status.wrdivctr);
s.integer(status.hirq_pos);
s.integer(status.virq_pos);
s.integer(status.rom_speed);
s.integer(status.r4214);
s.integer(status.r4216);
s.integer(status.rddiv);
s.integer(status.rdmpy);
s.integer(status.joy1l);
s.integer(status.joy1h);
@@ -74,6 +72,10 @@ void sCPU::serialize(serializer &s) {
s.integer(status.joy4l);
s.integer(status.joy4h);
s.integer(alu.mpyctr);
s.integer(alu.divctr);
s.integer(alu.shift);
for(unsigned i = 0; i < 8; i++) {
s.integer(channel[i].dma_enabled);
s.integer(channel[i].hdma_enabled);

View File

@@ -52,37 +52,26 @@ void sCPU::scanline() {
}
}
//used to test for ALU and H/DMA, which can trigger on the edge of every opcode cycle
void sCPU::cycle_edge() {
//===
//ALU
//===
if(status.wrmpyctr) {
//MUL performs eight iterations; but because cycle_edge() is called after $4203 write,
//a ninth iteration is added and ignored. counter is inverted to indicate shift position
if(--status.wrmpyctr < 8) {
unsigned shift = 7 - status.wrmpyctr;
if((status.wrmpya >> shift) & 1) status.r4216 += status.wrmpyb << shift;
}
void sCPU::alu_edge() {
if(alu.mpyctr) {
alu.mpyctr--;
if(status.rddiv & 1) status.rdmpy += alu.shift;
status.rddiv >>= 1;
alu.shift <<= 1;
}
if(status.wrdivctr) {
//same as MUL; but with sixteen iterations, and counter is not inverted
if(--status.wrdivctr < 16) {
unsigned shift = status.wrdivctr;
status.r4214 <<= 1;
if(status.r4216 >= (status.wrdivb << shift)) {
status.r4216 -= (status.wrdivb << shift);
status.r4214 |= 1;
}
if(alu.divctr) {
alu.divctr--;
status.rddiv <<= 1;
alu.shift >>= 1;
if(status.rdmpy >= alu.shift) {
status.rdmpy -= alu.shift;
status.rddiv |= 1;
}
}
}
//====
//HDMA
//====
void sCPU::dma_edge() {
while(cycle_edge_state) {
switch(bit::lowest(cycle_edge_state)) {
case EventFlagHdmaInit: {

View File

@@ -17,7 +17,8 @@
void add_clocks(unsigned clocks);
void scanline();
alwaysinline void cycle_edge();
alwaysinline void alu_edge();
alwaysinline void dma_edge();
alwaysinline void last_cycle();
void timing_power();

View File

@@ -7,17 +7,17 @@ bool DSPDebugger::property(unsigned id, string &name, string &value) {
if(id == n++) { name = "Main Volume - Right"; value = main_volume_right(); return true; }
if(id == n++) { name = "Echo Volume - Left"; value = echo_volume_left(); return true; }
if(id == n++) { name = "Echo Volume - Right"; value = echo_volume_right(); return true; }
if(id == n++) { name = "Key On"; value = sprint("0x$", strhex<2>(key_on())); return true; }
if(id == n++) { name = "Key Off"; value = sprint("0x$", strhex<2>(key_off())); return true; }
if(id == n++) { name = "Key On"; value = sprint("0x", strhex<2>(key_on())); return true; }
if(id == n++) { name = "Key Off"; value = sprint("0x", strhex<2>(key_off())); return true; }
if(id == n++) { name = "Flag - Reset"; value = flag_reset(); return true; }
if(id == n++) { name = "Flag - Mute"; value = flag_mute(); return true; }
if(id == n++) { name = "Flag - Echo Disable"; value = flag_echo_disable(); return true; }
if(id == n++) { name = "Flag - Noise Clock"; value = flag_noise_clock(); return true; }
if(id == n++) { name = "Source End Block"; value = source_end_block(); return true; }
if(id == n++) { name = "Echo Feedback"; value = echo_feedback(); return true; }
if(id == n++) { name = "Pitch Modulation Enable"; value = sprint("0x$", strhex<2>(pitch_modulation_enable())); return true; }
if(id == n++) { name = "Noise Enable"; value = sprint("0x$", strhex<2>(noise_enable())); return true; }
if(id == n++) { name = "Echo Enable"; value = sprint("0x$", strhex<2>(echo_enable())); return true; }
if(id == n++) { name = "Pitch Modulation Enable"; value = sprint("0x", strhex<2>(pitch_modulation_enable())); return true; }
if(id == n++) { name = "Noise Enable"; value = sprint("0x", strhex<2>(noise_enable())); return true; }
if(id == n++) { name = "Echo Enable"; value = sprint("0x", strhex<2>(echo_enable())); return true; }
if(id == n++) { name = "Source Directory"; value = source_directory(); return true; }
if(id == n++) { name = "Echo Start Address"; value = echo_start_address(); return true; }
if(id == n++) { name = "Echo Directory"; value = echo_directory(); return true; }
@@ -25,7 +25,7 @@ bool DSPDebugger::property(unsigned id, string &name, string &value) {
for(unsigned i = 0; i < 8; i++) {
if(id == n++) {
name = string() << "Coefficient " << i;
value = sprint("0x$", strhex<2>(echo_filter_coefficient(i)));
value = sprint("0x", strhex<2>(echo_filter_coefficient(i)));
return true;
}
}
@@ -39,7 +39,7 @@ bool DSPDebugger::property(unsigned id, string &name, string &value) {
if(id == n++) { name = "Volume - Left"; value = voice_volume_left(i); return true; }
if(id == n++) { name = "Volume - Right"; value = voice_volume_right(i); return true; }
if(id == n++) { name = "Pitch Height"; value = sprint("0x$", strhex<4>(voice_pitch_height(i))); return true; }
if(id == n++) { name = "Pitch Height"; value = sprint("0x", strhex<4>(voice_pitch_height(i))); return true; }
if(id == n++) { name = "Source Number"; value = voice_source_number(i); return true; }
if(id == n++) { name = "ADSR1"; value = voice_adsr1(i); return true; }
if(id == n++) { name = "ADSR2"; value = voice_adsr2(i); return true; }

View File

@@ -5,6 +5,15 @@
#endif
namespace SNES {
typedef int8_t int8;
typedef int16_t int16;
typedef int32_t int32;
typedef int64_t int64;
typedef uint8_t uint8;
typedef uint16_t uint16;
typedef uint32_t uint32;
typedef uint64_t uint64;
struct ChipDebugger {
virtual bool property(unsigned id, string &name, string &value) = 0;
};

View File

@@ -2,8 +2,8 @@
#define NALL_ANY_HPP
#include <typeinfo>
#include <type_traits>
#include <nall/static.hpp>
#include <nall/traits.hpp>
namespace nall {
class any {
@@ -13,8 +13,8 @@ namespace nall {
template<typename T> any& operator=(const T& value_) {
typedef typename static_if<
is_array<T>::value,
typename remove_extent<typename add_const<T>::type>::type*,
std::is_array<T>::value,
typename std::remove_extent<typename std::add_const<T>::type>::type*,
T
>::type auto_t;
@@ -49,13 +49,13 @@ namespace nall {
};
template<typename T> T any_cast(any &value) {
typedef typename remove_reference<T>::type nonref;
typedef typename std::remove_reference<T>::type nonref;
if(value.type() != typeid(nonref)) throw;
return static_cast<any::holder<nonref>*>(value.container)->value;
}
template<typename T> T any_cast(const any &value) {
typedef const typename remove_reference<T>::type nonref;
typedef const typename std::remove_reference<T>::type nonref;
if(value.type() != typeid(nonref)) throw;
return static_cast<any::holder<nonref>*>(value.container)->value;
}

View File

@@ -3,10 +3,11 @@
#include <stdlib.h>
#include <initializer_list>
#include <type_traits>
#include <utility>
#include <nall/algorithm.hpp>
#include <nall/bit.hpp>
#include <nall/concept.hpp>
#include <nall/traits.hpp>
namespace nall {
//dynamic vector array
@@ -81,7 +82,7 @@ namespace nall {
return *this;
}
array(const array &source) : pool(0) {
array(const array &source) : pool(0), poolsize(0), buffersize(0) {
operator=(source);
}
@@ -92,11 +93,12 @@ namespace nall {
poolsize = source.poolsize;
buffersize = source.buffersize;
source.pool = 0;
source.reset();
return *this;
}
array(array &&source) {
operator=(move(source));
array(array &&source) : pool(0), poolsize(0), buffersize(0) {
operator=(std::move(source));
}
//index

View File

@@ -6,9 +6,9 @@
for(unsigned foreach_counter = 0, foreach_limit = foreach_size(object), foreach_once = 0, foreach_broken = 0; foreach_counter < foreach_limit && foreach_broken == 0; foreach_counter++, foreach_once = 0) \
for(auto &iter = object[foreach_counter]; foreach_once == 0 && (foreach_broken = 1); foreach_once++, foreach_broken = 0)
#include <type_traits>
#include <nall/concept.hpp>
#include <nall/static.hpp>
#include <nall/traits.hpp>
namespace nall {
template<typename T> unsigned foreach_size(const T& object, typename mp_enable_if<has_count<T>>::type = 0) {
@@ -23,8 +23,8 @@ namespace nall {
return object.size();
}
template<typename T> unsigned foreach_size(const T& object, typename mp_enable_if<is_array<T>>::type = 0) {
return sizeof(T) / sizeof(typename remove_extent<T>::type);
template<typename T> unsigned foreach_size(const T& object, typename mp_enable_if<std::is_array<T>>::type = 0) {
return sizeof(T) / sizeof(typename std::remove_extent<T>::type);
}
}

View File

@@ -1,190 +1,102 @@
#ifndef NALL_FUNCTION_HPP
#define NALL_FUNCTION_HPP
#include <assert.h>
//prologue
#define TN typename
#include <functional>
#include <type_traits>
namespace nall {
template<typename T> class function;
}
//parameters = 0
#define cat(n) n
#define TL typename R
#define PL
#define CL
#include "function.hpp"
//parameters = 1
#define cat(n) , n
#define TL TN R, TN P1
#define PL P1 p1
#define CL p1
#include "function.hpp"
//parameters = 2
#define cat(n) , n
#define TL TN R, TN P1, TN P2
#define PL P1 p1, P2 p2
#define CL p1, p2
#include "function.hpp"
//parameters = 3
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3
#define PL P1 p1, P2 p2, P3 p3
#define CL p1, p2, p3
#include "function.hpp"
//parameters = 4
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4
#define PL P1 p1, P2 p2, P3 p3, P4 p4
#define CL p1, p2, p3, p4
#include "function.hpp"
//parameters = 5
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5
#define CL p1, p2, p3, p4, p5
#include "function.hpp"
//parameters = 6
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6
#define CL p1, p2, p3, p4, p5, p6
#include "function.hpp"
//parameters = 7
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6, TN P7
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7
#define CL p1, p2, p3, p4, p5, p6, p7
#include "function.hpp"
//parameters = 8
#define cat(n) , n
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6, TN P7, TN P8
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8
#define CL p1, p2, p3, p4, p5, p6, p7, p8
#include "function.hpp"
//epilogue
#undef TN
#define NALL_FUNCTION_T
#elif !defined(NALL_FUNCTION_T)
//function implementation template class
namespace nall {
template<TL>
class function<R (PL)> {
template<typename R, typename... P>
class function<R (P...)> {
private:
struct base1 { virtual void func1(PL) {} };
struct base2 { virtual void func2(PL) {} };
struct base1 { virtual void func1(P...) {} };
struct base2 { virtual void func2(P...) {} };
struct derived : base1, virtual base2 {};
struct data_t {
R (*fn_call)(const data_t& cat(PL));
R (*callback)(const data_t&, P...);
union {
R (*fn_global)(PL);
R (*callback_global)(P...);
struct {
R (derived::*fn_member)(PL);
R (derived::*callback_member)(P...);
void *object;
};
};
} data;
static R fn_call_global(const data_t &d cat(PL)) {
return d.fn_global(CL);
static R callback_global(const data_t &data, P... p) {
return data.callback_global(p...);
}
template<typename C>
static R fn_call_member(const data_t &d cat(PL)) {
return (((C*)d.object)->*((R (C::*&)(PL))d.fn_member))(CL);
static R callback_member(const data_t &data, P... p) {
return (((C*)data.object)->*((R (C::*&)(P...))data.callback_member))(p...);
}
public:
R operator()(PL) const { return data.fn_call(data cat(CL)); }
operator bool() const { return data.fn_call; }
R operator()(P... p) const { return data.callback(data, p...); }
operator bool() const { return data.callback; }
void reset() { data.callback = 0; }
function() { data.fn_call = 0; }
function(void *fn) {
data.fn_call = fn ? &fn_call_global : 0;
data.fn_global = (R (*)(PL))fn;
}
function(R (*fn)(PL)) {
data.fn_call = &fn_call_global;
data.fn_global = fn;
}
template<typename C>
function(R (C::*fn)(PL), C *obj) {
data.fn_call = &fn_call_member<C>;
(R (C::*&)(PL))data.fn_member = fn;
assert(sizeof data.fn_member >= sizeof fn);
data.object = obj;
}
template<typename C>
function(R (C::*fn)(PL) const, C *obj) {
data.fn_call = &fn_call_member<C>;
(R (C::*&)(PL))data.fn_member = (R (C::*&)(PL))fn;
assert(sizeof data.fn_member >= sizeof fn);
data.object = obj;
}
function& operator=(void *fn) { return operator=(function(fn)); }
function& operator=(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); return *this; }
function(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); }
function(const function &source) { operator=(source); }
//no pointer
function() {
data.callback = 0;
}
//symbolic link pointer (nall/dl.hpp::sym, etc)
function(void *callback) {
data.callback = callback ? &callback_global : 0;
data.callback_global = (R (*)(P...))callback;
}
//global function pointer
function(R (*callback)(P...)) {
data.callback = &callback_global;
data.callback_global = callback;
}
//member function pointer
template<typename C>
function(R (C::*callback)(P...), C *object) {
static_assert(sizeof data.callback_member >= sizeof callback, "callback_member is too small");
data.callback = &callback_member<C>;
(R (C::*&)(P...))data.callback_member = callback;
data.object = object;
}
//const member function pointer
template<typename C>
function(R (C::*callback)(P...) const, C *object) {
static_assert(sizeof data.callback_member >= sizeof callback, "callback_member is too small");
data.callback = &callback_member<C>;
(R (C::*&)(P...))data.callback_member = (R (C::*&)(P...))callback;
data.object = object;
}
//lambda function pointer
template<typename T>
function(T callback) {
static_assert(std::is_same<R, typename std::result_of<T(P...)>::type>::value, "lambda mismatch");
data.callback = &callback_global;
data.callback_global = (R (*)(P...))callback;
}
};
template<TL>
function<R (PL)> bind(R (*fn)(PL)) {
return function<R (PL)>(fn);
//bind functions to ease construction and assignment of function() with more than one argument
template<typename C, typename R, typename... P>
function<R (P...)> bind(R (C::*callback)(P...), C *object) {
return function<R (P...)>(callback, object);
}
template<typename C, TL>
function<R (PL)> bind(R (C::*fn)(PL), C *obj) {
return function<R (PL)>(fn, obj);
}
template<typename C, TL>
function<R (PL)> bind(R (C::*fn)(PL) const, C *obj) {
return function<R (PL)>(fn, obj);
template<typename C, typename R, typename... P>
function<R (P...)> bind(R (C::*callback)(P...) const, C *object) {
return function<R (P...)>(callback, object);
}
}
#undef cat
#undef TL
#undef PL
#undef CL
#endif

View File

@@ -1,8 +1,9 @@
#ifndef NALL_SERIALIZER_HPP
#define NALL_SERIALIZER_HPP
#include <type_traits>
#include <utility>
#include <nall/stdint.hpp>
#include <nall/traits.hpp>
#include <nall/utility.hpp>
namespace nall {
@@ -16,6 +17,7 @@ namespace nall {
//caveats:
//- only plain-old-data can be stored. complex classes must provide serialize(serializer&);
//- floating-point usage is not portable across platforms
class serializer {
public:
enum mode_t { Load, Save, Size };
@@ -51,7 +53,7 @@ namespace nall {
}
template<typename T> void integer(T &value) {
enum { size = is_bool<T>::value ? 1 : sizeof(T) };
enum { size = std::is_same<bool, T>::value ? 1 : sizeof(T) };
if(imode == Save) {
for(unsigned n = 0; n < size; n++) idata[isize++] = value >> (n << 3);
} else if(imode == Load) {
@@ -63,7 +65,7 @@ namespace nall {
}
template<typename T> void array(T &array) {
enum { size = sizeof(T) / sizeof(typename remove_extent<T>::type) };
enum { size = sizeof(T) / sizeof(typename std::remove_extent<T>::type) };
for(unsigned n = 0; n < size; n++) integer(array[n]);
}
@@ -102,7 +104,7 @@ namespace nall {
}
serializer(serializer &&s) {
operator=(move(s));
operator=(std::move(s));
}
//construction

View File

@@ -10,42 +10,13 @@
#include <nall/utf8.hpp>
#include <nall/vector.hpp>
inline char chrlower(char c);
inline char chrupper(char c);
inline int stricmp(const char *dest, const char *src);
inline int strpos (const char *str, const char *key);
inline int qstrpos(const char *str, const char *key);
inline bool strbegin (const char *str, const char *key);
inline bool stribegin(const char *str, const char *key);
inline bool strend (const char *str, const char *key);
inline bool striend(const char *str, const char *key);
inline char* strlower(char *str);
inline char* strupper(char *str);
inline char* strtr(char *dest, const char *before, const char *after);
inline uintmax_t strhex (const char *str);
inline intmax_t strsigned (const char *str);
inline uintmax_t strunsigned(const char *str);
inline uintmax_t strbin (const char *str);
inline double strdouble (const char *str);
inline bool match(const char *pattern, const char *str);
inline bool strint (const char *str, int &result);
inline bool strmath(const char *str, int &result);
inline size_t strlcpy(char *dest, const char *src, size_t length);
inline size_t strlcat(char *dest, const char *src, size_t length);
inline char* ltrim(char *str, const char *key = " ");
inline char* rtrim(char *str, const char *key = " ");
inline char* trim (char *str, const char *key = " ");
inline char* ltrim_once(char *str, const char *key = " ");
inline char* rtrim_once(char *str, const char *key = " ");
inline char* trim_once (char *str, const char *key = " ");
namespace nall {
class string;
template<typename T> inline string to_string(T);
class string {
public:
inline void reserve(size_t);
inline void reserve(unsigned);
inline unsigned length() const;
inline string& assign(const char*);
@@ -78,7 +49,7 @@ namespace nall {
protected:
char *data;
size_t size;
unsigned size;
#if defined(QT_CORE_LIB)
public:
@@ -98,29 +69,69 @@ namespace nall {
lstring(std::initializer_list<string>);
};
template<typename... Args> inline string sprint(const char *s, Args... args);
template<typename... Args> inline void print(const char *s, Args... args);
//compare.hpp
inline char chrlower(char c);
inline char chrupper(char c);
inline int stricmp(const char *dest, const char *src);
inline int strpos (const char *str, const char *key);
inline int qstrpos(const char *str, const char *key);
inline bool strbegin (const char *str, const char *key);
inline bool stribegin(const char *str, const char *key);
inline bool strend (const char *str, const char *key);
inline bool striend(const char *str, const char *key);
//convert.hpp
inline char* strlower(char *str);
inline char* strupper(char *str);
inline char* strtr(char *dest, const char *before, const char *after);
inline uintmax_t strhex (const char *str);
inline intmax_t strsigned (const char *str);
inline uintmax_t strunsigned(const char *str);
inline uintmax_t strbin (const char *str);
inline double strdouble (const char *str);
//match.hpp
inline bool match(const char *pattern, const char *str);
//math.hpp
inline bool strint (const char *str, int &result);
inline bool strmath(const char *str, int &result);
//strl.hpp
inline unsigned strlcpy(char *dest, const char *src, unsigned length);
inline unsigned strlcat(char *dest, const char *src, unsigned length);
//trim.hpp
inline char* ltrim(char *str, const char *key = " ");
inline char* rtrim(char *str, const char *key = " ");
inline char* trim (char *str, const char *key = " ");
inline char* ltrim_once(char *str, const char *key = " ");
inline char* rtrim_once(char *str, const char *key = " ");
inline char* trim_once (char *str, const char *key = " ");
//utility.hpp
inline unsigned strlcpy(string &dest, const char *src, unsigned length);
inline unsigned strlcat(string &dest, const char *src, unsigned length);
inline string substr(const char *src, unsigned start = 0, unsigned length = 0);
inline string& strlower(string &str);
inline string& strupper(string &str);
inline string& strtr(string &dest, const char *before, const char *after);
inline string& ltrim(string &str, const char *key = " ");
inline string& rtrim(string &str, const char *key = " ");
inline string& trim (string &str, const char *key = " ");
inline string& ltrim_once(string &str, const char *key = " ");
inline string& rtrim_once(string &str, const char *key = " ");
inline string& trim_once (string &str, const char *key = " ");
template<unsigned length = 0, char padding = '0'> inline string strhex(uintmax_t value);
template<unsigned length = 0, char padding = '0'> inline string strsigned(intmax_t value);
template<unsigned length = 0, char padding = '0'> inline string strunsigned(uintmax_t value);
template<unsigned length = 0, char padding = '0'> inline string strbin(uintmax_t value);
inline unsigned strdouble(char *str, double value);
inline string strdouble(double value);
//variadic.hpp
template<typename... Args> inline string sprint(Args... args);
template<typename... Args> inline void print(Args... args);
};
inline size_t strlcpy(nall::string &dest, const char *src, size_t length);
inline size_t strlcat(nall::string &dest, const char *src, size_t length);
inline nall::string& strlower(nall::string &str);
inline nall::string& strupper(nall::string &str);
inline nall::string& strtr(nall::string &dest, const char *before, const char *after);
inline nall::string& ltrim(nall::string &str, const char *key = " ");
inline nall::string& rtrim(nall::string &str, const char *key = " ");
inline nall::string& trim (nall::string &str, const char *key = " ");
inline nall::string& ltrim_once(nall::string &str, const char *key = " ");
inline nall::string& rtrim_once(nall::string &str, const char *key = " ");
inline nall::string& trim_once (nall::string &str, const char *key = " ");
inline nall::string substr(const char *src, size_t start = 0, size_t length = 0);
template<unsigned length = 0, char padding = '0'> inline nall::string strhex(uintmax_t value);
template<unsigned length = 0, char padding = '0'> inline nall::string strsigned(intmax_t value);
template<unsigned length = 0, char padding = '0'> inline nall::string strunsigned(uintmax_t value);
template<unsigned length = 0, char padding = '0'> inline nall::string strbin(uintmax_t value);
inline size_t strdouble(char *str, double value);
inline nall::string strdouble(double value);
#endif

View File

@@ -2,28 +2,31 @@
#define NALL_STRING_CAST_HPP
namespace nall {
//this is needed, as C++0x does not support explicit template specialization inside classes
template<> inline string to_string<bool> (bool v) { return v ? "true" : "false"; }
template<> inline string to_string<signed int> (signed int v) { return strsigned(v); }
template<> inline string to_string<unsigned int> (unsigned int v) { return strunsigned(v); }
template<> inline string to_string<double> (double v) { return strdouble(v); }
template<> inline string to_string<char*> (char *v) { return v; }
template<> inline string to_string<const char*> (const char *v) { return v; }
template<> inline string to_string<string> (string v) { return v; }
template<> inline string to_string<const string&>(const string &v) { return v; }
template<typename T> string& string::operator= (T value) { return assign(to_string<T>(value)); }
template<typename T> string& string::operator<<(T value) { return append(to_string<T>(value)); }
//this is needed, as C++0x does not support explicit template specialization inside classes
template<> inline string to_string<bool> (bool v) { return v ? "true" : "false"; }
template<> inline string to_string<signed int> (signed int v) { return strsigned(v); }
template<> inline string to_string<unsigned int> (unsigned int v) { return strunsigned(v); }
template<> inline string to_string<double> (double v) { return strdouble(v); }
template<> inline string to_string<char*> (char *v) { return v; }
template<> inline string to_string<const char*> (const char *v) { return v; }
template<> inline string to_string<string> (string v) { return v; }
template<> inline string to_string<const string&>(const string &v) { return v; }
template<typename T> lstring& lstring::operator<<(T value) {
operator[](size()).assign(to_string<T>(value));
return *this;
}
template<typename T> string& string::operator= (T value) { return assign(to_string<T>(value)); }
template<typename T> string& string::operator<<(T value) { return append(to_string<T>(value)); }
template<typename T> lstring& lstring::operator<<(T value) {
operator[](size()).assign(to_string<T>(value));
return *this;
}
#if defined(QT_CORE_LIB)
template<> inline string to_string<QString>(QString v) { return v.toUtf8().constData(); }
template<> inline string to_string<const QString&>(const QString &v) { return v.toUtf8().constData(); }
string::operator QString() const { return QString::fromUtf8(*this); }
#endif
#if defined(QT_CORE_LIB)
template<> inline string to_string<const QString&>(const QString &v) { return v.toUtf8().constData(); }
string::operator QString() const { return QString::fromUtf8(*this); }
#endif
}
#endif

View File

@@ -1,6 +1,8 @@
#ifndef NALL_STRING_COMPARE_HPP
#define NALL_STRING_COMPARE_HPP
namespace nall {
char chrlower(char c) {
return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c;
}
@@ -97,4 +99,6 @@ bool striend(const char *str, const char *key) {
return true;
}
}
#endif

View File

@@ -1,6 +1,8 @@
#ifndef NALL_STRING_CONVERT_HPP
#define NALL_STRING_CONVERT_HPP
namespace nall {
char* strlower(char *str) {
if(!str) return 0;
int i = 0;
@@ -146,4 +148,6 @@ double strdouble(const char *str) {
return !negate ? result : -result;
}
}
#endif

View File

@@ -3,7 +3,7 @@
namespace nall {
void string::reserve(size_t size_) {
void string::reserve(unsigned size_) {
if(size_ > size) {
size = size_;
data = (char*)realloc(data, size + 1);
@@ -81,6 +81,7 @@ string& string::operator=(string &&source) {
size = source.size;
data = source.data;
source.data = 0;
source.size = 0;
return *this;
}
@@ -94,12 +95,12 @@ bool string::readfile(const char *filename) {
#if !defined(_WIN32)
FILE *fp = fopen(filename, "rb");
#else
FILE *fp = _wfopen(nall::utf16_t(filename), L"rb");
FILE *fp = _wfopen(utf16_t(filename), L"rb");
#endif
if(!fp) return false;
fseek(fp, 0, SEEK_END);
size_t size = ftell(fp);
unsigned size = ftell(fp);
rewind(fp);
char *fdata = new char[size + 1];
unsigned unused = fread(fdata, 1, size, fp);

View File

@@ -2,59 +2,60 @@
#define NALL_FILENAME_HPP
namespace nall {
// "foo/bar.c" -> "foo/", "bar.c" -> "./"
inline string dir(char const *name) {
string result = name;
for(signed i = strlen(result); i >= 0; i--) {
if(result[i] == '/' || result[i] == '\\') {
result[i + 1] = 0;
break;
}
if(i == 0) result = "./";
}
return result;
}
// "foo/bar.c" -> "bar.c"
inline string notdir(char const *name) {
for(signed i = strlen(name); i >= 0; i--) {
if(name[i] == '/' || name[i] == '\\') {
name += i + 1;
break;
}
// "foo/bar.c" -> "foo/", "bar.c" -> "./"
inline string dir(char const *name) {
string result = name;
for(signed i = strlen(result); i >= 0; i--) {
if(result[i] == '/' || result[i] == '\\') {
result[i + 1] = 0;
break;
}
string result = name;
return result;
if(i == 0) result = "./";
}
return result;
}
// "foo/bar.c" -> "foo/bar"
inline string basename(char const *name) {
string result = name;
for(signed i = strlen(result); i >= 0; i--) {
if(result[i] == '/' || result[i] == '\\') {
//file has no extension
break;
}
if(result[i] == '.') {
result[i] = 0;
break;
}
// "foo/bar.c" -> "bar.c"
inline string notdir(char const *name) {
for(signed i = strlen(name); i >= 0; i--) {
if(name[i] == '/' || name[i] == '\\') {
name += i + 1;
break;
}
return result;
}
string result = name;
return result;
}
// "foo/bar.c" -> "c"
inline string extension(char const *name) {
for(signed i = strlen(name); i >= 0; i--) {
if(name[i] == '.') {
name += i + 1;
break;
}
// "foo/bar.c" -> "foo/bar"
inline string basename(char const *name) {
string result = name;
for(signed i = strlen(result); i >= 0; i--) {
if(result[i] == '/' || result[i] == '\\') {
//file has no extension
break;
}
if(result[i] == '.') {
result[i] = 0;
break;
}
string result = name;
return result;
}
return result;
}
// "foo/bar.c" -> "c"
inline string extension(char const *name) {
for(signed i = strlen(name); i >= 0; i--) {
if(name[i] == '.') {
name += i + 1;
break;
}
}
string result = name;
return result;
}
}
#endif

View File

@@ -1,6 +1,8 @@
#ifndef NALL_STRING_MATCH_HPP
#define NALL_STRING_MATCH_HPP
namespace nall {
bool match(const char *p, const char *s) {
const char *p_ = 0, *s_ = 0;
@@ -69,4 +71,6 @@ bool match(const char *p, const char *s) {
}
}
}
#endif

View File

@@ -1,6 +1,8 @@
#ifndef NALL_STRING_MATH_HPP
#define NALL_STRING_MATH_HPP
namespace nall {
static int eval_integer(const char *&s) {
if(!*s) throw "unrecognized_integer";
int value = 0, x = *s, y = *(s + 1);
@@ -157,4 +159,6 @@ bool strmath(const char *s, int &result) {
}
}
}
#endif

View File

@@ -1,13 +1,15 @@
#ifndef NALL_STRING_STRL_HPP
#define NALL_STRING_STRL_HPP
namespace nall {
//strlcpy, strlcat based on OpenBSD implementation by Todd C. Miller
//return = strlen(src)
size_t strlcpy(char *dest, const char *src, size_t length) {
unsigned strlcpy(char *dest, const char *src, unsigned length) {
char *d = dest;
const char *s = src;
size_t n = length;
unsigned n = length;
if(n) {
while(--n && (*d++ = *s++)); //copy as many bytes as possible, or until null terminator reached
@@ -22,13 +24,13 @@ size_t strlcpy(char *dest, const char *src, size_t length) {
}
//return = strlen(src) + min(length, strlen(dest))
size_t strlcat(char *dest, const char *src, size_t length) {
unsigned strlcat(char *dest, const char *src, unsigned length) {
char *d = dest;
const char *s = src;
size_t n = length;
unsigned n = length;
while(n-- && *d) d++; //find end of dest
size_t dlength = d - dest;
unsigned dlength = d - dest;
n = length - dlength; //subtract length of dest from maximum string length
if(!n) return dlength + strlen(s);
@@ -45,4 +47,6 @@ size_t strlcat(char *dest, const char *src, size_t length) {
return dlength + (s - src); //return length of resulting string, sans null terminator
}
}
#endif

View File

@@ -1,6 +1,8 @@
#ifndef NALL_STRING_TRIM_HPP
#define NALL_STRING_TRIM_HPP
namespace nall {
char* ltrim(char *str, const char *key) {
if(!key || !*key) return str;
while(strbegin(str, key)) {
@@ -47,4 +49,6 @@ char* trim_once(char *str, const char *key) {
return ltrim_once(rtrim_once(str, key), key);
}
}
#endif

View File

@@ -1,18 +1,20 @@
#ifndef NALL_STRING_UTILITY_HPP
#define NALL_STRING_UTILITY_HPP
size_t strlcpy(nall::string &dest, const char *src, size_t length) {
namespace nall {
unsigned strlcpy(string &dest, const char *src, unsigned length) {
dest.reserve(length);
return strlcpy(dest(), src, length);
}
size_t strlcat(nall::string &dest, const char *src, size_t length) {
unsigned strlcat(string &dest, const char *src, unsigned length) {
dest.reserve(length);
return strlcat(dest(), src, length);
}
nall::string substr(const char *src, size_t start, size_t length) {
nall::string dest;
string substr(const char *src, unsigned start, unsigned length) {
string dest;
if(length == 0) {
//copy entire string
dest = src + start;
@@ -23,22 +25,22 @@ nall::string substr(const char *src, size_t start, size_t length) {
return dest;
}
/* very simplistic wrappers to return nall::string& instead of char* type */
/* very simplistic wrappers to return string& instead of char* type */
nall::string& strlower(nall::string &str) { strlower(str()); return str; }
nall::string& strupper(nall::string &str) { strupper(str()); return str; }
nall::string& strtr(nall::string &dest, const char *before, const char *after) { strtr(dest(), before, after); return dest; }
nall::string& ltrim(nall::string &str, const char *key) { ltrim(str(), key); return str; }
nall::string& rtrim(nall::string &str, const char *key) { rtrim(str(), key); return str; }
nall::string& trim (nall::string &str, const char *key) { trim (str(), key); return str; }
nall::string& ltrim_once(nall::string &str, const char *key) { ltrim_once(str(), key); return str; }
nall::string& rtrim_once(nall::string &str, const char *key) { rtrim_once(str(), key); return str; }
nall::string& trim_once (nall::string &str, const char *key) { trim_once (str(), key); return str; }
string& strlower(string &str) { strlower(str()); return str; }
string& strupper(string &str) { strupper(str()); return str; }
string& strtr(string &dest, const char *before, const char *after) { strtr(dest(), before, after); return dest; }
string& ltrim(string &str, const char *key) { ltrim(str(), key); return str; }
string& rtrim(string &str, const char *key) { rtrim(str(), key); return str; }
string& trim (string &str, const char *key) { trim (str(), key); return str; }
string& ltrim_once(string &str, const char *key) { ltrim_once(str(), key); return str; }
string& rtrim_once(string &str, const char *key) { rtrim_once(str(), key); return str; }
string& trim_once (string &str, const char *key) { trim_once (str(), key); return str; }
/* arithmetic <> string */
template<unsigned length, char padding> nall::string strhex(uintmax_t value) {
nall::string output;
template<unsigned length, char padding> string strhex(uintmax_t value) {
string output;
unsigned offset = 0;
//render string backwards, as we do not know its length yet
@@ -61,8 +63,8 @@ template<unsigned length, char padding> nall::string strhex(uintmax_t value) {
return output;
}
template<unsigned length, char padding> nall::string strsigned(intmax_t value) {
nall::string output;
template<unsigned length, char padding> string strsigned(intmax_t value) {
string output;
unsigned offset = 0;
bool negative = value < 0;
@@ -87,8 +89,8 @@ template<unsigned length, char padding> nall::string strsigned(intmax_t value) {
return output;
}
template<unsigned length, char padding> nall::string strunsigned(uintmax_t value) {
nall::string output;
template<unsigned length, char padding> string strunsigned(uintmax_t value) {
string output;
unsigned offset = 0;
do {
@@ -109,8 +111,8 @@ template<unsigned length, char padding> nall::string strunsigned(uintmax_t value
return output;
}
template<unsigned length, char padding> nall::string strbin(uintmax_t value) {
nall::string output;
template<unsigned length, char padding> string strbin(uintmax_t value) {
string output;
unsigned offset = 0;
do {
@@ -134,7 +136,7 @@ template<unsigned length, char padding> nall::string strbin(uintmax_t value) {
//using sprintf is certainly not the most ideal method to convert
//a double to a string ... but attempting to parse a double by
//hand, digit-by-digit, results in subtle rounding errors.
size_t strdouble(char *str, double value) {
unsigned strdouble(char *str, double value) {
char buffer[256];
sprintf(buffer, "%f", value);
@@ -155,11 +157,13 @@ size_t strdouble(char *str, double value) {
return length + 1;
}
nall::string strdouble(double value) {
nall::string temp;
string strdouble(double value) {
string temp;
temp.reserve(strdouble(0, value));
strdouble(temp(), value);
return temp;
}
}
#endif

View File

@@ -2,36 +2,26 @@
#define NALL_STRING_VARIADIC_HPP
namespace nall {
static void sprint(string &output, unsigned &offset, const char *&s) {
while(*s) output[offset++] = *s++;
}
template<typename T, typename... Args>
static void sprint(string &output, unsigned &offset, const char *&s, T value, Args... args) {
while(*s) {
if(*s == '$') {
string data = to_string<T>(value);
unsigned i = 0;
while(data[i]) output[offset++] = data[i++];
sprint(output, offset, ++s, args...);
return;
} else {
output[offset++] = *s++;
}
}
}
static void isprint(string &output) {
}
template<typename... Args> inline string sprint(const char *s, Args... args) {
string output;
unsigned offset = 0;
sprint(output, offset, s, args...);
output[offset] = 0;
return output;
}
template<typename T, typename... Args>
static void isprint(string &output, T value, Args... args) {
output << to_string<T>(value);
isprint(output, args...);
}
template<typename... Args> inline string sprint(Args... args) {
string output;
isprint(output, args...);
return output;
}
template<typename... Args> inline void print(Args... args) {
printf("%s", (const char*)sprint(args...));
}
template<typename... Args> inline void print(const char *s, Args... args) {
printf("%s", (const char*)sprint(s, args...));
}
}
#endif

View File

@@ -2,9 +2,7 @@
#define NALL_STRING_XML_HPP
//XML subset parser
//version 0.04
#include <nall/array.hpp>
//version 0.05
namespace nall {
@@ -16,15 +14,14 @@ struct xml_attribute {
struct xml_element : xml_attribute {
string parse() const;
array<xml_attribute*> attribute;
array<xml_element*> element;
~xml_element();
linear_vector<xml_attribute> attribute;
linear_vector<xml_element> element;
protected:
void parse_doctype(const char *&data);
bool parse_head(string data);
bool parse_body(const char *&data);
friend xml_element *xml_parse(const char *data);
friend xml_element xml_parse(const char *data);
};
inline string xml_attribute::parse() const {
@@ -134,11 +131,11 @@ inline bool xml_element::parse_head(string data) {
side.qsplit("=", part[i]);
if(side.size() != 2) throw "...";
xml_attribute *attr = new xml_attribute;
attr->name = side[0];
attr->content = side[1];
if(strbegin(attr->content, "\"") && strend(attr->content, "\"")) trim_once(attr->content, "\"");
else if(strbegin(attr->content, "'") && strend(attr->content, "'")) trim_once(attr->content, "'");
xml_attribute attr;
attr.name = side[0];
attr.content = side[1];
if(strbegin(attr.content, "\"") && strend(attr.content, "\"")) trim_once(attr.content, "\"");
else if(strbegin(attr.content, "'") && strend(attr.content, "'")) trim_once(attr.content, "'");
else throw "...";
attribute.add(attr);
}
@@ -191,10 +188,8 @@ inline bool xml_element::parse_body(const char *&data) {
while(*data) {
unsigned index = element.size();
xml_element *elem = new xml_element;
if(elem->parse_body(data) == false) {
delete elem;
xml_element node;
if(node.parse_body(data) == false) {
if(*data == '/') {
signed length = data - content_begin - 1;
if(length > 0) content = substr(content_begin, 0, length);
@@ -216,23 +211,18 @@ inline bool xml_element::parse_body(const char *&data) {
return true;
}
} else {
element.add(elem);
element.add(node);
}
}
}
}
inline xml_element::~xml_element() {
for(unsigned i = 0; i < attribute.size(); i++) delete attribute[i];
for(unsigned i = 0; i < element.size(); i++) delete element[i];
}
//ensure there is only one root element
inline bool xml_validate(xml_element *document) {
inline bool xml_validate(xml_element &document) {
unsigned root_counter = 0;
for(unsigned i = 0; i < document->element.size(); i++) {
string &name = document->element[i]->name;
for(unsigned i = 0; i < document.element.size(); i++) {
string &name = document.element[i].name;
if(strbegin(name, "?")) continue;
if(strbegin(name, "!")) continue;
if(++root_counter > 1) return false;
@@ -241,25 +231,24 @@ inline bool xml_validate(xml_element *document) {
return true;
}
inline xml_element* xml_parse(const char *data) {
xml_element *self = new xml_element;
inline xml_element xml_parse(const char *data) {
xml_element self;
try {
while(*data) {
xml_element *elem = new xml_element;
if(elem->parse_body(data) == false) {
delete elem;
xml_element node;
if(node.parse_body(data) == false) {
break;
} else {
self->element.add(elem);
self.element.add(node);
}
}
if(xml_validate(self) == false) throw "...";
return self;
} catch(const char*) {
delete self;
return 0;
xml_element empty;
return empty;
}
}

View File

@@ -1,97 +0,0 @@
#ifndef NALL_TRAITS_HPP
#define NALL_TRAITS_HPP
namespace nall {
//==
//is
//==
template<typename T> struct is_integral { enum { value = false }; };
template<> struct is_integral<bool> { enum { value = true }; };
template<> struct is_integral<char> { enum { value = true }; };
template<> struct is_integral<signed char> { enum { value = true }; };
template<> struct is_integral<unsigned char> { enum { value = true }; };
template<> struct is_integral<wchar_t> { enum { value = true }; };
template<> struct is_integral<short> { enum { value = true }; };
template<> struct is_integral<unsigned short> { enum { value = true }; };
template<> struct is_integral<long> { enum { value = true }; };
template<> struct is_integral<unsigned long> { enum { value = true }; };
template<> struct is_integral<long long> { enum { value = true }; };
template<> struct is_integral<unsigned long long> { enum { value = true }; };
template<> struct is_integral<int> { enum { value = true }; };
template<> struct is_integral<unsigned int> { enum { value = true }; };
template<typename T> struct is_floating_point { enum { value = false }; };
template<> struct is_floating_point<float> { enum { value = true }; };
template<> struct is_floating_point<double> { enum { value = true }; };
template<> struct is_floating_point<long double> { enum { value = true }; };
template<typename T> struct is_bool { enum { value = false }; };
template<> struct is_bool<bool> { enum { value = true }; };
template<typename T> struct is_void { enum { value = false }; };
template<> struct is_void<void> { enum { value = true }; };
template<typename T> struct is_arithmetic {
enum { value = is_integral<T>::value || is_floating_point<T>::value };
};
template<typename T> struct is_fundamental {
enum { value = is_integral<T>::value || is_floating_point<T>::value || is_void<T>::value };
};
template<typename T> struct is_compound {
enum { value = !is_fundamental<T>::value };
};
template<typename T> struct is_array { enum { value = false }; };
template<typename T> struct is_array<T[]> { enum { value = true }; };
template<typename T, int N> struct is_array<T[N]> { enum { value = true }; };
template<typename T> struct is_const { enum { value = false }; };
template<typename T> struct is_const<const T> { enum { value = true }; };
template<typename T> struct is_const<const T&> { enum { value = true }; };
template<typename T> struct is_pointer { enum { value = false }; };
template<typename T> struct is_pointer<T*> { enum { value = true }; };
template<typename T> struct is_reference { enum { value = false }; };
template<typename T> struct is_reference<T&> { enum { value = true }; };
template<typename T, typename U> struct is_same { enum { value = false }; };
template<typename T> struct is_same<T, T> { enum { value = true }; };
//===
//add
//===
template<typename T> struct add_const { typedef const T type; };
template<typename T> struct add_const<const T> { typedef const T type; };
template<typename T> struct add_const<const T&> { typedef const T& type; };
template<typename T> struct add_pointer { typedef T* type; };
template<typename T> struct add_pointer<T*> { typedef T** type; };
template<typename T> struct add_reference { typedef T& type; };
template<typename T> struct add_reference<T&> { typedef T& type; };
//======
//remove
//======
template<typename T> struct remove_const { typedef T type; };
template<typename T> struct remove_const<const T> { typedef T type; };
template<typename T> struct remove_const<const T&> { typedef T type; };
template<typename T> struct remove_extent { typedef T type; };
template<typename T> struct remove_extent<T[]> { typedef T type; };
template<typename T, int N> struct remove_extent<T[N]> { typedef T type; };
template<typename T> struct remove_pointer { typedef T type; };
template<typename T> struct remove_pointer<T*> { typedef T type; };
template<typename T> struct remove_reference { typedef T type; };
template<typename T> struct remove_reference<T&> { typedef T type; };
}
#endif

View File

@@ -1,29 +1,18 @@
#ifndef NALL_UTILITY_HPP
#define NALL_UTILITY_HPP
#include <nall/traits.hpp>
#include <type_traits>
#include <utility>
namespace nall {
template<typename T> struct identity {
typedef T type;
};
template<typename T> typename remove_reference<T>::type&& move(T &&value) {
return value;
}
template<typename T> T&& forward(typename identity<T>::type &&value) {
return value;
}
template<bool C, typename T = bool> struct enable_if { typedef T type; };
template<typename T> struct enable_if<false, T> {};
template<typename C, typename T = bool> struct mp_enable_if : enable_if<C::value, T> {};
template<typename T> inline void swap(T &x, T &y) {
T temp(move(x));
x = move(y);
y = move(temp);
T temp(std::move(x));
x = std::move(y);
y = std::move(temp);
}
template<typename T> struct base_from_member {

View File

@@ -3,10 +3,11 @@
#include <initializer_list>
#include <new>
#include <type_traits>
#include <utility>
#include <nall/algorithm.hpp>
#include <nall/bit.hpp>
#include <nall/concept.hpp>
#include <nall/traits.hpp>
#include <nall/utility.hpp>
namespace nall {
@@ -86,11 +87,12 @@ namespace nall {
inline linear_vector<T>& operator=(const linear_vector<T> &source) {
reset();
reserve(source.capacity());
for(unsigned i = 0; i < source.size(); i++) add(source[i]);
resize(source.size());
for(unsigned i = 0; i < source.size(); i++) operator[](i) = source.operator[](i);
return *this;
}
linear_vector(const linear_vector<T> &source) {
linear_vector(const linear_vector<T> &source) : pool(0), poolsize(0), objectsize(0) {
operator=(source);
}
@@ -101,11 +103,12 @@ namespace nall {
poolsize = source.poolsize;
objectsize = source.objectsize;
source.pool = 0;
source.reset();
return *this;
}
linear_vector(linear_vector<T> &&source) {
operator=(move(source));
linear_vector(linear_vector<T> &&source) : pool(0), poolsize(0), objectsize(0) {
operator=(std::move(source));
}
//construction
@@ -193,11 +196,12 @@ namespace nall {
inline pointer_vector<T>& operator=(const pointer_vector<T> &source) {
reset();
reserve(source.capacity());
for(unsigned i = 0; i < source.size(); i++) add(source[i]);
resize(source.size());
for(unsigned i = 0; i < source.size(); i++) operator[](i) = source.operator[](i);
return *this;
}
pointer_vector(const pointer_vector<T> &source) {
pointer_vector(const pointer_vector<T> &source) : pool(0), poolsize(0), objectsize(0) {
operator=(source);
}
@@ -208,11 +212,12 @@ namespace nall {
poolsize = source.poolsize;
objectsize = source.objectsize;
source.pool = 0;
source.reset();
return *this;
}
pointer_vector(pointer_vector<T> &&source) {
operator=(move(source));
pointer_vector(pointer_vector<T> &&source) : pool(0), poolsize(0), objectsize(0) {
operator=(std::move(source));
}
//construction

View File

@@ -46,7 +46,7 @@ unsigned MappedRAM::size() const { return size_; }
uint8 MappedRAM::read(unsigned addr) { return data_[addr]; }
void MappedRAM::write(unsigned addr, uint8 n) { if(!write_protect_) data_[addr] = n; }
const uint8 MappedRAM::operator[](unsigned addr) const { return data_[addr]; }
const uint8& MappedRAM::operator[](unsigned addr) const { return data_[addr]; }
MappedRAM::MappedRAM() : data_(0), size_(-1U), write_protect_(false) {}
//Bus

View File

@@ -48,7 +48,7 @@ struct MappedRAM : Memory {
inline uint8 read(unsigned addr);
inline void write(unsigned addr, uint8 n);
inline const uint8 operator[](unsigned addr) const;
inline const uint8& operator[](unsigned addr) const;
inline MappedRAM();
private:

Some files were not shown because too many files have changed in this diff Show More