Skip to main content

News

Topic: miniSphere 5.0.1 (Read 199977 times) previous topic - next topic

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: minisphere
Reply #30

Oh, that's interesting. I was pretty sure FBNil added the feature in 1.6... but I guess I was wrong then? :P


It was experimental, I think. FBNil made it non-experimental. But then 1.6 is still an alpha version of Sphere still to this day.
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: minisphere
Reply #31
So is there a safer (not subject to buffer overflows) version of sprintf() I can use?  sprintf_s() is VC++-only, and C99 support in VC is abysmal, meaning no snprintf() either.  See, my code for normalizing paths looks like this:

Code: (c) [Select]
char*
normalize_path(const char* path, const char* base_dir, char* out_abs_path)
{
char* game_path = "C:/cowz";
char* norm_path = strdup(path);
size_t path_len = strlen(norm_path);
for (char* c = norm_path; *c != '\0'; ++c) {
if (*c == '\\') *c = '/';
}
if (norm_path[0] == '/' || norm_path[1] == ':')
// absolute path - not allowed
return NULL;
bool is_homed = (strstr(norm_path, "~/") == norm_path);
if (is_homed) {
sprintf(out_abs_path, "%s/%s", game_path, norm_path + 2);
}
else {
sprintf(out_abs_path, "%s/%s/%s", game_path, base_dir, norm_path);
}
free(norm_path);
return out_abs_path;
}


Which is obviously subject to buffer overflow.  Not a good thing considering Sphere takes JS as input--too much leeway for exploits using overly-long paths.
miniSphere 5.0.1 - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enourmous man eating pigs ~Rhuan

Re: minisphere
Reply #32
You should check out using parts of BSD's libc. That's what I've been doing for my Kashyyk IRC client when I want some reasonable C-string support with MSVC.

For instance, I imported BSD libc's strcasestr function (look here, strcasestr.c, strcasestr.h, str-two-way.h) for use with MSVC (and in more recent builds, MingW as well). I only compile the functions I need, not the entire library.
BSD's libc seems to be intended to work with pretty archaic and incapable compilers, and so it seems to mostly work with even MSVC, which it has no real reason to support. It also has very confined systems, so in the case of strcasestr, I only needed one extra file besides the source file and header for the function I wanted (and even then just a header).

Alternatively, just put in some defines or def'ed out functions that adapt snprintf, sprintf+strlen, and sprintf_s depending on what is available to the compiler. That way you can get sprintf_s and snprintf when they are available, and have a safe, if less efficient default when neither exists. I do that for `strdup' in TurboSphere. One define that uses strdup, one with strdup_, an inline function that uses strlen, malloc, and memcpy to replicate it.
  • Last Edit: February 07, 2015, 08:56:54 pm by Flying Jester

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: minisphere
Reply #33

Alternatively, just put in some defines or def'ed out functions that adapt snprintf, sprintf+strlen, and sprintf_s depending on what is available to the compiler. That way you can get sprintf_s and snprintf when they are available, and have a safe, if less efficient default when neither exists. I do that for `strdup' in TurboSphere. One define that uses strdup, one with strdup_, an inline function that uses strlen, malloc, and memcpy to replicate it.


This.
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: minisphere
Reply #34
...and I've just hit the one thing I absolutely hate about C: String processing.  Even just to parse the command line to interpret -game "<game dir>" is ridiculous.  Also, Duktape isn't particularly fast--in fact, I think it might even be slower than the SM in Sphere 1.5.  I had minisphere try to run Specs (which has lots of RequireScript in main.js), and there was about a half-second delay between the game window showing up and the JS error due to undefined identifiers (i.e. unimplemented APIs).  Granted, this was under the VC debugger, so I'm sure I took a performance hit just for that, but even so...

I'm starting to wonder how viable this project actually is. :(
miniSphere 5.0.1 - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enourmous man eating pigs ~Rhuan

Re: minisphere
Reply #35
You could check out using stdargs (or was it stdarg?) for that. Or for more generally strings, something the NSPR. There is a reason that a LOT of C-based projects either have or use some system other than just raw C-strings for their string representations.

It shoudn't be that hard to do arg parsing like that in C. TurboSphere did its argument parsing in pure C up until very recently.

It's possible that duktape is much slower on error conditions (like an uncaught exception). That's true of a lot of virtual machines, especially because often there's not a lot of reason to be fast when you can't recover.
  • Last Edit: February 08, 2015, 02:33:06 am by Flying Jester

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: minisphere
Reply #36
Yeah, I found out from playing around that the game dir comes into main() as argv[1] = "-game" and argv[2] = <game dir> conveniently sans quotes, making it simpler than expected.  Of course, this was AFTER writing code to parse the full command line... oh well.

Can I count on this behavior though, or do there exist compilers that pass the full command line to main() as a single argument?

Also, MS apparently doesn't like strdup and getcwd (and probably some others).  The compiler complains that "The POSIX name is deprecated, use _strdup instead."  Last I checked, these weren't deprecated in any standard...  I would really like a clean build without preprocessor cruft everywhere, but that's looking more and more impossible.  Pure C is apparently not as portable as everyone makes it out to be.
miniSphere 5.0.1 - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enourmous man eating pigs ~Rhuan

Re: minisphere
Reply #37
You can count on un-escape spaces to separate arguments.

Code: [Select]

./engine -game startup
# argv[0] engine
# argv[1] -game
# argv[2] startup


Code: [Select]

./engine -game\ startup
# argv[0] engine
# argv[1] -game startup


Code: [Select]

./engine "-game startup"
# argv[0] engine
# argv[1] -game startup


This is true on bash and sh compatible shells, and on CMD. So you can properly count on it.

The posix names are deprecated in MSVC. `strdup' is, in fact, not pure C. If you want to be portable, you should consider something like this:

Code: [Select]


#ifdef _MSC_VER
#define STRDUP strdup_
#else
#define STRDUP strdup
#endif



Recently I've not been doing that, though. I begin to seriously doubt that MSVC's standard library will ever lose the posix names.

You can see on github how I dealt with paths in Kashyyyk, which is what how TurboSphere does it is based on:

https://github.com/FlyingJester/Kashyyyk/blob/master/kashyyyk/platform/win32_paths.c
https://github.com/FlyingJester/Kashyyyk/blob/master/kashyyyk/platform/unix_paths.c
https://github.com/FlyingJester/Kashyyyk/blob/master/kashyyyk/platform/cocoa_paths.m
  • Last Edit: February 08, 2015, 02:15:09 pm by Flying Jester

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: minisphere
Reply #38
Let me just say for the record that Allegro is awesome.  So much stuff is built in that I never expected to be, I always thought it was just a graphics library.  For instance, a platform-agnostic way of handling file paths, avoiding all the path-parsing headaches discussed above.  Also: INI-style config management, meaning I don't even have to parse game.sgm myself, I can let Allegro do it. ;D

One potential source of incompatibility, though: Duktape doesn't recognize const, it causes a syntax error.  I realize it's not standard JS, but SpiderMonkey handles it without issue, so any existing Sphere game that declares things const won't run in minisphere.
  • Last Edit: February 10, 2015, 07:38:39 pm by Lord English
miniSphere 5.0.1 - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enourmous man eating pigs ~Rhuan

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: minisphere
Reply #39

One potential source of incompatibility, though: Duktape doesn't recognize const, it causes a syntax error.  I realize it's not standard JS, but SpiderMonkey handles it without issue, so any existing Sphere game that declares things const won't run in minisphere.


Same with Jurassic! I was able to modify the code though so I am using technically a modified version of it. You could do a RegEx replacement of const to var, but you have to make sure it's only ever in the context of a variable declaration and not say, in some text or a comment (meaning you'll have to write a custom pre-processor parser).
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: minisphere
Reply #40
Okay, so I think minisphere actually isn't too far off from being able to run Spectacles.  I think I just need surface support, which shouldn't be too difficult, and .rfn font support (plus associated text-drawing functions), which... may be harder.

See, Allegro has a function to register your own font loader, al_register_font_loader(), which I could use to let it load .rfn fonts, but here's the issue: The documentation for the ALLEGRO_FONT structure is, well, pretty much nonexistent--even a Google search turns up nothing of use.  Which leaves me only to look at how Allegro loads fonts internally to try to figure it out myself, and even that wasn't particularly helpful at last attempt.

I knew I had to hit a snag eventually.
miniSphere 5.0.1 - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enourmous man eating pigs ~Rhuan

Re: minisphere
Reply #41
It's not too difficult to even draw bitmap fonts yourself. Especially if you are using an immediate API.

I actually think .rfn (and .rws) support would best be done in script. I'm going to do that with TurboSphere.

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: minisphere
Reply #42
See, I would do stuff in script, but Duktape is actually pretty slow so I need all the performance help I can get by doing stuff natively.  Besides, if I let allegro load the font instead of drawing the bitmaps manually, I get stuff like WrapText etc. basically for free instead of having to implement it myself.
miniSphere 5.0.1 - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enourmous man eating pigs ~Rhuan

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: minisphere
Reply #43
So I finally got Allegro loading RFN fonts, and it actually seems to work pretty well.  Only issue: Apparently RFN fonts are actually stored fixed-width (including the default system font), despite vanilla Sphere rendering them variable-width--and the format supports it even!  This means naively rendering characters according to their associated glyphs' widths causes the string to be spaced quite far apart.  Still haven't figured out how to fix this yet.

I guess I could crop the glyph bitmaps at load time, but I'm reluctant to do so because that would mess with RFNs that were actually saved variable-width and would thus already be tuned for proper kerning, etc.

EDIT: Nevermind, ignore me, I'm an idiot.  The cause of my incorrect text rendering was this brain fart here:
Code: (c) [Select]
static int
rfn_render_char(const ALLEGRO_FONT* f, ALLEGRO_COLOR color, int ch, float x, float y)
{
rfn_font_t* rfn = f->data;
rfn_glyph_t* glyph = &rfn->glyphs[ch];
al_draw_tinted_bitmap(glyph->bitmap, color, x, y, 0x0);
return glyph->header.height; // <-- see, it's supposed to return the WIDTH of the char...
}
  • Last Edit: February 12, 2015, 02:58:31 pm by Lord English
miniSphere 5.0.1 - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enourmous man eating pigs ~Rhuan

  • N E O
  • [*][*][*][*][*]
  • Administrator
  • Senior Administrator
Re: minisphere
Reply #44
Just out of curiosity, is anyone else here seeing centered code blocks on Lord English's C examples? I want to double-check if I need to edit more than one theme to fix that.