mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-09-16 18:52:20 +02:00
Compare commits
36 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
a266a2b5e2 | ||
|
53f03be5a2 | ||
|
77375c3c68 | ||
|
dce3e61f06 | ||
|
20b44ddfd1 | ||
|
79f20030a0 | ||
|
79b939e1c7 | ||
|
3ae74ff5a5 | ||
|
7351b910c5 | ||
|
6bbb609f2f | ||
|
0d19902435 | ||
|
44bab83d68 | ||
|
42a4c1d60e | ||
|
645689e683 | ||
|
8b0153daf0 | ||
|
9ca1e259cb | ||
|
7227107d5e | ||
|
65ff00e28a | ||
|
717aa69d42 | ||
|
35fdb71f3d | ||
|
c33f70a8c6 | ||
|
0a3fdc404d | ||
|
efa7879c6d | ||
|
b11f22f517 | ||
|
9614275b34 | ||
|
9995876bc5 | ||
|
43a3991ddf | ||
|
27c24bc8a6 | ||
|
fac95dfec5 | ||
|
362542924e | ||
|
4179282244 | ||
|
02820ef2e9 | ||
|
0ecce7b93d | ||
|
f94fcd6f30 | ||
|
57f903630a | ||
|
9329de0a8d |
BIN
QtCore4.dll
BIN
QtCore4.dll
Binary file not shown.
BIN
QtGui4.dll
BIN
QtGui4.dll
Binary file not shown.
Binary file not shown.
BIN
libgomp-1.dll
BIN
libgomp-1.dll
Binary file not shown.
BIN
mingwm10.dll
BIN
mingwm10.dll
Binary file not shown.
@@ -1,17 +0,0 @@
|
||||
//CRT curvature shader
|
||||
//license: GPL
|
||||
//author: DOLLS
|
||||
|
||||
uniform sampler2D rubyTexture;
|
||||
|
||||
#define distortion 0.2
|
||||
|
||||
vec2 barrelDistortion(vec2 coord) {
|
||||
vec2 cc = coord - 0.5;
|
||||
float dist = dot(cc, cc);
|
||||
return coord + cc * (dist + distortion * dist * dist) * distortion;
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
gl_FragColor = texture2D(rubyTexture, barrelDistortion(gl_TexCoord[0].xy));
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
//HDRTV GLSL shader
|
||||
//license: GPL
|
||||
//original version by SimoneT
|
||||
//ruby port by byuu
|
||||
|
||||
uniform sampler2D rubyTexture;
|
||||
|
||||
void main(void) {
|
||||
vec4 rgb = texture2D(rubyTexture, gl_TexCoord[0].xy);
|
||||
vec4 intens = smoothstep(0.2,0.8,rgb) + normalize(vec4(rgb.xyz, 1.0));
|
||||
|
||||
if(fract(gl_FragCoord.y * 0.5) > 0.5) intens = rgb * 0.8;
|
||||
gl_FragColor = intens;
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
//HDRTV GLSL shader
|
||||
//license: GPL
|
||||
//original version by SimoneT
|
||||
//ruby port by byuu
|
||||
|
||||
void main(void) {
|
||||
gl_Position = ftransform();
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
}
|
@@ -1,25 +0,0 @@
|
||||
texture rubyTexture;
|
||||
|
||||
float4 vec;
|
||||
|
||||
sampler s0 = sampler_state { texture = <rubyTexture>; };
|
||||
float3 LightColor = { 1.0, 0.7, 0.5 };
|
||||
float3 DarkColor = { 0.2, 0.05, 0.0 };
|
||||
|
||||
float4 DiffColorPass(in float2 Tex : TEXCOORD0) : COLOR0
|
||||
{
|
||||
vec.x = 0.5;
|
||||
vec.y = 1.0;
|
||||
float3 scnColor = LightColor * tex2D(s0, Tex).xyz;
|
||||
float3 grayXfer = float3(0.3, 0.59, 0.11);
|
||||
float gray = dot(grayXfer, scnColor);
|
||||
float3 muted = lerp(scnColor, gray.xxx, vec.x);
|
||||
float3 sepia = lerp(DarkColor, LightColor, gray);
|
||||
float3 result = lerp(muted, sepia, vec.y);
|
||||
return float4(result, 1);
|
||||
}
|
||||
|
||||
Technique T0
|
||||
{
|
||||
pass p0 { PixelShader = compile ps_2_0 DiffColorPass(); }
|
||||
}
|
@@ -1,49 +0,0 @@
|
||||
//HQ2x GLSL shader
|
||||
//license: GPL
|
||||
//original version by guest(r)
|
||||
//ruby port by byuu
|
||||
|
||||
uniform sampler2D rubyTexture;
|
||||
|
||||
const float mx = 0.325; // start smoothing wt.
|
||||
const float k = -0.250; // wt. decrease factor
|
||||
const float max_w = 0.25; // max filter weigth
|
||||
const float min_w =-0.05; // min filter weigth
|
||||
const float lum_add = 0.25; // effects smoothing
|
||||
|
||||
void main() {
|
||||
vec3 c00 = texture2D(rubyTexture, gl_TexCoord[1].xy).xyz;
|
||||
vec3 c10 = texture2D(rubyTexture, gl_TexCoord[1].zw).xyz;
|
||||
vec3 c20 = texture2D(rubyTexture, gl_TexCoord[2].xy).xyz;
|
||||
vec3 c01 = texture2D(rubyTexture, gl_TexCoord[4].zw).xyz;
|
||||
vec3 c11 = texture2D(rubyTexture, gl_TexCoord[0].xy).xyz;
|
||||
vec3 c21 = texture2D(rubyTexture, gl_TexCoord[2].zw).xyz;
|
||||
vec3 c02 = texture2D(rubyTexture, gl_TexCoord[4].xy).xyz;
|
||||
vec3 c12 = texture2D(rubyTexture, gl_TexCoord[3].zw).xyz;
|
||||
vec3 c22 = texture2D(rubyTexture, gl_TexCoord[3].xy).xyz;
|
||||
vec3 dt = vec3(1.0, 1.0, 1.0);
|
||||
|
||||
float md1 = dot(abs(c00 - c22), dt);
|
||||
float md2 = dot(abs(c02 - c20), dt);
|
||||
|
||||
float w1 = dot(abs(c22 - c11), dt) * md2;
|
||||
float w2 = dot(abs(c02 - c11), dt) * md1;
|
||||
float w3 = dot(abs(c00 - c11), dt) * md2;
|
||||
float w4 = dot(abs(c20 - c11), dt) * md1;
|
||||
|
||||
float t1 = w1 + w3;
|
||||
float t2 = w2 + w4;
|
||||
float ww = max(t1, t2) + 0.0001;
|
||||
|
||||
c11 = (w1 * c00 + w2 * c20 + w3 * c22 + w4 * c02 + ww * c11) / (t1 + t2 + ww);
|
||||
|
||||
float lc1 = k / (0.12 * dot(c10 + c12 + c11, dt) + lum_add);
|
||||
float lc2 = k / (0.12 * dot(c01 + c21 + c11, dt) + lum_add);
|
||||
|
||||
w1 = clamp(lc1 * dot(abs(c11 - c10), dt) + mx, min_w, max_w);
|
||||
w2 = clamp(lc2 * dot(abs(c11 - c21), dt) + mx, min_w, max_w);
|
||||
w3 = clamp(lc1 * dot(abs(c11 - c12), dt) + mx, min_w, max_w);
|
||||
w4 = clamp(lc2 * dot(abs(c11 - c01), dt) + mx, min_w, max_w);
|
||||
|
||||
gl_FragColor.xyz = w1 * c10 + w2 * c21 + w3 * c12 + w4 * c01 + (1.0 - w1 - w2 - w3 - w4) * c11;
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
//HQ2x GLSL shader
|
||||
//license: GPL
|
||||
//original version by guest(r)
|
||||
//ruby port by byuu
|
||||
|
||||
uniform vec2 rubyTextureSize;
|
||||
|
||||
void main() {
|
||||
float x = 0.5 * (1.0 / rubyTextureSize.x);
|
||||
float y = 0.5 * (1.0 / rubyTextureSize.y);
|
||||
vec2 dg1 = vec2( x, y);
|
||||
vec2 dg2 = vec2(-x, y);
|
||||
vec2 dx = vec2(x, 0.0);
|
||||
vec2 dy = vec2(0.0, y);
|
||||
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_TexCoord[1].xy = gl_TexCoord[0].xy - dg1;
|
||||
gl_TexCoord[1].zw = gl_TexCoord[0].xy - dy;
|
||||
gl_TexCoord[2].xy = gl_TexCoord[0].xy - dg2;
|
||||
gl_TexCoord[2].zw = gl_TexCoord[0].xy + dx;
|
||||
gl_TexCoord[3].xy = gl_TexCoord[0].xy + dg1;
|
||||
gl_TexCoord[3].zw = gl_TexCoord[0].xy + dy;
|
||||
gl_TexCoord[4].xy = gl_TexCoord[0].xy + dg2;
|
||||
gl_TexCoord[4].zw = gl_TexCoord[0].xy - dx;
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
//Pixellate shader
|
||||
//license: GPL
|
||||
//author: Fes
|
||||
|
||||
uniform sampler2D rubyTexture;
|
||||
uniform vec2 rubyTextureSize;
|
||||
|
||||
void main() {
|
||||
vec2 texelSize = 1.0 / rubyTextureSize;
|
||||
|
||||
vec2 range;
|
||||
range.x = dFdx(gl_TexCoord[0].x) / 2.0 * 0.99;
|
||||
range.y = dFdy(gl_TexCoord[0].y) / 2.0 * 0.99;
|
||||
|
||||
float left = gl_TexCoord[0].x - range.x;
|
||||
float top = gl_TexCoord[0].y + range.y;
|
||||
float right = gl_TexCoord[0].x + range.x;
|
||||
float bottom = gl_TexCoord[0].y - range.y;
|
||||
|
||||
vec4 topLeftColor = texture2D(rubyTexture, (floor(vec2(left, top) / texelSize) + 0.5) * texelSize);
|
||||
vec4 bottomRightColor = texture2D(rubyTexture, (floor(vec2(right, bottom) / texelSize) + 0.5) * texelSize);
|
||||
vec4 bottomLeftColor = texture2D(rubyTexture, (floor(vec2(left, bottom) / texelSize) + 0.5) * texelSize);
|
||||
vec4 topRightColor = texture2D(rubyTexture, (floor(vec2(right, top) / texelSize) + 0.5) * texelSize);
|
||||
|
||||
vec2 border = clamp(round(gl_TexCoord[0] / texelSize) * texelSize, vec2(left, bottom), vec2(right, top));
|
||||
|
||||
float totalArea = 4.0 * range.x * range.y;
|
||||
|
||||
vec4 averageColor;
|
||||
averageColor = ((border.x - left) * (top - border.y) / totalArea) * topLeftColor;
|
||||
averageColor += ((right - border.x) * (border.y - bottom) / totalArea) * bottomRightColor;
|
||||
averageColor += ((border.x - left) * (border.y - bottom) / totalArea) * bottomLeftColor;
|
||||
averageColor += ((right - border.x) * (top - border.y) / totalArea) * topRightColor;
|
||||
|
||||
gl_FragColor = averageColor;
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
//Pixellate shader
|
||||
//license: GPL
|
||||
//author: Fes
|
||||
|
||||
void main() {
|
||||
gl_Position = ftransform();
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
}
|
@@ -1,28 +0,0 @@
|
||||
//Scale2x GLSL shader
|
||||
//license: GPL
|
||||
//original version by Pete Bernert
|
||||
//ruby port by byuu
|
||||
|
||||
uniform sampler2D rubyTexture;
|
||||
uniform vec2 rubyTextureSize;
|
||||
|
||||
void main() {
|
||||
vec4 colD, colF, colB, colH, col, tmp;
|
||||
vec2 sel;
|
||||
|
||||
col = texture2DProj(rubyTexture, gl_TexCoord[0]); //central (can be E0-E3)
|
||||
colD = texture2DProj(rubyTexture, gl_TexCoord[1]); //D (left)
|
||||
colF = texture2DProj(rubyTexture, gl_TexCoord[2]); //F (right)
|
||||
colB = texture2DProj(rubyTexture, gl_TexCoord[3]); //B (top)
|
||||
colH = texture2DProj(rubyTexture, gl_TexCoord[4]); //H (bottom)
|
||||
|
||||
sel = fract(gl_TexCoord[0].xy * rubyTextureSize.xy); //where are we (E0-E3)?
|
||||
//E0 is default
|
||||
if(sel.y >= 0.5) { tmp = colB; colB = colH; colH = tmp; } //E1 (or E3): swap B and H
|
||||
if(sel.x >= 0.5) { tmp = colF; colF = colD; colD = tmp; } //E2 (or E3): swap D and F
|
||||
|
||||
if(colB == colD && colB != colF && colD != colH) { //do the Scale2x rule
|
||||
col = colD;
|
||||
}
|
||||
|
||||
gl_FragColor = col;
|
@@ -1,28 +0,0 @@
|
||||
//Scale2x GLSL shader
|
||||
//license: GPL
|
||||
//original version by Pete Bernert
|
||||
//ruby port by byuu
|
||||
|
||||
uniform vec2 rubyTextureSize;
|
||||
|
||||
void main() {
|
||||
vec4 offsetx;
|
||||
vec4 offsety;
|
||||
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
|
||||
offsetx.x = 1.0 / rubyTextureSize.x;
|
||||
offsetx.y = 0.0;
|
||||
offsetx.w = 0.0;
|
||||
offsetx.z = 0.0;
|
||||
offsety.y = 1.0 / rubyTextureSize.y;
|
||||
offsety.x = 0.0;
|
||||
offsety.w = 0.0;
|
||||
offsety.z = 0.0;
|
||||
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0; //center
|
||||
gl_TexCoord[1] = gl_TexCoord[0] - offsetx; //left
|
||||
gl_TexCoord[2] = gl_TexCoord[0] + offsetx; //right
|
||||
gl_TexCoord[3] = gl_TexCoord[0] - offsety; //top
|
||||
gl_TexCoord[4] = gl_TexCoord[0] + offsety; //bottom
|
||||
}
|
BIN
pthreadGC2.dll
BIN
pthreadGC2.dll
Binary file not shown.
BIN
snesfilter.dll
BIN
snesfilter.dll
Binary file not shown.
@@ -20,11 +20,11 @@ void _2xSaIFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width,
|
||||
}
|
||||
|
||||
void _2xSaIFilter::render(
|
||||
uint32_t *output, unsigned outpitch, const uint16_t *input, unsigned pitch,
|
||||
const unsigned *line, unsigned width, unsigned height
|
||||
uint32_t *output, unsigned outpitch,
|
||||
const uint16_t *input, unsigned pitch, unsigned width, unsigned height
|
||||
) {
|
||||
if(width > 256 || height > 240) {
|
||||
filter_direct.render(output, outpitch, input, pitch, line, width, height);
|
||||
filter_direct.render(output, outpitch, input, pitch, width, height);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -62,11 +62,11 @@ void Super2xSaIFilter::size(unsigned &outwidth, unsigned &outheight, unsigned wi
|
||||
}
|
||||
|
||||
void Super2xSaIFilter::render(
|
||||
uint32_t *output, unsigned outpitch, const uint16_t *input, unsigned pitch,
|
||||
const unsigned *line, unsigned width, unsigned height
|
||||
uint32_t *output, unsigned outpitch,
|
||||
const uint16_t *input, unsigned pitch, unsigned width, unsigned height
|
||||
) {
|
||||
if(width > 256 || height > 240) {
|
||||
filter_direct.render(output, outpitch, input, pitch, line, width, height);
|
||||
filter_direct.render(output, outpitch, input, pitch, width, height);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -104,11 +104,11 @@ void SuperEagleFilter::size(unsigned &outwidth, unsigned &outheight, unsigned wi
|
||||
}
|
||||
|
||||
void SuperEagleFilter::render(
|
||||
uint32_t *output, unsigned outpitch, const uint16_t *input, unsigned pitch,
|
||||
const unsigned *line, unsigned width, unsigned height
|
||||
uint32_t *output, unsigned outpitch,
|
||||
const uint16_t *input, unsigned pitch, unsigned width, unsigned height
|
||||
) {
|
||||
if(width > 256 || height > 240) {
|
||||
filter_direct.render(output, outpitch, input, pitch, line, width, height);
|
||||
filter_direct.render(output, outpitch, input, pitch, width, height);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
class _2xSaIFilter {
|
||||
public:
|
||||
void size(unsigned&, unsigned&, unsigned, unsigned);
|
||||
void render(uint32_t*, unsigned, const uint16_t*, unsigned, const unsigned*, unsigned, unsigned);
|
||||
void render(uint32_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned);
|
||||
|
||||
_2xSaIFilter();
|
||||
~_2xSaIFilter();
|
||||
@@ -13,7 +13,7 @@ private:
|
||||
class Super2xSaIFilter {
|
||||
public:
|
||||
void size(unsigned&, unsigned&, unsigned, unsigned);
|
||||
void render(uint32_t*, unsigned, const uint16_t*, unsigned, const unsigned*, unsigned, unsigned);
|
||||
void render(uint32_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned);
|
||||
|
||||
Super2xSaIFilter();
|
||||
~Super2xSaIFilter();
|
||||
@@ -25,7 +25,7 @@ private:
|
||||
class SuperEagleFilter {
|
||||
public:
|
||||
void size(unsigned&, unsigned&, unsigned, unsigned);
|
||||
void render(uint32_t*, unsigned, const uint16_t*, unsigned, const unsigned*, unsigned, unsigned);
|
||||
void render(uint32_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned);
|
||||
|
||||
SuperEagleFilter();
|
||||
~SuperEagleFilter();
|
||||
|
@@ -7,24 +7,15 @@ void DirectFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width,
|
||||
|
||||
void DirectFilter::render(
|
||||
uint32_t *output, unsigned outpitch, const uint16_t *input, unsigned pitch,
|
||||
const unsigned *line, unsigned width, unsigned height
|
||||
unsigned width, unsigned height
|
||||
) {
|
||||
pitch >>= 1;
|
||||
outpitch >>= 2;
|
||||
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
if(width == 512 && line[y] == 256) {
|
||||
for(unsigned x = 0; x < 256; x++) {
|
||||
uint16_t p = *input++;
|
||||
*output++ = colortable[p];
|
||||
*output++ = colortable[p];
|
||||
}
|
||||
input += 256;
|
||||
} else {
|
||||
for(unsigned x = 0; x < width; x++) {
|
||||
uint16_t p = *input++;
|
||||
*output++ = colortable[p];
|
||||
}
|
||||
for(unsigned x = 0; x < width; x++) {
|
||||
uint16_t p = *input++;
|
||||
*output++ = colortable[p];
|
||||
}
|
||||
input += pitch - width;
|
||||
output += outpitch - width;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
class DirectFilter {
|
||||
public:
|
||||
void size(unsigned&, unsigned&, unsigned, unsigned);
|
||||
void render(uint32_t*, unsigned, const uint16_t*, unsigned, const unsigned*, unsigned, unsigned);
|
||||
void render(uint32_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned);
|
||||
} filter_direct;
|
||||
|
@@ -8,17 +8,17 @@
|
||||
#include "hq2x.hpp"
|
||||
|
||||
void HQ2xFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) {
|
||||
if(height > 240) return filter_direct.size(outwidth, outheight, width, height);
|
||||
outwidth = (width <= 256) ? width * 2 : width;
|
||||
outheight = (height <= 240) ? height * 2 : height;
|
||||
if(width > 256 || height > 240) return filter_direct.size(outwidth, outheight, width, height);
|
||||
outwidth = width * 2;
|
||||
outheight = height * 2;
|
||||
}
|
||||
|
||||
void HQ2xFilter::render(
|
||||
uint32_t *output, unsigned outpitch, const uint16_t *input, unsigned pitch,
|
||||
const unsigned *line, unsigned width, unsigned height
|
||||
uint32_t *output, unsigned outpitch,
|
||||
const uint16_t *input, unsigned pitch, unsigned width, unsigned height
|
||||
) {
|
||||
if(height > 240) {
|
||||
filter_direct.render(output, outpitch, input, pitch, line, width, height);
|
||||
if(width > 256 || height > 240) {
|
||||
filter_direct.render(output, outpitch, input, pitch, width, height);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -28,59 +28,51 @@ void HQ2xFilter::render(
|
||||
#pragma omp parallel for
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
const uint16_t *in = input + y * pitch;
|
||||
uint32_t *out0 = output + y * pitch;
|
||||
uint32_t *out1 = output + y * pitch + outpitch;
|
||||
uint32_t *out0 = output + y * outpitch * 2;
|
||||
uint32_t *out1 = output + y * outpitch * 2 + outpitch;
|
||||
|
||||
unsigned linewidth = line[y];
|
||||
int prevline = (y == 0 ? 0 : pitch);
|
||||
int nextline = (y == height - 1 ? 0 : pitch);
|
||||
|
||||
if(linewidth == 256) {
|
||||
int prevline = (y == 0) || (linewidth != line[y - 1]) ? 0 : pitch;
|
||||
int nextline = (y == height - 1) || (linewidth != line[y + 1]) ? 0 : pitch;
|
||||
in++;
|
||||
*out0++ = 0; *out0++ = 0;
|
||||
*out1++ = 0; *out1++ = 0;
|
||||
|
||||
for(unsigned x = 1; x < 256 - 1; x++) {
|
||||
uint16_t A = *(in - prevline - 1);
|
||||
uint16_t B = *(in - prevline + 0);
|
||||
uint16_t C = *(in - prevline + 1);
|
||||
uint16_t D = *(in - 1);
|
||||
uint16_t E = *(in + 0);
|
||||
uint16_t F = *(in + 1);
|
||||
uint16_t G = *(in + nextline - 1);
|
||||
uint16_t H = *(in + nextline + 0);
|
||||
uint16_t I = *(in + nextline + 1);
|
||||
uint32_t e = yuvTable[E] + diff_offset;
|
||||
|
||||
uint8_t pattern;
|
||||
pattern = diff(e, A) << 0;
|
||||
pattern |= diff(e, B) << 1;
|
||||
pattern |= diff(e, C) << 2;
|
||||
pattern |= diff(e, D) << 3;
|
||||
pattern |= diff(e, F) << 4;
|
||||
pattern |= diff(e, G) << 5;
|
||||
pattern |= diff(e, H) << 6;
|
||||
pattern |= diff(e, I) << 7;
|
||||
|
||||
*(out0 + 0) = colortable[blend(hqTable[pattern], E, A, B, D, F, H)]; pattern = rotate[pattern];
|
||||
*(out0 + 1) = colortable[blend(hqTable[pattern], E, C, F, B, H, D)]; pattern = rotate[pattern];
|
||||
*(out1 + 1) = colortable[blend(hqTable[pattern], E, I, H, F, D, B)]; pattern = rotate[pattern];
|
||||
*(out1 + 0) = colortable[blend(hqTable[pattern], E, G, D, H, B, F)];
|
||||
|
||||
in++;
|
||||
*out0++ = 0; *out0++ = 0;
|
||||
*out1++ = 0; *out1++ = 0;
|
||||
|
||||
for(unsigned x = 1; x < 256 - 1; x++) {
|
||||
uint16_t A = *(in - prevline - 1);
|
||||
uint16_t B = *(in - prevline + 0);
|
||||
uint16_t C = *(in - prevline + 1);
|
||||
uint16_t D = *(in - 1);
|
||||
uint16_t E = *(in + 0);
|
||||
uint16_t F = *(in + 1);
|
||||
uint16_t G = *(in + nextline - 1);
|
||||
uint16_t H = *(in + nextline + 0);
|
||||
uint16_t I = *(in + nextline + 1);
|
||||
uint32_t e = yuvTable[E] + diff_offset;
|
||||
|
||||
uint8_t pattern;
|
||||
pattern = diff(e, A) << 0;
|
||||
pattern |= diff(e, B) << 1;
|
||||
pattern |= diff(e, C) << 2;
|
||||
pattern |= diff(e, D) << 3;
|
||||
pattern |= diff(e, F) << 4;
|
||||
pattern |= diff(e, G) << 5;
|
||||
pattern |= diff(e, H) << 6;
|
||||
pattern |= diff(e, I) << 7;
|
||||
|
||||
*(out0 + 0) = colortable[blend(hqTable[pattern], E, A, B, D, F, H)]; pattern = rotate[pattern];
|
||||
*(out0 + 1) = colortable[blend(hqTable[pattern], E, C, F, B, H, D)]; pattern = rotate[pattern];
|
||||
*(out1 + 1) = colortable[blend(hqTable[pattern], E, I, H, F, D, B)]; pattern = rotate[pattern];
|
||||
*(out1 + 0) = colortable[blend(hqTable[pattern], E, G, D, H, B, F)];
|
||||
|
||||
in++;
|
||||
out0 += 2;
|
||||
out1 += 2;
|
||||
}
|
||||
|
||||
in++;
|
||||
*out0++ = 0; *out0++ = 0;
|
||||
*out1++ = 0; *out1++ = 0;
|
||||
} else {
|
||||
for(unsigned x = 0; x < 512; x++) {
|
||||
*out0++ = *out1++ = colortable[*in++];
|
||||
}
|
||||
out0 += 2;
|
||||
out1 += 2;
|
||||
}
|
||||
|
||||
in++;
|
||||
*out0++ = 0; *out0++ = 0;
|
||||
*out1++ = 0; *out1++ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
class HQ2xFilter {
|
||||
public:
|
||||
void size(unsigned&, unsigned&, unsigned, unsigned);
|
||||
void render(uint32_t*, unsigned, const uint16_t*, unsigned, const unsigned*, unsigned, unsigned);
|
||||
void render(uint32_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned);
|
||||
|
||||
HQ2xFilter();
|
||||
~HQ2xFilter();
|
||||
|
@@ -1,17 +1,17 @@
|
||||
#include "lq2x.hpp"
|
||||
|
||||
void LQ2xFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) {
|
||||
if(height > 240) return filter_direct.size(outwidth, outheight, width, height);
|
||||
outwidth = (width <= 256) ? width * 2 : width;
|
||||
outheight = (height <= 240) ? height * 2 : height;
|
||||
if(width > 256 || height > 240) return filter_direct.size(outwidth, outheight, width, height);
|
||||
outwidth = width * 2;
|
||||
outheight = height * 2;
|
||||
}
|
||||
|
||||
void LQ2xFilter::render(
|
||||
uint32_t *output, unsigned outpitch, const uint16_t *input, unsigned pitch,
|
||||
const unsigned *line, unsigned width, unsigned height
|
||||
uint32_t *output, unsigned outpitch,
|
||||
const uint16_t *input, unsigned pitch, unsigned width, unsigned height
|
||||
) {
|
||||
if(height > 240) {
|
||||
filter_direct.render(output, outpitch, input, pitch, line, width, height);
|
||||
if(width > 256 || height > 240) {
|
||||
filter_direct.render(output, outpitch, input, pitch, width, height);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -22,39 +22,31 @@ void LQ2xFilter::render(
|
||||
uint32_t *out1 = output + outpitch;
|
||||
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
unsigned linewidth = line[y];
|
||||
int prevline = (y == 0 ? 0 : pitch);
|
||||
int nextline = (y == height - 1 ? 0 : pitch);
|
||||
|
||||
if(linewidth == 256) {
|
||||
int prevline = (y == 0) || (linewidth != line[y - 1]) ? 0 : pitch;
|
||||
int nextline = (y == height - 1) || (linewidth != line[y + 1]) ? 0 : pitch;
|
||||
for(unsigned x = 0; x < width; x++) {
|
||||
uint16_t A = *(input - prevline);
|
||||
uint16_t B = (x > 0) ? *(input - 1) : *input;
|
||||
uint16_t C = *input;
|
||||
uint16_t D = (x < 255) ? *(input + 1) : *input;
|
||||
uint16_t E = *(input++ + nextline);
|
||||
uint32_t c = colortable[C];
|
||||
|
||||
for(unsigned x = 0; x < 256; x++) {
|
||||
uint16_t A = *(input - prevline);
|
||||
uint16_t B = (x > 0) ? *(input - 1) : *input;
|
||||
uint16_t C = *input;
|
||||
uint16_t D = (x < 255) ? *(input + 1) : *input;
|
||||
uint16_t E = *(input++ + nextline);
|
||||
uint32_t c = colortable[C];
|
||||
|
||||
if(A != E && B != D) {
|
||||
*out0++ = (A == B ? colortable[C + A - ((C ^ A) & 0x0421) >> 1] : c);
|
||||
*out0++ = (A == D ? colortable[C + A - ((C ^ A) & 0x0421) >> 1] : c);
|
||||
*out1++ = (E == B ? colortable[C + E - ((C ^ E) & 0x0421) >> 1] : c);
|
||||
*out1++ = (E == D ? colortable[C + E - ((C ^ E) & 0x0421) >> 1] : c);
|
||||
} else {
|
||||
*out0++ = c;
|
||||
*out0++ = c;
|
||||
*out1++ = c;
|
||||
*out1++ = c;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(unsigned x = 0; x < 512; x++) {
|
||||
*out0++ = *out1++ = colortable[*input++];
|
||||
if(A != E && B != D) {
|
||||
*out0++ = (A == B ? colortable[C + A - ((C ^ A) & 0x0421) >> 1] : c);
|
||||
*out0++ = (A == D ? colortable[C + A - ((C ^ A) & 0x0421) >> 1] : c);
|
||||
*out1++ = (E == B ? colortable[C + E - ((C ^ E) & 0x0421) >> 1] : c);
|
||||
*out1++ = (E == D ? colortable[C + E - ((C ^ E) & 0x0421) >> 1] : c);
|
||||
} else {
|
||||
*out0++ = c;
|
||||
*out0++ = c;
|
||||
*out1++ = c;
|
||||
*out1++ = c;
|
||||
}
|
||||
}
|
||||
|
||||
input += pitch - linewidth;
|
||||
input += pitch - width;
|
||||
out0 += outpitch + outpitch - 512;
|
||||
out1 += outpitch + outpitch - 512;
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
class LQ2xFilter {
|
||||
public:
|
||||
void size(unsigned&, unsigned&, unsigned, unsigned);
|
||||
void render(uint32_t*, unsigned, const uint16_t*, unsigned, const unsigned*, unsigned, unsigned);
|
||||
void render(uint32_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned);
|
||||
} filter_lq2x;
|
||||
|
@@ -30,7 +30,7 @@ endif
|
||||
|
||||
ifeq ($(compiler),)
|
||||
ifeq ($(platform),osx)
|
||||
compiler := gcc-4.2
|
||||
compiler := gcc-mp-4.4
|
||||
else
|
||||
compiler := gcc
|
||||
endif
|
||||
|
@@ -12,12 +12,6 @@ namespace nall {
|
||||
template<typename T, typename U> T max(const T &t, const U &u) {
|
||||
return t > u ? t : u;
|
||||
}
|
||||
|
||||
//pseudo-random number generator
|
||||
inline unsigned prng() {
|
||||
static unsigned n = 0;
|
||||
return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -3,10 +3,13 @@
|
||||
|
||||
#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>
|
||||
#include <nall/foreach.hpp>
|
||||
#include <nall/utility.hpp>
|
||||
|
||||
namespace nall {
|
||||
//dynamic vector array
|
||||
@@ -47,13 +50,32 @@ namespace nall {
|
||||
return pool;
|
||||
}
|
||||
|
||||
void add(const T data) {
|
||||
void append(const T data) {
|
||||
operator[](buffersize) = data;
|
||||
}
|
||||
|
||||
signed find(const T data) {
|
||||
for(unsigned i = 0; i < size(); i++) if(pool[i] == data) return i;
|
||||
return -1; //not found
|
||||
template<typename U> void insert(unsigned index, const U list) {
|
||||
unsigned listsize = container_size(list);
|
||||
resize(buffersize + listsize);
|
||||
memmove(pool + index + listsize, pool + index, (buffersize - index) * sizeof(T));
|
||||
foreach(item, list) pool[index++] = item;
|
||||
}
|
||||
|
||||
void insert(unsigned index, const T item) {
|
||||
insert(index, array<T>{ item });
|
||||
}
|
||||
|
||||
void remove(unsigned index, unsigned count = 1) {
|
||||
for(unsigned i = index; count + i < buffersize; i++) {
|
||||
pool[i] = pool[count + i];
|
||||
}
|
||||
if(count + index >= buffersize) resize(index); //every element >= index was removed
|
||||
else resize(buffersize - count);
|
||||
}
|
||||
|
||||
optional<unsigned> find(const T data) {
|
||||
for(unsigned i = 0; i < size(); i++) if(pool[i] == data) return { true, i };
|
||||
return { false, 0 };
|
||||
}
|
||||
|
||||
void clear() {
|
||||
@@ -64,7 +86,7 @@ namespace nall {
|
||||
}
|
||||
|
||||
array(std::initializer_list<T> list) : pool(0), poolsize(0), buffersize(0) {
|
||||
for(const T *p = list.begin(); p != list.end(); ++p) add(*p);
|
||||
for(const T *p = list.begin(); p != list.end(); ++p) append(*p);
|
||||
}
|
||||
|
||||
~array() {
|
||||
@@ -81,7 +103,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 +114,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
|
||||
|
@@ -1,6 +1,9 @@
|
||||
#ifndef NALL_CONCEPT_HPP
|
||||
#define NALL_CONCEPT_HPP
|
||||
|
||||
#include <nall/static.hpp>
|
||||
#include <nall/utility.hpp>
|
||||
|
||||
namespace nall {
|
||||
//unsigned count() const;
|
||||
template<typename T> struct has_count { enum { value = false }; };
|
||||
@@ -10,6 +13,22 @@ namespace nall {
|
||||
|
||||
//unsigned size() const;
|
||||
template<typename T> struct has_size { enum { value = false }; };
|
||||
|
||||
template<typename T> unsigned container_size(const T& object, typename mp_enable_if<has_count<T>>::type = 0) {
|
||||
return object.count();
|
||||
}
|
||||
|
||||
template<typename T> unsigned container_size(const T& object, typename mp_enable_if<has_length<T>>::type = 0) {
|
||||
return object.length();
|
||||
}
|
||||
|
||||
template<typename T> unsigned container_size(const T& object, typename mp_enable_if<has_size<T>>::type = 0) {
|
||||
return object.size();
|
||||
}
|
||||
|
||||
template<typename T> unsigned container_size(const T& object, typename mp_enable_if<std::is_array<T>>::type = 0) {
|
||||
return sizeof(T) / sizeof(typename std::remove_extent<T>::type);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -78,9 +78,8 @@ namespace nall {
|
||||
line.split("\n", data);
|
||||
|
||||
for(unsigned i = 0; i < line.size(); i++) {
|
||||
int position = qstrpos(line[i], "#");
|
||||
if(position >= 0) line[i][position] = 0;
|
||||
if(qstrpos(line[i], " = ") < 0) continue;
|
||||
if(auto position = qstrpos(line[i], "#")) line[i][position()] = 0;
|
||||
if(!qstrpos(line[i], " = ")) continue;
|
||||
|
||||
lstring part;
|
||||
part.qsplit(" = ", line[i]);
|
||||
|
@@ -15,9 +15,8 @@ namespace nall {
|
||||
|
||||
//no match, use input; remove input identifier, if one exists
|
||||
if(strbegin(input, "{{")) {
|
||||
int pos = strpos(input, "}}");
|
||||
if(pos >= 0) {
|
||||
string temp = substr(input, pos + 2);
|
||||
if(auto pos = strpos(input, "}}")) {
|
||||
string temp = substr(input, pos() + 2);
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
|
@@ -1,31 +1,12 @@
|
||||
#ifndef NALL_FOREACH_HPP
|
||||
#define NALL_FOREACH_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <nall/concept.hpp>
|
||||
|
||||
#undef foreach
|
||||
#define foreach(iter, object) \
|
||||
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(unsigned foreach_counter = 0, foreach_limit = container_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 <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) {
|
||||
return object.count();
|
||||
}
|
||||
|
||||
template<typename T> unsigned foreach_size(const T& object, typename mp_enable_if<has_length<T>>::type = 0) {
|
||||
return object.length();
|
||||
}
|
||||
|
||||
template<typename T> unsigned foreach_size(const T& object, typename mp_enable_if<has_size<T>>::type = 0) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -1,190 +1,90 @@
|
||||
#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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
#undef cat
|
||||
#undef TL
|
||||
#undef PL
|
||||
#undef CL
|
||||
|
||||
#endif
|
||||
|
@@ -93,9 +93,9 @@ struct Keyboard {
|
||||
if(!strbegin(name, "KB")) return 0;
|
||||
ltrim(s, "KB");
|
||||
unsigned id = strunsigned(s);
|
||||
int pos = strpos(s, "::");
|
||||
if(pos < 0) return 0;
|
||||
s = substr(s, pos + 2);
|
||||
auto pos = strpos(s, "::");
|
||||
if(!pos) return 0;
|
||||
s = substr(s, pos() + 2);
|
||||
for(unsigned i = 0; i < Limit; i++) {
|
||||
if(s == KeyboardScancodeName[i]) return Base + Size * id + i;
|
||||
}
|
||||
@@ -190,9 +190,9 @@ struct Mouse {
|
||||
if(!strbegin(name, "MS")) return 0;
|
||||
ltrim(s, "MS");
|
||||
unsigned id = strunsigned(s);
|
||||
int pos = strpos(s, "::");
|
||||
if(pos < 0) return 0;
|
||||
s = substr(s, pos + 2);
|
||||
auto pos = strpos(s, "::");
|
||||
if(!pos) return 0;
|
||||
s = substr(s, pos() + 2);
|
||||
for(unsigned i = 0; i < Limit; i++) {
|
||||
if(s == MouseScancodeName[i]) return Base + Size * id + i;
|
||||
}
|
||||
@@ -314,9 +314,9 @@ struct Joypad {
|
||||
if(!strbegin(name, "JP")) return 0;
|
||||
ltrim(s, "JP");
|
||||
unsigned id = strunsigned(s);
|
||||
int pos = strpos(s, "::");
|
||||
if(pos < 0) return 0;
|
||||
s = substr(s, pos + 2);
|
||||
auto pos = strpos(s, "::");
|
||||
if(!pos) return 0;
|
||||
s = substr(s, pos() + 2);
|
||||
for(unsigned i = 0; i < Limit; i++) {
|
||||
if(s == JoypadScancodeName[i]) return Base + Size * id + i;
|
||||
}
|
||||
|
@@ -211,7 +211,7 @@ inline void FileDialog::filterBoxChanged() {
|
||||
if(filters.length() == 0) {
|
||||
fileSystemModel->setNameFilters(QStringList() << "*");
|
||||
} else {
|
||||
filters = substr(filters, strpos(filters, "("));
|
||||
filters = substr(filters, strpos(filters, "(")());
|
||||
ltrim(filters, "(");
|
||||
rtrim(filters, ")");
|
||||
lstring part;
|
||||
|
20
snesfilter/nall/random.hpp
Normal file
20
snesfilter/nall/random.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef NALL_RANDOM_HPP
|
||||
#define NALL_RANDOM_HPP
|
||||
|
||||
namespace nall {
|
||||
//pseudo-random number generator
|
||||
inline unsigned prng() {
|
||||
static unsigned n = 0;
|
||||
return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320);
|
||||
}
|
||||
|
||||
struct random_cyclic {
|
||||
unsigned seed;
|
||||
inline unsigned operator()() {
|
||||
return seed = (seed >> 1) ^ (((seed & 1) - 1) & 0xedb88320);
|
||||
}
|
||||
random_cyclic() : seed(0) {}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@@ -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
|
||||
|
@@ -1,28 +1,135 @@
|
||||
#include "xml.hpp"
|
||||
XML xml;
|
||||
#ifndef NALL_SNES_INFO_HPP
|
||||
#define NALL_SNES_INFO_HPP
|
||||
|
||||
typedef uint8_t uint8;
|
||||
typedef uint16_t uint16;
|
||||
typedef uint32_t uint32;
|
||||
typedef uint64_t uint64;
|
||||
namespace nall {
|
||||
|
||||
void XML::generate(string &xml, const uint8_t *data, unsigned size) {
|
||||
class snes_information {
|
||||
public:
|
||||
string xml_memory_map;
|
||||
|
||||
inline snes_information(const uint8_t *data, unsigned size);
|
||||
|
||||
private:
|
||||
inline void read_header(const uint8_t *data, unsigned size);
|
||||
inline unsigned find_header(const uint8_t *data, unsigned size);
|
||||
inline unsigned score_header(const uint8_t *data, unsigned size, unsigned addr);
|
||||
inline unsigned gameboy_ram_size(const uint8_t *data, unsigned size);
|
||||
inline bool gameboy_has_rtc(const uint8_t *data, unsigned size);
|
||||
|
||||
enum HeaderField {
|
||||
CartName = 0x00,
|
||||
Mapper = 0x15,
|
||||
RomType = 0x16,
|
||||
RomSize = 0x17,
|
||||
RamSize = 0x18,
|
||||
CartRegion = 0x19,
|
||||
Company = 0x1a,
|
||||
Version = 0x1b,
|
||||
Complement = 0x1c, //inverse checksum
|
||||
Checksum = 0x1e,
|
||||
ResetVector = 0x3c,
|
||||
};
|
||||
|
||||
enum Mode {
|
||||
ModeNormal,
|
||||
ModeBsxSlotted,
|
||||
ModeBsx,
|
||||
ModeSufamiTurbo,
|
||||
ModeSuperGameBoy,
|
||||
};
|
||||
|
||||
enum Type {
|
||||
TypeNormal,
|
||||
TypeBsxSlotted,
|
||||
TypeBsxBios,
|
||||
TypeBsx,
|
||||
TypeSufamiTurboBios,
|
||||
TypeSufamiTurbo,
|
||||
TypeSuperGameBoy1Bios,
|
||||
TypeSuperGameBoy2Bios,
|
||||
TypeGameBoy,
|
||||
TypeUnknown,
|
||||
};
|
||||
|
||||
enum Region {
|
||||
NTSC,
|
||||
PAL,
|
||||
};
|
||||
|
||||
enum MemoryMapper {
|
||||
LoROM,
|
||||
HiROM,
|
||||
ExLoROM,
|
||||
ExHiROM,
|
||||
SuperFXROM,
|
||||
SA1ROM,
|
||||
SPC7110ROM,
|
||||
BSCLoROM,
|
||||
BSCHiROM,
|
||||
BSXROM,
|
||||
STROM,
|
||||
};
|
||||
|
||||
enum DSP1MemoryMapper {
|
||||
DSP1Unmapped,
|
||||
DSP1LoROM1MB,
|
||||
DSP1LoROM2MB,
|
||||
DSP1HiROM,
|
||||
};
|
||||
|
||||
bool loaded; //is a base cartridge inserted?
|
||||
unsigned crc32; //crc32 of all cartridges (base+slot(s))
|
||||
unsigned rom_size;
|
||||
unsigned ram_size;
|
||||
|
||||
Mode mode;
|
||||
Type type;
|
||||
Region region;
|
||||
MemoryMapper mapper;
|
||||
DSP1MemoryMapper dsp1_mapper;
|
||||
|
||||
bool has_bsx_slot;
|
||||
bool has_superfx;
|
||||
bool has_sa1;
|
||||
bool has_srtc;
|
||||
bool has_sdd1;
|
||||
bool has_spc7110;
|
||||
bool has_spc7110rtc;
|
||||
bool has_cx4;
|
||||
bool has_dsp1;
|
||||
bool has_dsp2;
|
||||
bool has_dsp3;
|
||||
bool has_dsp4;
|
||||
bool has_obc1;
|
||||
bool has_st010;
|
||||
bool has_st011;
|
||||
bool has_st018;
|
||||
};
|
||||
|
||||
snes_information::snes_information(const uint8_t *data, unsigned size) {
|
||||
read_header(data, size);
|
||||
|
||||
xml = "<?xml version='1.0' encoding='UTF-8'?>\n";
|
||||
string xml = "<?xml version='1.0' encoding='UTF-8'?>\n";
|
||||
|
||||
if(type == TypeBsx) {
|
||||
xml << "<cartridge/>";
|
||||
xml_memory_map = xml;
|
||||
return;
|
||||
} else if(type == TypeSufamiTurbo) {
|
||||
}
|
||||
|
||||
if(type == TypeSufamiTurbo) {
|
||||
xml << "<cartridge/>";
|
||||
xml_memory_map = xml;
|
||||
return;
|
||||
} else if(type == TypeGameBoy) {
|
||||
}
|
||||
|
||||
if(type == TypeGameBoy) {
|
||||
xml << "<cartridge rtc='" << gameboy_has_rtc(data, size) << "'>\n";
|
||||
if(gameboy_ram_size(data, size) > 0) {
|
||||
xml << " <ram size='" << strhex(gameboy_ram_size(data, size)) << "'/>\n";
|
||||
}
|
||||
xml << "</cartridge>\n";
|
||||
xml_memory_map = xml;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -56,30 +163,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 +230,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 +387,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 +444,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";
|
||||
}
|
||||
@@ -409,9 +518,10 @@ void XML::generate(string &xml, const uint8_t *data, unsigned size) {
|
||||
}
|
||||
|
||||
xml << "</cartridge>\n";
|
||||
xml_memory_map = xml;
|
||||
}
|
||||
|
||||
void XML::read_header(const uint8_t *data, unsigned size) {
|
||||
void snes_information::read_header(const uint8_t *data, unsigned size) {
|
||||
type = TypeUnknown;
|
||||
mapper = LoROM;
|
||||
dsp1_mapper = DSP1Unmapped;
|
||||
@@ -449,11 +559,11 @@ void XML::read_header(const uint8_t *data, unsigned size) {
|
||||
}
|
||||
|
||||
const unsigned index = find_header(data, size);
|
||||
const uint8 mapperid = data[index + Mapper];
|
||||
const uint8 rom_type = data[index + RomType];
|
||||
const uint8 rom_size = data[index + RomSize];
|
||||
const uint8 company = data[index + Company];
|
||||
const uint8 regionid = data[index + CartRegion] & 0x7f;
|
||||
const uint8_t mapperid = data[index + Mapper];
|
||||
const uint8_t rom_type = data[index + RomType];
|
||||
const uint8_t rom_size = data[index + RomSize];
|
||||
const uint8_t company = data[index + Company];
|
||||
const uint8_t regionid = data[index + CartRegion] & 0x7f;
|
||||
|
||||
ram_size = 1024 << (data[index + RamSize] & 7);
|
||||
if(ram_size == 1024) ram_size = 0; //no RAM present
|
||||
@@ -515,7 +625,7 @@ void XML::read_header(const uint8_t *data, unsigned size) {
|
||||
//detect presence of BS-X flash cartridge connector (reads extended header information)
|
||||
if(data[index - 14] == 'Z') {
|
||||
if(data[index - 11] == 'J') {
|
||||
uint8 n13 = data[index - 13];
|
||||
uint8_t n13 = data[index - 13];
|
||||
if((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9')) {
|
||||
if(company == 0x33 || (data[index - 10] == 0x00 && data[index - 4] == 0x00)) {
|
||||
has_bsx_slot = true;
|
||||
@@ -634,7 +744,7 @@ void XML::read_header(const uint8_t *data, unsigned size) {
|
||||
}
|
||||
}
|
||||
|
||||
unsigned XML::find_header(const uint8_t *data, unsigned size) const {
|
||||
unsigned snes_information::find_header(const uint8_t *data, unsigned size) {
|
||||
unsigned score_lo = score_header(data, size, 0x007fc0);
|
||||
unsigned score_hi = score_header(data, size, 0x00ffc0);
|
||||
unsigned score_ex = score_header(data, size, 0x40ffc0);
|
||||
@@ -649,16 +759,16 @@ unsigned XML::find_header(const uint8_t *data, unsigned size) const {
|
||||
}
|
||||
}
|
||||
|
||||
unsigned XML::score_header(const uint8_t *data, unsigned size, unsigned addr) const {
|
||||
unsigned snes_information::score_header(const uint8_t *data, unsigned size, unsigned addr) {
|
||||
if(size < addr + 64) return 0; //image too small to contain header at this location?
|
||||
int score = 0;
|
||||
|
||||
uint16 resetvector = data[addr + ResetVector] | (data[addr + ResetVector + 1] << 8);
|
||||
uint16 checksum = data[addr + Checksum ] | (data[addr + Checksum + 1] << 8);
|
||||
uint16 complement = data[addr + Complement ] | (data[addr + Complement + 1] << 8);
|
||||
uint16_t resetvector = data[addr + ResetVector] | (data[addr + ResetVector + 1] << 8);
|
||||
uint16_t checksum = data[addr + Checksum ] | (data[addr + Checksum + 1] << 8);
|
||||
uint16_t complement = data[addr + Complement ] | (data[addr + Complement + 1] << 8);
|
||||
|
||||
uint8 resetop = data[(addr & ~0x7fff) | (resetvector & 0x7fff)]; //first opcode executed upon reset
|
||||
uint8 mapper = data[addr + Mapper] & ~0x10; //mask off irrelevent FastROM-capable bit
|
||||
uint8_t resetop = data[(addr & ~0x7fff) | (resetvector & 0x7fff)]; //first opcode executed upon reset
|
||||
uint8_t mapper = data[addr + Mapper] & ~0x10; //mask off irrelevent FastROM-capable bit
|
||||
|
||||
//$00:[000-7fff] contains uninitialized RAM and MMIO.
|
||||
//reset vector must point to ROM at $00:[8000-ffff] to be considered valid.
|
||||
@@ -730,7 +840,7 @@ unsigned XML::score_header(const uint8_t *data, unsigned size, unsigned addr) co
|
||||
return score;
|
||||
}
|
||||
|
||||
unsigned XML::gameboy_ram_size(const uint8_t *data, unsigned size) const {
|
||||
unsigned snes_information::gameboy_ram_size(const uint8_t *data, unsigned size) {
|
||||
if(size < 512) return 0;
|
||||
switch(data[0x0149]) {
|
||||
case 0x00: return 0 * 1024;
|
||||
@@ -743,8 +853,12 @@ unsigned XML::gameboy_ram_size(const uint8_t *data, unsigned size) const {
|
||||
}
|
||||
}
|
||||
|
||||
bool XML::gameboy_has_rtc(const uint8_t *data, unsigned size) const {
|
||||
bool snes_information::gameboy_has_rtc(const uint8_t *data, unsigned size) {
|
||||
if(size < 512) return false;
|
||||
if(data[0x0147] == 0x0f ||data[0x0147] == 0x10) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@@ -2,6 +2,8 @@
|
||||
#define NALL_STRING_HPP
|
||||
|
||||
#include <initializer_list>
|
||||
#include <nall/utility.hpp>
|
||||
|
||||
#include <nall/string/base.hpp>
|
||||
#include <nall/string/core.hpp>
|
||||
#include <nall/string/cast.hpp>
|
||||
@@ -11,6 +13,7 @@
|
||||
#include <nall/string/match.hpp>
|
||||
#include <nall/string/math.hpp>
|
||||
#include <nall/string/strl.hpp>
|
||||
#include <nall/string/strpos.hpp>
|
||||
#include <nall/string/trim.hpp>
|
||||
#include <nall/string/replace.hpp>
|
||||
#include <nall/string/split.hpp>
|
||||
|
@@ -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*);
|
||||
@@ -64,12 +35,13 @@ namespace nall {
|
||||
inline bool operator> (const char*) const;
|
||||
inline bool operator>=(const char*) const;
|
||||
|
||||
inline string& operator=(const string&);
|
||||
inline string& operator=(string&&);
|
||||
|
||||
inline string();
|
||||
inline string(const char*);
|
||||
inline string(const string&);
|
||||
inline string(string&&);
|
||||
inline string& operator=(const string&);
|
||||
inline string& operator=(string&&);
|
||||
inline ~string();
|
||||
|
||||
inline bool readfile(const char*);
|
||||
@@ -78,9 +50,9 @@ namespace nall {
|
||||
|
||||
protected:
|
||||
char *data;
|
||||
size_t size;
|
||||
unsigned size;
|
||||
|
||||
#if defined(QT_CORE_LIB)
|
||||
#if defined(QSTRING_H)
|
||||
public:
|
||||
inline operator QString() const;
|
||||
#endif
|
||||
@@ -98,29 +70,67 @@ 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 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
|
||||
|
@@ -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(QSTRING_H)
|
||||
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
|
||||
|
@@ -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;
|
||||
}
|
||||
@@ -19,38 +21,6 @@ int stricmp(const char *dest, const char *src) {
|
||||
return (int)chrlower(*dest) - (int)chrlower(*src);
|
||||
}
|
||||
|
||||
int strpos(const char *str, const char *key) {
|
||||
int ssl = strlen(str), ksl = strlen(key);
|
||||
|
||||
if(ksl > ssl) return -1;
|
||||
for(int i = 0; i <= ssl - ksl; i++) {
|
||||
if(!memcmp(str + i, key, ksl)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int qstrpos(const char *str, const char *key) {
|
||||
int ssl = strlen(str), ksl = strlen(key);
|
||||
|
||||
if(ksl > ssl) return -1;
|
||||
for(int i = 0; i <= ssl - ksl;) {
|
||||
uint8_t x = str[i];
|
||||
if(x == '\"' || x == '\'') {
|
||||
uint8_t z = i++;
|
||||
while(str[i] != x && i < ssl) i++;
|
||||
if(i >= ssl) i = z;
|
||||
}
|
||||
if(!memcmp(str + i, key, ksl)) {
|
||||
return i;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool strbegin(const char *str, const char *key) {
|
||||
int i, ssl = strlen(str), ksl = strlen(key);
|
||||
|
||||
@@ -97,4 +67,6 @@ bool striend(const char *str, const char *key) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -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;
|
||||
@@ -125,7 +127,7 @@ double strdouble(const char *str) {
|
||||
while(*str) {
|
||||
uint8_t x = *str++;
|
||||
if(x >= '0' && x <= '9') x -= '0';
|
||||
else if(x == '.') break; //break loop and read fractional part
|
||||
else if(x == '.' || x == ',') break; //break loop and read fractional part
|
||||
else return (double)result_integral; //invalid value, assume no fractional part
|
||||
result_integral = result_integral * 10 + x;
|
||||
}
|
||||
@@ -146,4 +148,6 @@ double strdouble(const char *str) {
|
||||
return !negate ? result : -result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -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);
|
||||
@@ -49,6 +49,20 @@ bool string::operator<=(const char *str) const { return strcmp(data, str) <= 0;
|
||||
bool string::operator> (const char *str) const { return strcmp(data, str) > 0; }
|
||||
bool string::operator>=(const char *str) const { return strcmp(data, str) >= 0; }
|
||||
|
||||
string& string::operator=(const string &value) {
|
||||
assign(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string& string::operator=(string &&source) {
|
||||
if(data) free(data);
|
||||
size = source.size;
|
||||
data = source.data;
|
||||
source.data = 0;
|
||||
source.size = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
string::string() {
|
||||
size = 64;
|
||||
data = (char*)malloc(size + 1);
|
||||
@@ -71,19 +85,6 @@ string::string(string &&source) {
|
||||
source.data = 0;
|
||||
}
|
||||
|
||||
string& string::operator=(const string &value) {
|
||||
assign(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string& string::operator=(string &&source) {
|
||||
if(data) free(data);
|
||||
size = source.size;
|
||||
data = source.data;
|
||||
source.data = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
string::~string() {
|
||||
free(data);
|
||||
}
|
||||
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
41
snesfilter/nall/string/strpos.hpp
Normal file
41
snesfilter/nall/string/strpos.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef NALL_STRING_STRPOS_HPP
|
||||
#define NALL_STRING_STRPOS_HPP
|
||||
|
||||
//usage example:
|
||||
//if(auto pos = strpos(str, key)) print(pos(), "\n");
|
||||
//prints position of key within str, only if it is found
|
||||
|
||||
namespace nall {
|
||||
|
||||
optional<unsigned> inline strpos(const char *str, const char *key) {
|
||||
unsigned ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl) return { false, 0 };
|
||||
|
||||
for(unsigned i = 0; i <= ssl - ksl; i++) {
|
||||
if(!memcmp(str + i, key, ksl)) return { true, i };
|
||||
}
|
||||
|
||||
return { false, 0 };
|
||||
}
|
||||
|
||||
optional<unsigned> inline qstrpos(const char *str, const char *key) {
|
||||
unsigned ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl) return { false, 0 };
|
||||
|
||||
for(unsigned i = 0; i <= ssl - ksl;) {
|
||||
uint8_t x = str[i];
|
||||
if(x == '\"' || x == '\'') {
|
||||
uint8_t z = i++;
|
||||
while(str[i] != x && i < ssl) i++;
|
||||
if(i >= ssl) i = z;
|
||||
}
|
||||
if(!memcmp(str + i, key, ksl)) return { true, i };
|
||||
i++;
|
||||
}
|
||||
|
||||
return { false, 0 };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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 {
|
||||
@@ -68,21 +65,25 @@ inline string xml_element::parse() const {
|
||||
}
|
||||
|
||||
if(strbegin(source, "<!--")) {
|
||||
signed pos = strpos(source, "-->");
|
||||
if(pos == -1) return "";
|
||||
source += pos + 3;
|
||||
continue;
|
||||
if(auto pos = strpos(source, "-->")) {
|
||||
source += pos() + 3;
|
||||
continue;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
if(strbegin(source, "<![CDATA[")) {
|
||||
signed pos = strpos(source, "]]>");
|
||||
if(pos == -1) return "";
|
||||
string cdata = substr(source, 9, pos - 9);
|
||||
data << cdata;
|
||||
offset += strlen(cdata);
|
||||
if(auto pos = strpos(source, "]]>")) {
|
||||
string cdata = substr(source, 9, pos() - 9);
|
||||
data << cdata;
|
||||
offset += strlen(cdata);
|
||||
|
||||
source += offset + 3;
|
||||
continue;
|
||||
source += offset + 3;
|
||||
continue;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
//reject illegal characters
|
||||
@@ -118,7 +119,7 @@ inline bool xml_element::parse_head(string data) {
|
||||
data.qreplace("\t", " ");
|
||||
data.qreplace("\r", " ");
|
||||
data.qreplace("\n", " ");
|
||||
while(qstrpos(data, " ") >= 0) data.qreplace(" ", " ");
|
||||
while(qstrpos(data, " ")) data.qreplace(" ", " ");
|
||||
data.qreplace(" =", "=");
|
||||
data.qreplace("= ", "=");
|
||||
rtrim(data);
|
||||
@@ -134,13 +135,13 @@ 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);
|
||||
attribute.append(attr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,24 +157,28 @@ inline bool xml_element::parse_body(const char *&data) {
|
||||
}
|
||||
|
||||
if(strbegin(data, "!--")) {
|
||||
signed offset = strpos(data, "-->");
|
||||
if(offset == -1) throw "...";
|
||||
data += offset + 3;
|
||||
continue;
|
||||
if(auto offset = strpos(data, "-->")) {
|
||||
data += offset() + 3;
|
||||
continue;
|
||||
} else {
|
||||
throw "...";
|
||||
}
|
||||
}
|
||||
|
||||
if(strbegin(data, "![CDATA[")) {
|
||||
signed offset = strpos(data, "]]>");
|
||||
if(offset == -1) throw "...";
|
||||
data += offset + 3;
|
||||
continue;
|
||||
if(auto offset = strpos(data, "]]>")) {
|
||||
data += offset() + 3;
|
||||
continue;
|
||||
} else {
|
||||
throw "...";
|
||||
}
|
||||
}
|
||||
|
||||
signed offset = strpos(data, ">");
|
||||
if(offset == -1) throw "...";
|
||||
auto offset = strpos(data, ">");
|
||||
if(!offset) throw "...";
|
||||
|
||||
string tag = substr(data, 0, offset);
|
||||
data += offset + 1;
|
||||
string tag = substr(data, 0, offset());
|
||||
data += offset() + 1;
|
||||
const char *content_begin = data;
|
||||
|
||||
bool self_terminating = false;
|
||||
@@ -191,48 +196,41 @@ 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);
|
||||
|
||||
data++;
|
||||
offset = strpos(data, ">");
|
||||
if(offset == -1) throw "...";
|
||||
auto offset = strpos(data, ">");
|
||||
if(!offset) throw "...";
|
||||
|
||||
tag = substr(data, 0, offset);
|
||||
data += offset + 1;
|
||||
tag = substr(data, 0, offset());
|
||||
data += offset() + 1;
|
||||
|
||||
tag.replace("\t", " ");
|
||||
tag.replace("\r", " ");
|
||||
tag.replace("\n", " ");
|
||||
while(strpos(tag, " ") >= 0) tag.replace(" ", " ");
|
||||
while(strpos(tag, " ")) tag.replace(" ", " ");
|
||||
rtrim(tag);
|
||||
|
||||
if(name != tag) throw "...";
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
element.add(elem);
|
||||
element.append(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 +239,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.append(node);
|
||||
}
|
||||
}
|
||||
|
||||
if(xml_validate(self) == false) throw "...";
|
||||
return self;
|
||||
} catch(const char*) {
|
||||
delete self;
|
||||
return 0;
|
||||
xml_element empty;
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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
|
@@ -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 {
|
||||
@@ -31,9 +20,18 @@ namespace nall {
|
||||
base_from_member(T value_) : value(value_) {}
|
||||
};
|
||||
|
||||
template<typename T> inline T* allocate(size_t size, const T &value) {
|
||||
template<typename T> class optional {
|
||||
bool valid;
|
||||
T value;
|
||||
public:
|
||||
inline operator bool() const { return valid; }
|
||||
inline const T& operator()() const { if(!valid) throw; return value; }
|
||||
inline optional(bool valid, const T &value) : valid(valid), value(value) {}
|
||||
};
|
||||
|
||||
template<typename T> inline T* allocate(unsigned size, const T &value) {
|
||||
T *array = new T[size];
|
||||
for(size_t i = 0; i < size; i++) array[i] = value;
|
||||
for(unsigned i = 0; i < size; i++) array[i] = value;
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
@@ -3,10 +3,12 @@
|
||||
|
||||
#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/foreach.hpp>
|
||||
#include <nall/utility.hpp>
|
||||
|
||||
namespace nall {
|
||||
@@ -67,11 +69,31 @@ namespace nall {
|
||||
objectsize = newsize;
|
||||
}
|
||||
|
||||
void add(const T data) {
|
||||
void append(const T data) {
|
||||
if(objectsize + 1 > poolsize) reserve(objectsize + 1);
|
||||
new(pool + objectsize++) T(data);
|
||||
}
|
||||
|
||||
template<typename U> void insert(unsigned index, const U list) {
|
||||
linear_vector<T> merged;
|
||||
for(unsigned i = 0; i < index; i++) merged.append(pool[i]);
|
||||
foreach(item, list) merged.append(item);
|
||||
for(unsigned i = index; i < objectsize; i++) merged.append(pool[i]);
|
||||
operator=(merged);
|
||||
}
|
||||
|
||||
void insert(unsigned index, const T item) {
|
||||
insert(index, linear_vector<T>{ item });
|
||||
}
|
||||
|
||||
void remove(unsigned index, unsigned count = 1) {
|
||||
for(unsigned i = index; count + i < objectsize; i++) {
|
||||
pool[i] = pool[count + i];
|
||||
}
|
||||
if(count + index >= objectsize) resize(index); //every element >= index was removed
|
||||
else resize(objectsize - count);
|
||||
}
|
||||
|
||||
inline T& operator[](unsigned index) {
|
||||
if(index >= objectsize) resize(index + 1);
|
||||
return pool[index];
|
||||
@@ -86,11 +108,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 +124,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
|
||||
@@ -113,7 +137,7 @@ namespace nall {
|
||||
}
|
||||
|
||||
linear_vector(std::initializer_list<T> list) : pool(0), poolsize(0), objectsize(0) {
|
||||
for(const T *p = list.begin(); p != list.end(); ++p) add(*p);
|
||||
for(const T *p = list.begin(); p != list.end(); ++p) append(*p);
|
||||
}
|
||||
|
||||
~linear_vector() {
|
||||
@@ -173,11 +197,31 @@ namespace nall {
|
||||
objectsize = newsize;
|
||||
}
|
||||
|
||||
void add(const T data) {
|
||||
void append(const T data) {
|
||||
if(objectsize + 1 > poolsize) reserve(objectsize + 1);
|
||||
pool[objectsize++] = new T(data);
|
||||
}
|
||||
|
||||
template<typename U> void insert(unsigned index, const U list) {
|
||||
pointer_vector<T> merged;
|
||||
for(unsigned i = 0; i < index; i++) merged.append(*pool[i]);
|
||||
foreach(item, list) merged.append(item);
|
||||
for(unsigned i = index; i < objectsize; i++) merged.append(*pool[i]);
|
||||
operator=(merged);
|
||||
}
|
||||
|
||||
void insert(unsigned index, const T item) {
|
||||
insert(index, pointer_vector<T>{ item });
|
||||
}
|
||||
|
||||
void remove(unsigned index, unsigned count = 1) {
|
||||
for(unsigned i = index; count + i < objectsize; i++) {
|
||||
*pool[i] = *pool[count + i];
|
||||
}
|
||||
if(count + index >= objectsize) resize(index); //every element >= index was removed
|
||||
else resize(objectsize - count);
|
||||
}
|
||||
|
||||
inline T& operator[](unsigned index) {
|
||||
if(index >= objectsize) resize(index + 1);
|
||||
if(!pool[index]) pool[index] = new T;
|
||||
@@ -193,11 +237,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 +253,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
|
||||
@@ -220,7 +266,7 @@ namespace nall {
|
||||
}
|
||||
|
||||
pointer_vector(std::initializer_list<T> list) : pool(0), poolsize(0), objectsize(0) {
|
||||
for(const T *p = list.begin(); p != list.end(); ++p) add(*p);
|
||||
for(const T *p = list.begin(); p != list.end(); ++p) append(*p);
|
||||
}
|
||||
|
||||
~pointer_vector() {
|
||||
|
@@ -24,37 +24,21 @@ void NTSCFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, u
|
||||
}
|
||||
|
||||
void NTSCFilter::render(
|
||||
uint32_t *output, unsigned outpitch, const uint16_t *input, unsigned pitch,
|
||||
const unsigned *line, unsigned width, unsigned height
|
||||
uint32_t *output, unsigned outpitch,
|
||||
const uint16_t *input, unsigned pitch, unsigned width, unsigned height
|
||||
) {
|
||||
if(!ntsc) return;
|
||||
|
||||
width = SNES_NTSC_OUT_WIDTH(256);
|
||||
burst ^= burst_toggle;
|
||||
|
||||
pitch >>= 1;
|
||||
outpitch >>= 2;
|
||||
|
||||
unsigned line_burst = burst;
|
||||
for(unsigned y = 0; y < height;) {
|
||||
const uint16_t *in = input + y * pitch;
|
||||
uint32_t *out = output + y * outpitch;
|
||||
|
||||
//render as many lines in one snes_ntsc_blit as possible:
|
||||
//do this by determining for how many lines the width stays the same
|
||||
unsigned rheight = 1;
|
||||
unsigned rwidth = line[y];
|
||||
while(y + rheight < height && rwidth == line[y + rheight]) rheight++;
|
||||
|
||||
if(rwidth == 256) {
|
||||
snes_ntsc_blit (ntsc, in, pitch, line_burst, rwidth, rheight, out, outpitch << 2);
|
||||
} else {
|
||||
snes_ntsc_blit_hires(ntsc, in, pitch, line_burst, rwidth, rheight, out, outpitch << 2);
|
||||
}
|
||||
|
||||
line_burst = (line_burst + rheight) % 3;
|
||||
y += rheight;
|
||||
if(width <= 256) {
|
||||
snes_ntsc_blit (ntsc, input, pitch, burst, width, height, output, outpitch << 2);
|
||||
} else {
|
||||
snes_ntsc_blit_hires(ntsc, input, pitch, burst, width, height, output, outpitch << 2);
|
||||
}
|
||||
|
||||
burst ^= burst_toggle;
|
||||
}
|
||||
|
||||
QWidget* NTSCFilter::settings() {
|
||||
|
@@ -4,7 +4,7 @@ class NTSCFilter : public QObject {
|
||||
public:
|
||||
void bind(configuration&);
|
||||
void size(unsigned&, unsigned&, unsigned, unsigned);
|
||||
void render(uint32_t*, unsigned, const uint16_t*, unsigned, const unsigned*, unsigned, unsigned);
|
||||
void render(uint32_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned);
|
||||
QWidget* settings();
|
||||
|
||||
NTSCFilter();
|
||||
|
@@ -6,8 +6,8 @@ void Pixellate2xFilter::size(unsigned &outwidth, unsigned &outheight, unsigned w
|
||||
}
|
||||
|
||||
void Pixellate2xFilter::render(
|
||||
uint32_t *output, unsigned outpitch, const uint16_t *input, unsigned pitch,
|
||||
const unsigned *line, unsigned width, unsigned height
|
||||
uint32_t *output, unsigned outpitch,
|
||||
const uint16_t *input, unsigned pitch, unsigned width, unsigned height
|
||||
) {
|
||||
pitch >>= 1;
|
||||
outpitch >>= 2;
|
||||
@@ -16,19 +16,18 @@ void Pixellate2xFilter::render(
|
||||
uint32_t *out1 = output + outpitch;
|
||||
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
unsigned linewidth = line[y];
|
||||
for(unsigned x = 0; x < linewidth; x++) {
|
||||
for(unsigned x = 0; x < width; x++) {
|
||||
uint32_t p = colortable[*input++];
|
||||
|
||||
*out0++ = p;
|
||||
if(height <= 240) *out1++ = p;
|
||||
if(linewidth > 256) continue;
|
||||
if(width > 256) continue;
|
||||
|
||||
*out0++ = p;
|
||||
if(height <= 240) *out1++ = p;
|
||||
}
|
||||
|
||||
input += pitch - linewidth;
|
||||
input += pitch - width;
|
||||
if(height <= 240) {
|
||||
out0 += outpitch + outpitch - 512;
|
||||
out1 += outpitch + outpitch - 512;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
class Pixellate2xFilter {
|
||||
public:
|
||||
void size(unsigned&, unsigned&, unsigned, unsigned);
|
||||
void render(uint32_t*, unsigned, const uint16_t*, unsigned, const unsigned*, unsigned, unsigned);
|
||||
void render(uint32_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned);
|
||||
} filter_pixellate2x;
|
||||
|
@@ -1,17 +1,17 @@
|
||||
#include "scale2x.hpp"
|
||||
|
||||
void Scale2xFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) {
|
||||
if(height > 240) return filter_direct.size(outwidth, outheight, width, height);
|
||||
outwidth = (width <= 256) ? width * 2 : width;
|
||||
outheight = (height <= 240) ? height * 2 : height;
|
||||
if(width > 256 || height > 240) return filter_direct.size(outwidth, outheight, width, height);
|
||||
outwidth = width * 2;
|
||||
outheight = height * 2;
|
||||
}
|
||||
|
||||
void Scale2xFilter::render(
|
||||
uint32_t *output, unsigned outpitch, const uint16_t *input, unsigned pitch,
|
||||
const unsigned *line, unsigned width, unsigned height
|
||||
uint32_t *output, unsigned outpitch,
|
||||
const uint16_t *input, unsigned pitch, unsigned width, unsigned height
|
||||
) {
|
||||
if(height > 240) {
|
||||
filter_direct.render(output, outpitch, input, pitch, line, width, height);
|
||||
if(width > 256 || height > 240) {
|
||||
filter_direct.render(output, outpitch, input, pitch, width, height);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -22,39 +22,31 @@ void Scale2xFilter::render(
|
||||
uint32_t *out1 = output + outpitch;
|
||||
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
unsigned linewidth = line[y];
|
||||
int prevline = (y == 0 ? 0 : pitch);
|
||||
int nextline = (y == height - 1 ? 0 : pitch);
|
||||
|
||||
if(linewidth == 256) {
|
||||
int prevline = (y == 0) || (linewidth != line[y - 1]) ? 0 : pitch;
|
||||
int nextline = (y == height - 1) || (linewidth != line[y + 1]) ? 0 : pitch;
|
||||
for(unsigned x = 0; x < width; x++) {
|
||||
uint16_t A = *(input - prevline);
|
||||
uint16_t B = (x > 0) ? *(input - 1) : *input;
|
||||
uint16_t C = *input;
|
||||
uint16_t D = (x < 255) ? *(input + 1) : *input;
|
||||
uint16_t E = *(input++ + nextline);
|
||||
uint32_t c = colortable[C];
|
||||
|
||||
for(unsigned x = 0; x < 256; x++) {
|
||||
uint16_t A = *(input - prevline);
|
||||
uint16_t B = (x > 0) ? *(input - 1) : *input;
|
||||
uint16_t C = *input;
|
||||
uint16_t D = (x < 255) ? *(input + 1) : *input;
|
||||
uint16_t E = *(input++ + nextline);
|
||||
uint32_t c = colortable[C];
|
||||
|
||||
if(A != E && B != D) {
|
||||
*out0++ = (A == B ? colortable[A] : c);
|
||||
*out0++ = (A == D ? colortable[A] : c);
|
||||
*out1++ = (E == B ? colortable[E] : c);
|
||||
*out1++ = (E == D ? colortable[E] : c);
|
||||
} else {
|
||||
*out0++ = c;
|
||||
*out0++ = c;
|
||||
*out1++ = c;
|
||||
*out1++ = c;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(unsigned x = 0; x < 512; x++) {
|
||||
*out0++ = *out1++ = colortable[*input++];
|
||||
if(A != E && B != D) {
|
||||
*out0++ = (A == B ? colortable[A] : c);
|
||||
*out0++ = (A == D ? colortable[A] : c);
|
||||
*out1++ = (E == B ? colortable[E] : c);
|
||||
*out1++ = (E == D ? colortable[E] : c);
|
||||
} else {
|
||||
*out0++ = c;
|
||||
*out0++ = c;
|
||||
*out1++ = c;
|
||||
*out1++ = c;
|
||||
}
|
||||
}
|
||||
|
||||
input += pitch - linewidth;
|
||||
input += pitch - width;
|
||||
out0 += outpitch + outpitch - 512;
|
||||
out1 += outpitch + outpitch - 512;
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
class Scale2xFilter {
|
||||
public:
|
||||
void size(unsigned&, unsigned&, unsigned, unsigned);
|
||||
void render(uint32_t*, unsigned, const uint16_t*, unsigned, const unsigned*, unsigned, unsigned);
|
||||
void render(uint32_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned);
|
||||
} filter_scale2x;
|
||||
|
@@ -60,19 +60,18 @@ dllexport void snesfilter_size(unsigned filter, unsigned &outwidth, unsigned &ou
|
||||
|
||||
dllexport void snesfilter_render(
|
||||
unsigned filter, uint32_t *output, unsigned outpitch,
|
||||
const uint16_t *input, unsigned pitch,
|
||||
const unsigned *line, unsigned width, unsigned height
|
||||
const uint16_t *input, unsigned pitch, unsigned width, unsigned height
|
||||
) {
|
||||
switch(filter) {
|
||||
default: return filter_direct.render(output, outpitch, input, pitch, line, width, height);
|
||||
case 1: return filter_pixellate2x.render(output, outpitch, input, pitch, line, width, height);
|
||||
case 2: return filter_scale2x.render(output, outpitch, input, pitch, line, width, height);
|
||||
case 3: return filter_2xsai.render(output, outpitch, input, pitch, line, width, height);
|
||||
case 4: return filter_super2xsai.render(output, outpitch, input, pitch, line, width, height);
|
||||
case 5: return filter_supereagle.render(output, outpitch, input, pitch, line, width, height);
|
||||
case 6: return filter_lq2x.render(output, outpitch, input, pitch, line, width, height);
|
||||
case 7: return filter_hq2x.render(output, outpitch, input, pitch, line, width, height);
|
||||
case 8: return filter_ntsc.render(output, outpitch, input, pitch, line, width, height);
|
||||
default: return filter_direct.render(output, outpitch, input, pitch, width, height);
|
||||
case 1: return filter_pixellate2x.render(output, outpitch, input, pitch, width, height);
|
||||
case 2: return filter_scale2x.render(output, outpitch, input, pitch, width, height);
|
||||
case 3: return filter_2xsai.render(output, outpitch, input, pitch, width, height);
|
||||
case 4: return filter_super2xsai.render(output, outpitch, input, pitch, width, height);
|
||||
case 5: return filter_supereagle.render(output, outpitch, input, pitch, width, height);
|
||||
case 6: return filter_lq2x.render(output, outpitch, input, pitch, width, height);
|
||||
case 7: return filter_hq2x.render(output, outpitch, input, pitch, width, height);
|
||||
case 8: return filter_ntsc.render(output, outpitch, input, pitch, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -7,10 +7,6 @@ extern "C" {
|
||||
void snesfilter_configuration(nall::configuration&);
|
||||
void snesfilter_colortable(const uint32_t*);
|
||||
void snesfilter_size(unsigned, unsigned&, unsigned&, unsigned, unsigned);
|
||||
void snesfilter_render(
|
||||
unsigned, uint32_t*, unsigned,
|
||||
const uint16_t*, unsigned,
|
||||
const unsigned*, unsigned, unsigned
|
||||
);
|
||||
void snesfilter_render(unsigned, uint32_t*, unsigned, const uint16_t*, unsigned, unsigned, unsigned);
|
||||
QWidget* snesfilter_settings(unsigned);
|
||||
}
|
||||
|
BIN
snesreader.dll
BIN
snesreader.dll
Binary file not shown.
@@ -59,7 +59,6 @@ $(foreach f,$(moc_objects), \
|
||||
$(eval $f: $(__file)) \
|
||||
)
|
||||
|
||||
|
||||
##################
|
||||
### snesreader ###
|
||||
##################
|
||||
|
@@ -19,16 +19,17 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#ifndef __PORTABLE_H
|
||||
#define __PORTABLE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef signed char INT8;
|
||||
typedef unsigned char UINT8;
|
||||
typedef short INT16;
|
||||
typedef unsigned short UINT16;
|
||||
typedef long INT32;
|
||||
typedef unsigned long UINT32;
|
||||
typedef long long INT64;
|
||||
typedef unsigned long long UINT64;
|
||||
typedef int8_t INT8;
|
||||
typedef uint8_t UINT8;
|
||||
typedef int16_t INT16;
|
||||
typedef uint16_t UINT16;
|
||||
typedef int32_t INT32;
|
||||
typedef uint32_t UINT32;
|
||||
typedef int64_t INT64;
|
||||
typedef uint64_t UINT64;
|
||||
|
||||
typedef UINT8 BYTE;
|
||||
typedef UINT16 WORD;
|
||||
|
@@ -30,7 +30,7 @@ endif
|
||||
|
||||
ifeq ($(compiler),)
|
||||
ifeq ($(platform),osx)
|
||||
compiler := gcc-4.2
|
||||
compiler := gcc-mp-4.4
|
||||
else
|
||||
compiler := gcc
|
||||
endif
|
||||
|
@@ -12,12 +12,6 @@ namespace nall {
|
||||
template<typename T, typename U> T max(const T &t, const U &u) {
|
||||
return t > u ? t : u;
|
||||
}
|
||||
|
||||
//pseudo-random number generator
|
||||
inline unsigned prng() {
|
||||
static unsigned n = 0;
|
||||
return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -3,10 +3,13 @@
|
||||
|
||||
#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>
|
||||
#include <nall/foreach.hpp>
|
||||
#include <nall/utility.hpp>
|
||||
|
||||
namespace nall {
|
||||
//dynamic vector array
|
||||
@@ -47,13 +50,32 @@ namespace nall {
|
||||
return pool;
|
||||
}
|
||||
|
||||
void add(const T data) {
|
||||
void append(const T data) {
|
||||
operator[](buffersize) = data;
|
||||
}
|
||||
|
||||
signed find(const T data) {
|
||||
for(unsigned i = 0; i < size(); i++) if(pool[i] == data) return i;
|
||||
return -1; //not found
|
||||
template<typename U> void insert(unsigned index, const U list) {
|
||||
unsigned listsize = container_size(list);
|
||||
resize(buffersize + listsize);
|
||||
memmove(pool + index + listsize, pool + index, (buffersize - index) * sizeof(T));
|
||||
foreach(item, list) pool[index++] = item;
|
||||
}
|
||||
|
||||
void insert(unsigned index, const T item) {
|
||||
insert(index, array<T>{ item });
|
||||
}
|
||||
|
||||
void remove(unsigned index, unsigned count = 1) {
|
||||
for(unsigned i = index; count + i < buffersize; i++) {
|
||||
pool[i] = pool[count + i];
|
||||
}
|
||||
if(count + index >= buffersize) resize(index); //every element >= index was removed
|
||||
else resize(buffersize - count);
|
||||
}
|
||||
|
||||
optional<unsigned> find(const T data) {
|
||||
for(unsigned i = 0; i < size(); i++) if(pool[i] == data) return { true, i };
|
||||
return { false, 0 };
|
||||
}
|
||||
|
||||
void clear() {
|
||||
@@ -64,7 +86,7 @@ namespace nall {
|
||||
}
|
||||
|
||||
array(std::initializer_list<T> list) : pool(0), poolsize(0), buffersize(0) {
|
||||
for(const T *p = list.begin(); p != list.end(); ++p) add(*p);
|
||||
for(const T *p = list.begin(); p != list.end(); ++p) append(*p);
|
||||
}
|
||||
|
||||
~array() {
|
||||
@@ -81,7 +103,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 +114,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
|
||||
|
@@ -1,6 +1,9 @@
|
||||
#ifndef NALL_CONCEPT_HPP
|
||||
#define NALL_CONCEPT_HPP
|
||||
|
||||
#include <nall/static.hpp>
|
||||
#include <nall/utility.hpp>
|
||||
|
||||
namespace nall {
|
||||
//unsigned count() const;
|
||||
template<typename T> struct has_count { enum { value = false }; };
|
||||
@@ -10,6 +13,22 @@ namespace nall {
|
||||
|
||||
//unsigned size() const;
|
||||
template<typename T> struct has_size { enum { value = false }; };
|
||||
|
||||
template<typename T> unsigned container_size(const T& object, typename mp_enable_if<has_count<T>>::type = 0) {
|
||||
return object.count();
|
||||
}
|
||||
|
||||
template<typename T> unsigned container_size(const T& object, typename mp_enable_if<has_length<T>>::type = 0) {
|
||||
return object.length();
|
||||
}
|
||||
|
||||
template<typename T> unsigned container_size(const T& object, typename mp_enable_if<has_size<T>>::type = 0) {
|
||||
return object.size();
|
||||
}
|
||||
|
||||
template<typename T> unsigned container_size(const T& object, typename mp_enable_if<std::is_array<T>>::type = 0) {
|
||||
return sizeof(T) / sizeof(typename std::remove_extent<T>::type);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -78,9 +78,8 @@ namespace nall {
|
||||
line.split("\n", data);
|
||||
|
||||
for(unsigned i = 0; i < line.size(); i++) {
|
||||
int position = qstrpos(line[i], "#");
|
||||
if(position >= 0) line[i][position] = 0;
|
||||
if(qstrpos(line[i], " = ") < 0) continue;
|
||||
if(auto position = qstrpos(line[i], "#")) line[i][position()] = 0;
|
||||
if(!qstrpos(line[i], " = ")) continue;
|
||||
|
||||
lstring part;
|
||||
part.qsplit(" = ", line[i]);
|
||||
|
@@ -15,9 +15,8 @@ namespace nall {
|
||||
|
||||
//no match, use input; remove input identifier, if one exists
|
||||
if(strbegin(input, "{{")) {
|
||||
int pos = strpos(input, "}}");
|
||||
if(pos >= 0) {
|
||||
string temp = substr(input, pos + 2);
|
||||
if(auto pos = strpos(input, "}}")) {
|
||||
string temp = substr(input, pos() + 2);
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
|
@@ -1,31 +1,12 @@
|
||||
#ifndef NALL_FOREACH_HPP
|
||||
#define NALL_FOREACH_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <nall/concept.hpp>
|
||||
|
||||
#undef foreach
|
||||
#define foreach(iter, object) \
|
||||
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(unsigned foreach_counter = 0, foreach_limit = container_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 <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) {
|
||||
return object.count();
|
||||
}
|
||||
|
||||
template<typename T> unsigned foreach_size(const T& object, typename mp_enable_if<has_length<T>>::type = 0) {
|
||||
return object.length();
|
||||
}
|
||||
|
||||
template<typename T> unsigned foreach_size(const T& object, typename mp_enable_if<has_size<T>>::type = 0) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -1,190 +1,90 @@
|
||||
#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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
#undef cat
|
||||
#undef TL
|
||||
#undef PL
|
||||
#undef CL
|
||||
|
||||
#endif
|
||||
|
@@ -93,9 +93,9 @@ struct Keyboard {
|
||||
if(!strbegin(name, "KB")) return 0;
|
||||
ltrim(s, "KB");
|
||||
unsigned id = strunsigned(s);
|
||||
int pos = strpos(s, "::");
|
||||
if(pos < 0) return 0;
|
||||
s = substr(s, pos + 2);
|
||||
auto pos = strpos(s, "::");
|
||||
if(!pos) return 0;
|
||||
s = substr(s, pos() + 2);
|
||||
for(unsigned i = 0; i < Limit; i++) {
|
||||
if(s == KeyboardScancodeName[i]) return Base + Size * id + i;
|
||||
}
|
||||
@@ -190,9 +190,9 @@ struct Mouse {
|
||||
if(!strbegin(name, "MS")) return 0;
|
||||
ltrim(s, "MS");
|
||||
unsigned id = strunsigned(s);
|
||||
int pos = strpos(s, "::");
|
||||
if(pos < 0) return 0;
|
||||
s = substr(s, pos + 2);
|
||||
auto pos = strpos(s, "::");
|
||||
if(!pos) return 0;
|
||||
s = substr(s, pos() + 2);
|
||||
for(unsigned i = 0; i < Limit; i++) {
|
||||
if(s == MouseScancodeName[i]) return Base + Size * id + i;
|
||||
}
|
||||
@@ -314,9 +314,9 @@ struct Joypad {
|
||||
if(!strbegin(name, "JP")) return 0;
|
||||
ltrim(s, "JP");
|
||||
unsigned id = strunsigned(s);
|
||||
int pos = strpos(s, "::");
|
||||
if(pos < 0) return 0;
|
||||
s = substr(s, pos + 2);
|
||||
auto pos = strpos(s, "::");
|
||||
if(!pos) return 0;
|
||||
s = substr(s, pos() + 2);
|
||||
for(unsigned i = 0; i < Limit; i++) {
|
||||
if(s == JoypadScancodeName[i]) return Base + Size * id + i;
|
||||
}
|
||||
|
@@ -211,7 +211,7 @@ inline void FileDialog::filterBoxChanged() {
|
||||
if(filters.length() == 0) {
|
||||
fileSystemModel->setNameFilters(QStringList() << "*");
|
||||
} else {
|
||||
filters = substr(filters, strpos(filters, "("));
|
||||
filters = substr(filters, strpos(filters, "(")());
|
||||
ltrim(filters, "(");
|
||||
rtrim(filters, ")");
|
||||
lstring part;
|
||||
|
20
snesreader/nall/random.hpp
Normal file
20
snesreader/nall/random.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef NALL_RANDOM_HPP
|
||||
#define NALL_RANDOM_HPP
|
||||
|
||||
namespace nall {
|
||||
//pseudo-random number generator
|
||||
inline unsigned prng() {
|
||||
static unsigned n = 0;
|
||||
return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320);
|
||||
}
|
||||
|
||||
struct random_cyclic {
|
||||
unsigned seed;
|
||||
inline unsigned operator()() {
|
||||
return seed = (seed >> 1) ^ (((seed & 1) - 1) & 0xedb88320);
|
||||
}
|
||||
random_cyclic() : seed(0) {}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@@ -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
|
||||
|
864
snesreader/nall/snes/info.hpp
Normal file
864
snesreader/nall/snes/info.hpp
Normal file
@@ -0,0 +1,864 @@
|
||||
#ifndef NALL_SNES_INFO_HPP
|
||||
#define NALL_SNES_INFO_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
class snes_information {
|
||||
public:
|
||||
string xml_memory_map;
|
||||
|
||||
inline snes_information(const uint8_t *data, unsigned size);
|
||||
|
||||
private:
|
||||
inline void read_header(const uint8_t *data, unsigned size);
|
||||
inline unsigned find_header(const uint8_t *data, unsigned size);
|
||||
inline unsigned score_header(const uint8_t *data, unsigned size, unsigned addr);
|
||||
inline unsigned gameboy_ram_size(const uint8_t *data, unsigned size);
|
||||
inline bool gameboy_has_rtc(const uint8_t *data, unsigned size);
|
||||
|
||||
enum HeaderField {
|
||||
CartName = 0x00,
|
||||
Mapper = 0x15,
|
||||
RomType = 0x16,
|
||||
RomSize = 0x17,
|
||||
RamSize = 0x18,
|
||||
CartRegion = 0x19,
|
||||
Company = 0x1a,
|
||||
Version = 0x1b,
|
||||
Complement = 0x1c, //inverse checksum
|
||||
Checksum = 0x1e,
|
||||
ResetVector = 0x3c,
|
||||
};
|
||||
|
||||
enum Mode {
|
||||
ModeNormal,
|
||||
ModeBsxSlotted,
|
||||
ModeBsx,
|
||||
ModeSufamiTurbo,
|
||||
ModeSuperGameBoy,
|
||||
};
|
||||
|
||||
enum Type {
|
||||
TypeNormal,
|
||||
TypeBsxSlotted,
|
||||
TypeBsxBios,
|
||||
TypeBsx,
|
||||
TypeSufamiTurboBios,
|
||||
TypeSufamiTurbo,
|
||||
TypeSuperGameBoy1Bios,
|
||||
TypeSuperGameBoy2Bios,
|
||||
TypeGameBoy,
|
||||
TypeUnknown,
|
||||
};
|
||||
|
||||
enum Region {
|
||||
NTSC,
|
||||
PAL,
|
||||
};
|
||||
|
||||
enum MemoryMapper {
|
||||
LoROM,
|
||||
HiROM,
|
||||
ExLoROM,
|
||||
ExHiROM,
|
||||
SuperFXROM,
|
||||
SA1ROM,
|
||||
SPC7110ROM,
|
||||
BSCLoROM,
|
||||
BSCHiROM,
|
||||
BSXROM,
|
||||
STROM,
|
||||
};
|
||||
|
||||
enum DSP1MemoryMapper {
|
||||
DSP1Unmapped,
|
||||
DSP1LoROM1MB,
|
||||
DSP1LoROM2MB,
|
||||
DSP1HiROM,
|
||||
};
|
||||
|
||||
bool loaded; //is a base cartridge inserted?
|
||||
unsigned crc32; //crc32 of all cartridges (base+slot(s))
|
||||
unsigned rom_size;
|
||||
unsigned ram_size;
|
||||
|
||||
Mode mode;
|
||||
Type type;
|
||||
Region region;
|
||||
MemoryMapper mapper;
|
||||
DSP1MemoryMapper dsp1_mapper;
|
||||
|
||||
bool has_bsx_slot;
|
||||
bool has_superfx;
|
||||
bool has_sa1;
|
||||
bool has_srtc;
|
||||
bool has_sdd1;
|
||||
bool has_spc7110;
|
||||
bool has_spc7110rtc;
|
||||
bool has_cx4;
|
||||
bool has_dsp1;
|
||||
bool has_dsp2;
|
||||
bool has_dsp3;
|
||||
bool has_dsp4;
|
||||
bool has_obc1;
|
||||
bool has_st010;
|
||||
bool has_st011;
|
||||
bool has_st018;
|
||||
};
|
||||
|
||||
snes_information::snes_information(const uint8_t *data, unsigned size) {
|
||||
read_header(data, size);
|
||||
|
||||
string xml = "<?xml version='1.0' encoding='UTF-8'?>\n";
|
||||
|
||||
if(type == TypeBsx) {
|
||||
xml << "<cartridge/>";
|
||||
xml_memory_map = xml;
|
||||
return;
|
||||
}
|
||||
|
||||
if(type == TypeSufamiTurbo) {
|
||||
xml << "<cartridge/>";
|
||||
xml_memory_map = xml;
|
||||
return;
|
||||
}
|
||||
|
||||
if(type == TypeGameBoy) {
|
||||
xml << "<cartridge rtc='" << gameboy_has_rtc(data, size) << "'>\n";
|
||||
if(gameboy_ram_size(data, size) > 0) {
|
||||
xml << " <ram size='" << strhex(gameboy_ram_size(data, size)) << "'/>\n";
|
||||
}
|
||||
xml << "</cartridge>\n";
|
||||
xml_memory_map = xml;
|
||||
return;
|
||||
}
|
||||
|
||||
xml << "<cartridge";
|
||||
if(region == NTSC) {
|
||||
xml << " region='NTSC'";
|
||||
} else {
|
||||
xml << " region='PAL'";
|
||||
}
|
||||
xml << ">\n";
|
||||
|
||||
if(type == TypeSuperGameBoy1Bios) {
|
||||
xml << " <rom>\n";
|
||||
xml << " <map mode='linear' address='00-7f:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='80-ff:8000-ffff'/>\n";
|
||||
xml << " </rom>\n";
|
||||
xml << " <supergameboy revision='1'>\n";
|
||||
xml << " <mmio>\n";
|
||||
xml << " <map address='00-3f:6000-7fff'/>\n";
|
||||
xml << " <map address='80-bf:6000-7fff'/>\n";
|
||||
xml << " </mmio>\n";
|
||||
xml << " </supergameboy>\n";
|
||||
} else if(type == TypeSuperGameBoy2Bios) {
|
||||
xml << " <rom>\n";
|
||||
xml << " <map mode='linear' address='00-7f:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='80-ff:8000-ffff'/>\n";
|
||||
xml << " </rom>\n";
|
||||
xml << " <supergameboy revision='2'>\n";
|
||||
xml << " <mmio>\n";
|
||||
xml << " <map address='00-3f:6000-7fff'/>\n";
|
||||
xml << " <map address='80-bf:6000-7fff'/>\n";
|
||||
xml << " </mmio>\n";
|
||||
xml << " </supergameboy>\n";
|
||||
} else if(has_spc7110) {
|
||||
xml << " <rom>\n";
|
||||
xml << " <map mode='shadow' address='00-0f:8000-ffff'/>\n";
|
||||
xml << " <map mode='shadow' address='80-bf:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='c0-cf:0000-ffff'/>\n";
|
||||
xml << " </rom>\n";
|
||||
|
||||
xml << " <spc7110>\n";
|
||||
xml << " <mcu>\n";
|
||||
xml << " <map address='d0-ff:0000-ffff' offset='100000' size='" << strhex(size - 0x100000) << "'/>\n";
|
||||
xml << " </mcu>\n";
|
||||
xml << " <ram size='" << strhex(ram_size) << "'>\n";
|
||||
xml << " <map mode='linear' address='00:6000-7fff'/>\n";
|
||||
xml << " <map mode='linear' address='30:6000-7fff'/>\n";
|
||||
xml << " </ram>\n";
|
||||
xml << " <mmio>\n";
|
||||
xml << " <map address='00-3f:4800-483f'/>\n";
|
||||
xml << " <map address='80-bf:4800-483f'/>\n";
|
||||
xml << " </mmio>\n";
|
||||
if(has_spc7110rtc) {
|
||||
xml << " <rtc>\n";
|
||||
xml << " <map address='00-3f:4840-4842'/>\n";
|
||||
xml << " <map address='80-bf:4840-4842'/>\n";
|
||||
xml << " </rtc>\n";
|
||||
}
|
||||
xml << " <dcu>\n";
|
||||
xml << " <map address='50:0000-ffff'/>\n";
|
||||
xml << " </dcu>\n";
|
||||
xml << " </spc7110>\n";
|
||||
} else if(mapper == LoROM) {
|
||||
xml << " <rom>\n";
|
||||
xml << " <map mode='linear' address='00-7f:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='80-ff: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";
|
||||
if((rom_size > 0x200000) || (ram_size > 32 * 1024)) {
|
||||
xml << " <map mode='linear' address='70-7f:0000-7fff'/>\n";
|
||||
xml << " <map mode='linear' address='f0-ff:0000-7fff'/>\n";
|
||||
} else {
|
||||
xml << " <map mode='linear' address='70-7f:0000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='f0-ff:0000-ffff'/>\n";
|
||||
}
|
||||
xml << " </ram>\n";
|
||||
}
|
||||
} else if(mapper == HiROM) {
|
||||
xml << " <rom>\n";
|
||||
xml << " <map mode='shadow' address='00-3f:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='40-7f:0000-ffff'/>\n";
|
||||
xml << " <map mode='shadow' address='80-bf:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='c0-ff:0000-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";
|
||||
if((rom_size > 0x200000) || (ram_size > 32 * 1024)) {
|
||||
xml << " <map mode='linear' address='70-7f:0000-7fff'/>\n";
|
||||
} else {
|
||||
xml << " <map mode='linear' address='70-7f:0000-ffff'/>\n";
|
||||
}
|
||||
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";
|
||||
xml << " <map mode='linear' address='40-7f:0000-ffff' offset='400000'/>\n";
|
||||
xml << " <map mode='shadow' address='80-bf:8000-ffff' offset='000000'/>\n";
|
||||
xml << " <map mode='linear' address='c0-ff:0000-ffff' offset='000000'/>\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";
|
||||
if((rom_size > 0x200000) || (ram_size > 32 * 1024)) {
|
||||
xml << " <map mode='linear' address='70-7f:0000-7fff'/>\n";
|
||||
} else {
|
||||
xml << " <map mode='linear' address='70-7f:0000-ffff'/>\n";
|
||||
}
|
||||
xml << " </ram>\n";
|
||||
}
|
||||
} else if(mapper == SuperFXROM) {
|
||||
xml << " <superfx revision='2'>\n";
|
||||
xml << " <rom>\n";
|
||||
xml << " <map mode='linear' address='00-3f:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='40-5f:0000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='80-bf:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='c0-df:0000-ffff'/>\n";
|
||||
xml << " </rom>\n";
|
||||
xml << " <ram size='" << strhex(ram_size) << "'>\n";
|
||||
xml << " <map mode='linear' address='00-3f:6000-7fff' size='2000'/>\n";
|
||||
xml << " <map mode='linear' address='60-7f:0000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='80-bf:6000-7fff' size='2000'/>\n";
|
||||
xml << " <map mode='linear' address='e0-ff:0000-ffff'/>\n";
|
||||
xml << " </ram>\n";
|
||||
xml << " <mmio>\n";
|
||||
xml << " <map address='00-3f:3000-32ff'/>\n";
|
||||
xml << " <map address='80-bf:3000-32ff'/>\n";
|
||||
xml << " </mmio>\n";
|
||||
xml << " </superfx>\n";
|
||||
} else if(mapper == SA1ROM) {
|
||||
xml << " <sa1>\n";
|
||||
xml << " <rom>\n";
|
||||
xml << " <map mode='linear' address='00-3f:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='80-bf:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='c0-ff:0000-ffff'/>\n";
|
||||
xml << " </rom>\n";
|
||||
xml << " <iram size='800'>\n";
|
||||
xml << " <map mode='linear' address='00-3f:3000-37ff'/>\n";
|
||||
xml << " <map mode='linear' address='80-bf:3000-37ff'/>\n";
|
||||
xml << " </iram>\n";
|
||||
xml << " <bwram size='" << strhex(ram_size) << "'>\n";
|
||||
xml << " <map mode='linear' address='00-3f:6000-7fff'/>\n";
|
||||
xml << " <map mode='linear' address='40-4f:0000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='80-bf:6000-7fff'/>\n";
|
||||
xml << " </bwram>\n";
|
||||
xml << " <mmio>\n";
|
||||
xml << " <map address='00-3f:2200-23ff'/>\n";
|
||||
xml << " <map address='80-bf:2200-23ff'/>\n";
|
||||
xml << " </mmio>\n";
|
||||
xml << " </sa1>\n";
|
||||
} else if(mapper == BSCLoROM) {
|
||||
xml << " <rom>\n";
|
||||
xml << " <map mode='linear' address='00-1f:8000-ffff' offset='000000'/>\n";
|
||||
xml << " <map mode='linear' address='20-3f:8000-ffff' offset='100000'/>\n";
|
||||
xml << " <map mode='linear' address='80-9f:8000-ffff' offset='200000'/>\n";
|
||||
xml << " <map mode='linear' address='a0-bf:8000-ffff' offset='100000'/>\n";
|
||||
xml << " </rom>\n";
|
||||
xml << " <ram size='" << strhex(ram_size) << "'>\n";
|
||||
xml << " <map mode='linear' address='70-7f:0000-7fff'/>\n";
|
||||
xml << " <map mode='linear' address='f0-ff:0000-7fff'/>\n";
|
||||
xml << " </ram>\n";
|
||||
xml << " <bsx>\n";
|
||||
xml << " <slot>\n";
|
||||
xml << " <map mode='linear' address='c0-ef:0000-ffff'/>\n";
|
||||
xml << " </slot>\n";
|
||||
xml << " </bsx>\n";
|
||||
} else if(mapper == BSCHiROM) {
|
||||
xml << " <rom>\n";
|
||||
xml << " <map mode='shadow' address='00-1f:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='40-5f:0000-ffff'/>\n";
|
||||
xml << " <map mode='shadow' address='80-9f:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='c0-df:0000-ffff'/>\n";
|
||||
xml << " </rom>\n";
|
||||
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 << " </ram>\n";
|
||||
xml << " <bsx>\n";
|
||||
xml << " <slot>\n";
|
||||
xml << " <map mode='shadow' address='20-3f:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='60-7f:0000-ffff'/>\n";
|
||||
xml << " <map mode='shadow' address='a0-bf:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='e0-ff:0000-ffff'/>\n";
|
||||
xml << " </slot>\n";
|
||||
xml << " </bsx>\n";
|
||||
} else if(mapper == BSXROM) {
|
||||
xml << " <rom>\n";
|
||||
xml << " <map mode='linear' address='00-3f:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='80-bf:8000-ffff'/>\n";
|
||||
xml << " </rom>\n";
|
||||
xml << " <bsx>\n";
|
||||
xml << " <mmio>\n";
|
||||
xml << " <map address='00-3f:5000-5fff'/>\n";
|
||||
xml << " <map address='80-bf:5000-5fff'/>\n";
|
||||
xml << " </mmio>\n";
|
||||
xml << " </bsx>\n";
|
||||
} else if(mapper == STROM) {
|
||||
xml << " <rom>\n";
|
||||
xml << " <map mode='linear' address='00-1f:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='80-9f:8000-ffff'/>\n";
|
||||
xml << " </rom>\n";
|
||||
xml << " <sufamiturbo>\n";
|
||||
xml << " <slot id='A'>\n";
|
||||
xml << " <rom>\n";
|
||||
xml << " <map mode='linear' address='20-3f:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='a0-bf:8000-ffff'/>\n";
|
||||
xml << " </rom>\n";
|
||||
xml << " <ram>\n";
|
||||
xml << " <map mode='linear' address='60-63:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='e0-e3:8000-ffff'/>\n";
|
||||
xml << " </ram>\n";
|
||||
xml << " </slot>\n";
|
||||
xml << " <slot id='B'>\n";
|
||||
xml << " <rom>\n";
|
||||
xml << " <map mode='linear' address='40-5f:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='c0-df:8000-ffff'/>\n";
|
||||
xml << " </rom>\n";
|
||||
xml << " <ram>\n";
|
||||
xml << " <map mode='linear' address='70-73:8000-ffff'/>\n";
|
||||
xml << " <map mode='linear' address='f0-f3:8000-ffff'/>\n";
|
||||
xml << " </ram>\n";
|
||||
xml << " </slot>\n";
|
||||
xml << " </sufamiturbo>\n";
|
||||
}
|
||||
|
||||
if(has_srtc) {
|
||||
xml << " <srtc>\n";
|
||||
xml << " <mmio>\n";
|
||||
xml << " <map address='00-3f:2800-2801'/>\n";
|
||||
xml << " <map address='80-bf:2800-2801'/>\n";
|
||||
xml << " </mmio>\n";
|
||||
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";
|
||||
xml << " <map address='00-3f:6000-7fff'/>\n";
|
||||
xml << " <map address='80-bf:6000-7fff'/>\n";
|
||||
xml << " </mmio>\n";
|
||||
xml << " </cx4>\n";
|
||||
}
|
||||
|
||||
if(has_dsp1) {
|
||||
xml << " <necdsp program='DSP-1B'>\n";
|
||||
if(dsp1_mapper == DSP1LoROM1MB) {
|
||||
xml << " <dr>\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";
|
||||
} else if(dsp1_mapper == DSP1LoROM2MB) {
|
||||
xml << " <dr>\n";
|
||||
xml << " <map address='60-6f:0000-3fff'/>\n";
|
||||
xml << " <map address='e0-ef:0000-3fff'/>\n";
|
||||
xml << " </dr>\n";
|
||||
xml << " <sr>\n";
|
||||
xml << " <map address='60-6f:4000-7fff'/>\n";
|
||||
xml << " <map address='e0-ef:4000-7fff'/>\n";
|
||||
xml << " </sr>\n";
|
||||
} else if(dsp1_mapper == DSP1HiROM) {
|
||||
xml << " <dr>\n";
|
||||
xml << " <map address='00-1f:6000-6fff'/>\n";
|
||||
xml << " <map address='80-9f:6000-6fff'/>\n";
|
||||
xml << " </dr>\n";
|
||||
xml << " <sr>\n";
|
||||
xml << " <map address='00-1f:7000-7fff'/>\n";
|
||||
xml << " <map address='80-9f:7000-7fff'/>\n";
|
||||
xml << " </sr>\n";
|
||||
}
|
||||
xml << " </necdsp>\n";
|
||||
}
|
||||
|
||||
if(has_dsp2) {
|
||||
xml << " <necdsp program='DSP-2'>\n";
|
||||
xml << " <dr>\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";
|
||||
}
|
||||
|
||||
if(has_dsp3) {
|
||||
xml << " <necdsp program='DSP-3'>\n";
|
||||
xml << " <dr>\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";
|
||||
}
|
||||
|
||||
if(has_dsp4) {
|
||||
xml << " <necdsp program='DSP-4'>\n";
|
||||
xml << " <dr>\n";
|
||||
xml << " <map address='30-3f:8000-bfff'/>\n";
|
||||
xml << " <map address='b0-bf:8000-bfff'/>\n";
|
||||
xml << " </dr>\n";
|
||||
xml << " <sr>\n";
|
||||
xml << " <map address='30-3f:c000-ffff'/>\n";
|
||||
xml << " <map address='b0-bf:c000-ffff'/>\n";
|
||||
xml << " </sr>\n";
|
||||
xml << " </necdsp>\n";
|
||||
}
|
||||
|
||||
if(has_obc1) {
|
||||
xml << " <obc1>\n";
|
||||
xml << " <mmio>\n";
|
||||
xml << " <map address='00-3f:6000-7fff'/>\n";
|
||||
xml << " <map address='80-bf:6000-7fff'/>\n";
|
||||
xml << " </mmio>\n";
|
||||
xml << " </obc1>\n";
|
||||
}
|
||||
|
||||
if(has_st010) {
|
||||
xml << " <setadsp program='ST-0010'>\n";
|
||||
xml << " <mmio>\n";
|
||||
xml << " <map address='68-6f:0000-0fff'/>\n";
|
||||
xml << " <map address='e8-ef:0000-0fff'/>\n";
|
||||
xml << " </mmio>\n";
|
||||
xml << " </setadsp>\n";
|
||||
}
|
||||
|
||||
if(has_st011) {
|
||||
//ST-0011 addresses not verified; chip is unsupported
|
||||
xml << " <setadsp program='ST-0011'>\n";
|
||||
xml << " <mmio>\n";
|
||||
xml << " <map address='68-6f:0000-0fff'/>\n";
|
||||
xml << " <map address='e8-ef:0000-0fff'/>\n";
|
||||
xml << " </mmio>\n";
|
||||
xml << " </setadsp>\n";
|
||||
}
|
||||
|
||||
if(has_st018) {
|
||||
xml << " <setarisc program='ST-0018'>\n";
|
||||
xml << " <mmio>\n";
|
||||
xml << " <map address='00-3f:3800-38ff'/>\n";
|
||||
xml << " <map address='80-bf:3800-38ff'/>\n";
|
||||
xml << " </mmio>\n";
|
||||
xml << " </setarisc>\n";
|
||||
}
|
||||
|
||||
xml << "</cartridge>\n";
|
||||
xml_memory_map = xml;
|
||||
}
|
||||
|
||||
void snes_information::read_header(const uint8_t *data, unsigned size) {
|
||||
type = TypeUnknown;
|
||||
mapper = LoROM;
|
||||
dsp1_mapper = DSP1Unmapped;
|
||||
region = NTSC;
|
||||
rom_size = size;
|
||||
ram_size = 0;
|
||||
|
||||
has_bsx_slot = false;
|
||||
has_superfx = false;
|
||||
has_sa1 = false;
|
||||
has_srtc = false;
|
||||
has_sdd1 = false;
|
||||
has_spc7110 = false;
|
||||
has_spc7110rtc = false;
|
||||
has_cx4 = false;
|
||||
has_dsp1 = false;
|
||||
has_dsp2 = false;
|
||||
has_dsp3 = false;
|
||||
has_dsp4 = false;
|
||||
has_obc1 = false;
|
||||
has_st010 = false;
|
||||
has_st011 = false;
|
||||
has_st018 = false;
|
||||
|
||||
//=====================
|
||||
//detect Game Boy carts
|
||||
//=====================
|
||||
|
||||
if(size >= 0x0140) {
|
||||
if(data[0x0104] == 0xce && data[0x0105] == 0xed && data[0x0106] == 0x66 && data[0x0107] == 0x66
|
||||
&& data[0x0108] == 0xcc && data[0x0109] == 0x0d && data[0x010a] == 0x00 && data[0x010b] == 0x0b) {
|
||||
type = TypeGameBoy;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned index = find_header(data, size);
|
||||
const uint8_t mapperid = data[index + Mapper];
|
||||
const uint8_t rom_type = data[index + RomType];
|
||||
const uint8_t rom_size = data[index + RomSize];
|
||||
const uint8_t company = data[index + Company];
|
||||
const uint8_t regionid = data[index + CartRegion] & 0x7f;
|
||||
|
||||
ram_size = 1024 << (data[index + RamSize] & 7);
|
||||
if(ram_size == 1024) ram_size = 0; //no RAM present
|
||||
|
||||
//0, 1, 13 = NTSC; 2 - 12 = PAL
|
||||
region = (regionid <= 1 || regionid >= 13) ? NTSC : PAL;
|
||||
|
||||
//=======================
|
||||
//detect BS-X flash carts
|
||||
//=======================
|
||||
|
||||
if(data[index + 0x13] == 0x00 || data[index + 0x13] == 0xff) {
|
||||
if(data[index + 0x14] == 0x00) {
|
||||
const uint8_t n15 = data[index + 0x15];
|
||||
if(n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c || n15 == 0xbc || n15 == 0xfc) {
|
||||
if(data[index + 0x1a] == 0x33 || data[index + 0x1a] == 0xff) {
|
||||
type = TypeBsx;
|
||||
mapper = BSXROM;
|
||||
region = NTSC; //BS-X only released in Japan
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=========================
|
||||
//detect Sufami Turbo carts
|
||||
//=========================
|
||||
|
||||
if(!memcmp(data, "BANDAI SFC-ADX", 14)) {
|
||||
if(!memcmp(data + 16, "SFC-ADX BACKUP", 14)) {
|
||||
type = TypeSufamiTurboBios;
|
||||
} else {
|
||||
type = TypeSufamiTurbo;
|
||||
}
|
||||
mapper = STROM;
|
||||
region = NTSC; //Sufami Turbo only released in Japan
|
||||
return; //RAM size handled outside this routine
|
||||
}
|
||||
|
||||
//==========================
|
||||
//detect Super Game Boy BIOS
|
||||
//==========================
|
||||
|
||||
if(!memcmp(data + index, "Super GAMEBOY2", 14)) {
|
||||
type = TypeSuperGameBoy2Bios;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!memcmp(data + index, "Super GAMEBOY", 13)) {
|
||||
type = TypeSuperGameBoy1Bios;
|
||||
return;
|
||||
}
|
||||
|
||||
//=====================
|
||||
//detect standard carts
|
||||
//=====================
|
||||
|
||||
//detect presence of BS-X flash cartridge connector (reads extended header information)
|
||||
if(data[index - 14] == 'Z') {
|
||||
if(data[index - 11] == 'J') {
|
||||
uint8_t n13 = data[index - 13];
|
||||
if((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9')) {
|
||||
if(company == 0x33 || (data[index - 10] == 0x00 && data[index - 4] == 0x00)) {
|
||||
has_bsx_slot = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(has_bsx_slot) {
|
||||
if(!memcmp(data + index, "Satellaview BS-X ", 21)) {
|
||||
//BS-X base cart
|
||||
type = TypeBsxBios;
|
||||
mapper = BSXROM;
|
||||
region = NTSC; //BS-X only released in Japan
|
||||
return; //RAM size handled internally by load_cart_bsx() -> BSXCart class
|
||||
} else {
|
||||
type = TypeBsxSlotted;
|
||||
mapper = (index == 0x7fc0 ? BSCLoROM : BSCHiROM);
|
||||
region = NTSC; //BS-X slotted cartridges only released in Japan
|
||||
}
|
||||
} else {
|
||||
//standard cart
|
||||
type = TypeNormal;
|
||||
|
||||
if(index == 0x7fc0 && size >= 0x401000) {
|
||||
mapper = ExLoROM;
|
||||
} else if(index == 0x7fc0 && mapperid == 0x32) {
|
||||
mapper = ExLoROM;
|
||||
} else if(index == 0x7fc0) {
|
||||
mapper = LoROM;
|
||||
} else if(index == 0xffc0) {
|
||||
mapper = HiROM;
|
||||
} else { //index == 0x40ffc0
|
||||
mapper = ExHiROM;
|
||||
}
|
||||
}
|
||||
|
||||
if(mapperid == 0x20 && (rom_type == 0x13 || rom_type == 0x14 || rom_type == 0x15 || rom_type == 0x1a)) {
|
||||
has_superfx = true;
|
||||
mapper = SuperFXROM;
|
||||
ram_size = 1024 << (data[index - 3] & 7);
|
||||
if(ram_size == 1024) ram_size = 0;
|
||||
}
|
||||
|
||||
if(mapperid == 0x23 && (rom_type == 0x32 || rom_type == 0x34 || rom_type == 0x35)) {
|
||||
has_sa1 = true;
|
||||
mapper = SA1ROM;
|
||||
}
|
||||
|
||||
if(mapperid == 0x35 && rom_type == 0x55) {
|
||||
has_srtc = true;
|
||||
}
|
||||
|
||||
if(mapperid == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) {
|
||||
has_sdd1 = true;
|
||||
}
|
||||
|
||||
if(mapperid == 0x3a && (rom_type == 0xf5 || rom_type == 0xf9)) {
|
||||
has_spc7110 = true;
|
||||
has_spc7110rtc = (rom_type == 0xf9);
|
||||
mapper = SPC7110ROM;
|
||||
}
|
||||
|
||||
if(mapperid == 0x20 && rom_type == 0xf3) {
|
||||
has_cx4 = true;
|
||||
}
|
||||
|
||||
if((mapperid == 0x20 || mapperid == 0x21) && rom_type == 0x03) {
|
||||
has_dsp1 = true;
|
||||
}
|
||||
|
||||
if(mapperid == 0x30 && rom_type == 0x05 && company != 0xb2) {
|
||||
has_dsp1 = true;
|
||||
}
|
||||
|
||||
if(mapperid == 0x31 && (rom_type == 0x03 || rom_type == 0x05)) {
|
||||
has_dsp1 = true;
|
||||
}
|
||||
|
||||
if(has_dsp1 == true) {
|
||||
if((mapperid & 0x2f) == 0x20 && size <= 0x100000) {
|
||||
dsp1_mapper = DSP1LoROM1MB;
|
||||
} else if((mapperid & 0x2f) == 0x20) {
|
||||
dsp1_mapper = DSP1LoROM2MB;
|
||||
} else if((mapperid & 0x2f) == 0x21) {
|
||||
dsp1_mapper = DSP1HiROM;
|
||||
}
|
||||
}
|
||||
|
||||
if(mapperid == 0x20 && rom_type == 0x05) {
|
||||
has_dsp2 = true;
|
||||
}
|
||||
|
||||
if(mapperid == 0x30 && rom_type == 0x05 && company == 0xb2) {
|
||||
has_dsp3 = true;
|
||||
}
|
||||
|
||||
if(mapperid == 0x30 && rom_type == 0x03) {
|
||||
has_dsp4 = true;
|
||||
}
|
||||
|
||||
if(mapperid == 0x30 && rom_type == 0x25) {
|
||||
has_obc1 = true;
|
||||
}
|
||||
|
||||
if(mapperid == 0x30 && rom_type == 0xf6 && rom_size >= 10) {
|
||||
has_st010 = true;
|
||||
}
|
||||
|
||||
if(mapperid == 0x30 && rom_type == 0xf6 && rom_size < 10) {
|
||||
has_st011 = true;
|
||||
}
|
||||
|
||||
if(mapperid == 0x30 && rom_type == 0xf5) {
|
||||
has_st018 = true;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned snes_information::find_header(const uint8_t *data, unsigned size) {
|
||||
unsigned score_lo = score_header(data, size, 0x007fc0);
|
||||
unsigned score_hi = score_header(data, size, 0x00ffc0);
|
||||
unsigned score_ex = score_header(data, size, 0x40ffc0);
|
||||
if(score_ex) score_ex += 4; //favor ExHiROM on images > 32mbits
|
||||
|
||||
if(score_lo >= score_hi && score_lo >= score_ex) {
|
||||
return 0x007fc0;
|
||||
} else if(score_hi >= score_ex) {
|
||||
return 0x00ffc0;
|
||||
} else {
|
||||
return 0x40ffc0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned snes_information::score_header(const uint8_t *data, unsigned size, unsigned addr) {
|
||||
if(size < addr + 64) return 0; //image too small to contain header at this location?
|
||||
int score = 0;
|
||||
|
||||
uint16_t resetvector = data[addr + ResetVector] | (data[addr + ResetVector + 1] << 8);
|
||||
uint16_t checksum = data[addr + Checksum ] | (data[addr + Checksum + 1] << 8);
|
||||
uint16_t complement = data[addr + Complement ] | (data[addr + Complement + 1] << 8);
|
||||
|
||||
uint8_t resetop = data[(addr & ~0x7fff) | (resetvector & 0x7fff)]; //first opcode executed upon reset
|
||||
uint8_t mapper = data[addr + Mapper] & ~0x10; //mask off irrelevent FastROM-capable bit
|
||||
|
||||
//$00:[000-7fff] contains uninitialized RAM and MMIO.
|
||||
//reset vector must point to ROM at $00:[8000-ffff] to be considered valid.
|
||||
if(resetvector < 0x8000) return 0;
|
||||
|
||||
//some images duplicate the header in multiple locations, and others have completely
|
||||
//invalid header information that cannot be relied upon.
|
||||
//below code will analyze the first opcode executed at the specified reset vector to
|
||||
//determine the probability that this is the correct header.
|
||||
|
||||
//most likely opcodes
|
||||
if(resetop == 0x78 //sei
|
||||
|| resetop == 0x18 //clc (clc; xce)
|
||||
|| resetop == 0x38 //sec (sec; xce)
|
||||
|| resetop == 0x9c //stz $nnnn (stz $4200)
|
||||
|| resetop == 0x4c //jmp $nnnn
|
||||
|| resetop == 0x5c //jml $nnnnnn
|
||||
) score += 8;
|
||||
|
||||
//plausible opcodes
|
||||
if(resetop == 0xc2 //rep #$nn
|
||||
|| resetop == 0xe2 //sep #$nn
|
||||
|| resetop == 0xad //lda $nnnn
|
||||
|| resetop == 0xae //ldx $nnnn
|
||||
|| resetop == 0xac //ldy $nnnn
|
||||
|| resetop == 0xaf //lda $nnnnnn
|
||||
|| resetop == 0xa9 //lda #$nn
|
||||
|| resetop == 0xa2 //ldx #$nn
|
||||
|| resetop == 0xa0 //ldy #$nn
|
||||
|| resetop == 0x20 //jsr $nnnn
|
||||
|| resetop == 0x22 //jsl $nnnnnn
|
||||
) score += 4;
|
||||
|
||||
//implausible opcodes
|
||||
if(resetop == 0x40 //rti
|
||||
|| resetop == 0x60 //rts
|
||||
|| resetop == 0x6b //rtl
|
||||
|| resetop == 0xcd //cmp $nnnn
|
||||
|| resetop == 0xec //cpx $nnnn
|
||||
|| resetop == 0xcc //cpy $nnnn
|
||||
) score -= 4;
|
||||
|
||||
//least likely opcodes
|
||||
if(resetop == 0x00 //brk #$nn
|
||||
|| resetop == 0x02 //cop #$nn
|
||||
|| resetop == 0xdb //stp
|
||||
|| resetop == 0x42 //wdm
|
||||
|| resetop == 0xff //sbc $nnnnnn,x
|
||||
) score -= 8;
|
||||
|
||||
//at times, both the header and reset vector's first opcode will match ...
|
||||
//fallback and rely on info validity in these cases to determine more likely header.
|
||||
|
||||
//a valid checksum is the biggest indicator of a valid header.
|
||||
if((checksum + complement) == 0xffff && (checksum != 0) && (complement != 0)) score += 4;
|
||||
|
||||
if(addr == 0x007fc0 && mapper == 0x20) score += 2; //0x20 is usually LoROM
|
||||
if(addr == 0x00ffc0 && mapper == 0x21) score += 2; //0x21 is usually HiROM
|
||||
if(addr == 0x007fc0 && mapper == 0x22) score += 2; //0x22 is usually ExLoROM
|
||||
if(addr == 0x40ffc0 && mapper == 0x25) score += 2; //0x25 is usually ExHiROM
|
||||
|
||||
if(data[addr + Company] == 0x33) score += 2; //0x33 indicates extended header
|
||||
if(data[addr + RomType] < 0x08) score++;
|
||||
if(data[addr + RomSize] < 0x10) score++;
|
||||
if(data[addr + RamSize] < 0x08) score++;
|
||||
if(data[addr + CartRegion] < 14) score++;
|
||||
|
||||
if(score < 0) score = 0;
|
||||
return score;
|
||||
}
|
||||
|
||||
unsigned snes_information::gameboy_ram_size(const uint8_t *data, unsigned size) {
|
||||
if(size < 512) return 0;
|
||||
switch(data[0x0149]) {
|
||||
case 0x00: return 0 * 1024;
|
||||
case 0x01: return 8 * 1024;
|
||||
case 0x02: return 8 * 1024;
|
||||
case 0x03: return 32 * 1024;
|
||||
case 0x04: return 128 * 1024;
|
||||
case 0x05: return 128 * 1024;
|
||||
default: return 128 * 1024;
|
||||
}
|
||||
}
|
||||
|
||||
bool snes_information::gameboy_has_rtc(const uint8_t *data, unsigned size) {
|
||||
if(size < 512) return false;
|
||||
if(data[0x0147] == 0x0f ||data[0x0147] == 0x10) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@@ -2,6 +2,8 @@
|
||||
#define NALL_STRING_HPP
|
||||
|
||||
#include <initializer_list>
|
||||
#include <nall/utility.hpp>
|
||||
|
||||
#include <nall/string/base.hpp>
|
||||
#include <nall/string/core.hpp>
|
||||
#include <nall/string/cast.hpp>
|
||||
@@ -11,6 +13,7 @@
|
||||
#include <nall/string/match.hpp>
|
||||
#include <nall/string/math.hpp>
|
||||
#include <nall/string/strl.hpp>
|
||||
#include <nall/string/strpos.hpp>
|
||||
#include <nall/string/trim.hpp>
|
||||
#include <nall/string/replace.hpp>
|
||||
#include <nall/string/split.hpp>
|
||||
|
@@ -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*);
|
||||
@@ -64,12 +35,13 @@ namespace nall {
|
||||
inline bool operator> (const char*) const;
|
||||
inline bool operator>=(const char*) const;
|
||||
|
||||
inline string& operator=(const string&);
|
||||
inline string& operator=(string&&);
|
||||
|
||||
inline string();
|
||||
inline string(const char*);
|
||||
inline string(const string&);
|
||||
inline string(string&&);
|
||||
inline string& operator=(const string&);
|
||||
inline string& operator=(string&&);
|
||||
inline ~string();
|
||||
|
||||
inline bool readfile(const char*);
|
||||
@@ -78,9 +50,9 @@ namespace nall {
|
||||
|
||||
protected:
|
||||
char *data;
|
||||
size_t size;
|
||||
unsigned size;
|
||||
|
||||
#if defined(QT_CORE_LIB)
|
||||
#if defined(QSTRING_H)
|
||||
public:
|
||||
inline operator QString() const;
|
||||
#endif
|
||||
@@ -98,29 +70,67 @@ 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 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
|
||||
|
@@ -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(QSTRING_H)
|
||||
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
|
||||
|
@@ -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;
|
||||
}
|
||||
@@ -19,38 +21,6 @@ int stricmp(const char *dest, const char *src) {
|
||||
return (int)chrlower(*dest) - (int)chrlower(*src);
|
||||
}
|
||||
|
||||
int strpos(const char *str, const char *key) {
|
||||
int ssl = strlen(str), ksl = strlen(key);
|
||||
|
||||
if(ksl > ssl) return -1;
|
||||
for(int i = 0; i <= ssl - ksl; i++) {
|
||||
if(!memcmp(str + i, key, ksl)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int qstrpos(const char *str, const char *key) {
|
||||
int ssl = strlen(str), ksl = strlen(key);
|
||||
|
||||
if(ksl > ssl) return -1;
|
||||
for(int i = 0; i <= ssl - ksl;) {
|
||||
uint8_t x = str[i];
|
||||
if(x == '\"' || x == '\'') {
|
||||
uint8_t z = i++;
|
||||
while(str[i] != x && i < ssl) i++;
|
||||
if(i >= ssl) i = z;
|
||||
}
|
||||
if(!memcmp(str + i, key, ksl)) {
|
||||
return i;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool strbegin(const char *str, const char *key) {
|
||||
int i, ssl = strlen(str), ksl = strlen(key);
|
||||
|
||||
@@ -97,4 +67,6 @@ bool striend(const char *str, const char *key) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -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;
|
||||
@@ -125,7 +127,7 @@ double strdouble(const char *str) {
|
||||
while(*str) {
|
||||
uint8_t x = *str++;
|
||||
if(x >= '0' && x <= '9') x -= '0';
|
||||
else if(x == '.') break; //break loop and read fractional part
|
||||
else if(x == '.' || x == ',') break; //break loop and read fractional part
|
||||
else return (double)result_integral; //invalid value, assume no fractional part
|
||||
result_integral = result_integral * 10 + x;
|
||||
}
|
||||
@@ -146,4 +148,6 @@ double strdouble(const char *str) {
|
||||
return !negate ? result : -result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -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);
|
||||
@@ -49,6 +49,20 @@ bool string::operator<=(const char *str) const { return strcmp(data, str) <= 0;
|
||||
bool string::operator> (const char *str) const { return strcmp(data, str) > 0; }
|
||||
bool string::operator>=(const char *str) const { return strcmp(data, str) >= 0; }
|
||||
|
||||
string& string::operator=(const string &value) {
|
||||
assign(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string& string::operator=(string &&source) {
|
||||
if(data) free(data);
|
||||
size = source.size;
|
||||
data = source.data;
|
||||
source.data = 0;
|
||||
source.size = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
string::string() {
|
||||
size = 64;
|
||||
data = (char*)malloc(size + 1);
|
||||
@@ -71,19 +85,6 @@ string::string(string &&source) {
|
||||
source.data = 0;
|
||||
}
|
||||
|
||||
string& string::operator=(const string &value) {
|
||||
assign(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string& string::operator=(string &&source) {
|
||||
if(data) free(data);
|
||||
size = source.size;
|
||||
data = source.data;
|
||||
source.data = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
string::~string() {
|
||||
free(data);
|
||||
}
|
||||
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
41
snesreader/nall/string/strpos.hpp
Normal file
41
snesreader/nall/string/strpos.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef NALL_STRING_STRPOS_HPP
|
||||
#define NALL_STRING_STRPOS_HPP
|
||||
|
||||
//usage example:
|
||||
//if(auto pos = strpos(str, key)) print(pos(), "\n");
|
||||
//prints position of key within str, only if it is found
|
||||
|
||||
namespace nall {
|
||||
|
||||
optional<unsigned> inline strpos(const char *str, const char *key) {
|
||||
unsigned ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl) return { false, 0 };
|
||||
|
||||
for(unsigned i = 0; i <= ssl - ksl; i++) {
|
||||
if(!memcmp(str + i, key, ksl)) return { true, i };
|
||||
}
|
||||
|
||||
return { false, 0 };
|
||||
}
|
||||
|
||||
optional<unsigned> inline qstrpos(const char *str, const char *key) {
|
||||
unsigned ssl = strlen(str), ksl = strlen(key);
|
||||
if(ksl > ssl) return { false, 0 };
|
||||
|
||||
for(unsigned i = 0; i <= ssl - ksl;) {
|
||||
uint8_t x = str[i];
|
||||
if(x == '\"' || x == '\'') {
|
||||
uint8_t z = i++;
|
||||
while(str[i] != x && i < ssl) i++;
|
||||
if(i >= ssl) i = z;
|
||||
}
|
||||
if(!memcmp(str + i, key, ksl)) return { true, i };
|
||||
i++;
|
||||
}
|
||||
|
||||
return { false, 0 };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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 {
|
||||
@@ -68,21 +65,25 @@ inline string xml_element::parse() const {
|
||||
}
|
||||
|
||||
if(strbegin(source, "<!--")) {
|
||||
signed pos = strpos(source, "-->");
|
||||
if(pos == -1) return "";
|
||||
source += pos + 3;
|
||||
continue;
|
||||
if(auto pos = strpos(source, "-->")) {
|
||||
source += pos() + 3;
|
||||
continue;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
if(strbegin(source, "<![CDATA[")) {
|
||||
signed pos = strpos(source, "]]>");
|
||||
if(pos == -1) return "";
|
||||
string cdata = substr(source, 9, pos - 9);
|
||||
data << cdata;
|
||||
offset += strlen(cdata);
|
||||
if(auto pos = strpos(source, "]]>")) {
|
||||
string cdata = substr(source, 9, pos() - 9);
|
||||
data << cdata;
|
||||
offset += strlen(cdata);
|
||||
|
||||
source += offset + 3;
|
||||
continue;
|
||||
source += offset + 3;
|
||||
continue;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
//reject illegal characters
|
||||
@@ -118,7 +119,7 @@ inline bool xml_element::parse_head(string data) {
|
||||
data.qreplace("\t", " ");
|
||||
data.qreplace("\r", " ");
|
||||
data.qreplace("\n", " ");
|
||||
while(qstrpos(data, " ") >= 0) data.qreplace(" ", " ");
|
||||
while(qstrpos(data, " ")) data.qreplace(" ", " ");
|
||||
data.qreplace(" =", "=");
|
||||
data.qreplace("= ", "=");
|
||||
rtrim(data);
|
||||
@@ -134,13 +135,13 @@ 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);
|
||||
attribute.append(attr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,24 +157,28 @@ inline bool xml_element::parse_body(const char *&data) {
|
||||
}
|
||||
|
||||
if(strbegin(data, "!--")) {
|
||||
signed offset = strpos(data, "-->");
|
||||
if(offset == -1) throw "...";
|
||||
data += offset + 3;
|
||||
continue;
|
||||
if(auto offset = strpos(data, "-->")) {
|
||||
data += offset() + 3;
|
||||
continue;
|
||||
} else {
|
||||
throw "...";
|
||||
}
|
||||
}
|
||||
|
||||
if(strbegin(data, "![CDATA[")) {
|
||||
signed offset = strpos(data, "]]>");
|
||||
if(offset == -1) throw "...";
|
||||
data += offset + 3;
|
||||
continue;
|
||||
if(auto offset = strpos(data, "]]>")) {
|
||||
data += offset() + 3;
|
||||
continue;
|
||||
} else {
|
||||
throw "...";
|
||||
}
|
||||
}
|
||||
|
||||
signed offset = strpos(data, ">");
|
||||
if(offset == -1) throw "...";
|
||||
auto offset = strpos(data, ">");
|
||||
if(!offset) throw "...";
|
||||
|
||||
string tag = substr(data, 0, offset);
|
||||
data += offset + 1;
|
||||
string tag = substr(data, 0, offset());
|
||||
data += offset() + 1;
|
||||
const char *content_begin = data;
|
||||
|
||||
bool self_terminating = false;
|
||||
@@ -191,48 +196,41 @@ 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);
|
||||
|
||||
data++;
|
||||
offset = strpos(data, ">");
|
||||
if(offset == -1) throw "...";
|
||||
auto offset = strpos(data, ">");
|
||||
if(!offset) throw "...";
|
||||
|
||||
tag = substr(data, 0, offset);
|
||||
data += offset + 1;
|
||||
tag = substr(data, 0, offset());
|
||||
data += offset() + 1;
|
||||
|
||||
tag.replace("\t", " ");
|
||||
tag.replace("\r", " ");
|
||||
tag.replace("\n", " ");
|
||||
while(strpos(tag, " ") >= 0) tag.replace(" ", " ");
|
||||
while(strpos(tag, " ")) tag.replace(" ", " ");
|
||||
rtrim(tag);
|
||||
|
||||
if(name != tag) throw "...";
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
element.add(elem);
|
||||
element.append(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 +239,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.append(node);
|
||||
}
|
||||
}
|
||||
|
||||
if(xml_validate(self) == false) throw "...";
|
||||
return self;
|
||||
} catch(const char*) {
|
||||
delete self;
|
||||
return 0;
|
||||
xml_element empty;
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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
|
@@ -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 {
|
||||
@@ -31,9 +20,18 @@ namespace nall {
|
||||
base_from_member(T value_) : value(value_) {}
|
||||
};
|
||||
|
||||
template<typename T> inline T* allocate(size_t size, const T &value) {
|
||||
template<typename T> class optional {
|
||||
bool valid;
|
||||
T value;
|
||||
public:
|
||||
inline operator bool() const { return valid; }
|
||||
inline const T& operator()() const { if(!valid) throw; return value; }
|
||||
inline optional(bool valid, const T &value) : valid(valid), value(value) {}
|
||||
};
|
||||
|
||||
template<typename T> inline T* allocate(unsigned size, const T &value) {
|
||||
T *array = new T[size];
|
||||
for(size_t i = 0; i < size; i++) array[i] = value;
|
||||
for(unsigned i = 0; i < size; i++) array[i] = value;
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user