[Tool]FemtoIDE

No, final doesn’t work that way. It locks out variable changes, effectively being a const for int and all other primivite types (and as such those variables will be optimised away by a decent compiler), but won’t have the effect you think when the variable is an object or an array - which remains totally modifiable. It’s a constant pointer to a non constant object in that case. The object still has to exist somewhere -in this case that means both the String and its contents- and be usable and elligible for garbage collection like any other one. If that’s a root variable, like a static final, then the garbage collection won’t touch it of course, that is, until the VM shutdowns.

However, Java’s String are immutable by design, some something could be done there.

Edit: Now that I think about it, it might be best to just automatically declare any string literals as static final String literal_01 ="Hello"; in a AllStrings class and use AllStrings.literal_01 whenever "Hello" is encountered.

Also, operator<<(T value) has a major difference over printf‘s format: it simply cannot be changed after compile time. It’s a strength (great performance and sturdiness) and a flaw depending on the context. Java’s own string format also includes indexes for parameters, which means they can be changed on the fly - a great asset for simple internationalization.
Also, for end users (especially translators), something like "Hi, %1$s! How are you doing? I'm %2$s, nice to meet you!".format(protagName, opponentName) could be more useful than << "Hi, " << protagName << "! How are you doing? I'm " << opponentName << ", nice to meet you!".
And if you need to change the order because it looks best in another language, you could just replace the format string and voila - "Bonjour, je suis %2$s ! Vous êtes bien %1$s, si je ne me trompe pas ? Enchanté !".format(protagName, opponentName).
It all boils down to what you want to achieve in the end. C++’ operator<<() is great for machines and fixed formats, but it’s more discutable for humans and their pesky languages. Altough, even the most machine-like human e.g. sys admins still love changing a log format from time time. Also, if you can transform code into data, it’s best to do so, right? :stuck_out_tongue:

I read somewhere that the equivalent of printf could be safely build with stream things, with safe template support too. But I doubt it’d support parameters swapping unfortunately, so it might be only syntax sugar (or salt).
Edit: Could be relatively easy to do actually, a string-swappable format by using template-based detection to determine the type of the argument at compile time to use the appropriate handler, and just keeps the formatting flags and parameters in place for adjusting the format itself. Then the format string will not control anymore which type it’s encountering, fixing the many security issues of printf.

Yet another edit:
Could be great to have a minimal version of StringBuilder actually!

3 Likes

Drat, I forgot about the lack of const-correctness.

I was only really thinking of String anyway.

The static final optimisation wouldn’t apply to arrays either.

Though I think if we introduced a few custom types (e.g. ROMByteArray) then there would be room for abusing it providing similar optimisations.

Yeah, that would probably work.
Like a sort of compile-time string pool.

True, but that comes at a cost.

The format function actually has to iterate through every character of the input string and inspect the character, looking for a format match, then it has to analyse the format and report a type error if there’s a type mismatch.
(Note that Java’s format function actually reports a type error, whereas most C++ functions (which are mostly inherited from C) don’t.)

Something the C++ library doesn’t do, but which could be done, is to create an actual Format object that represents the formatting.
For example:

constexpr Format englishString = "Hi, " << 0_formatString << "! How are you doing? I'm " << 1_formatString << ", nice to meet you!";
constexpr Format frenchString = "Bonjour, je suis " << 1_formatString << "s ! Vous êtes bien " << 0_formatString << "s, si je ne me trompe pas ? Enchanté !";

(If you don’t like <<, it would also be possible to use +, ,, ^ & et cetera.)
Then you can just do englishString.format(protagName, opponentName).

The only downsides are that it would be a bit more expensive to construct the object at runtime,
and that it would only be properly typesafe if each Format object was actually a different type so it could have a different format function that accepted different arguments - in this case format(const char *, const char *) or format(std::string, std::string).

If you don’t need it to work at runtime then it’s a much more type safe and efficient option.

Although, now I think about it…
You wouldn’t actually necessarily need the type info in the Format object, you could just do:

constexpr Format englishString = "Hi, " << FormatParameter(0) << "! How are you doing? I'm " << FormatParameter(1) << ", nice to meet you!";
constexpr Format frenchString = "Bonjour, je suis " << FormatParameter(1) << "s ! Vous êtes bien " << FormatParameter(0) << "s, si je ne me trompe pas ? Enchanté !";

And then let englishString.format(protagName, opponentName) determine the types of the arguments.
That way the same format isn’t restricted to using a particular type of data, it’s just providing placeholders for variables, which can be any type.

The problem of providing new formats can be solved by providing a free function (or operator) that can be overloaded, and have the default case fall back to calling formatObject.format.

(Hrm, I might have a go at writing something like that…)

Code is data too.

Never heard of LISP’s ability to inspect its own structure and rewrite its own code at runtime? :P

C++ can’t do that (probably), but operator overloading lets you do some crazy stuff.
Boost.Spirit lets you write expression parsers using a sort of BNF-like grammar notation (code taken from this example):

///////////////////////////////////////////////////////////////////////////////
//  Our employee parser
///////////////////////////////////////////////////////////////////////////////
//[tutorial_employee_parser
template <typename Iterator>
struct employee_parser : qi::grammar<Iterator, employee(), ascii::space_type>
{
	employee_parser() : employee_parser::base_type(start)
	{
		using qi::int_;
		using qi::lit;
		using qi::double_;
		using qi::lexeme;
		using ascii::char_;

		quoted_string %= lexeme['"' >> +(char_ - '"') >> '"'];

		start %=
			lit("employee")
			>> '{'
			>>  int_ >> ','
			>>  quoted_string >> ','
			>>  quoted_string >> ','
			>>  double_
			>>  '}'
			;
	}

	qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
	qi::rule<Iterator, employee(), ascii::space_type> start;
};

Which is then used a bit like this (I modified it slightly from the example):

using boost::spirit::ascii::space;
using employee_parser = client::employee_parser<iterator_type>;
std::string string = getString();
client::employee employee;
bool success = phrase_parse(std::begin(string), std::end(string), employee_parser(), space, employee);

Roughly what I discussed earlier in the comment using FormatParameter(0).

(And printf has far more issues that just it’s lack of type safety. :P)

If I find the time I might have a go at it.

If I knew how to access the internal pointer of a char[] in FemtoJava and knew that the compiler was using C++17 then I’d use the std::to_chars function that I mentioned earlier.

1 Like

Hi,

Game.changeState( new Main() );
do not work for me any more. After restarting the game with the A button, it hangs on the line:
screen = new HiRes16Color(Pico8.palette(), TIC80.font());

It has been working before.

Here are the sources: ZombieFlock.zip (1.8 MB)

Can you get on Discord so we can debug it there?
Edit: Problem solved :slight_smile:

2 Likes

For the record: the screen object should be static to avoid memory fragmentation, when deallocating and reallocating objects during the game restart.

1 Like

FemtoIDE v0.1.0 Released

  • MicroPython: First Contact. MP projects compile and run.
  • Femto: femto.mode.LowRes16Color for 110x88 games (mode 2 in the PokittoLib).
  • Femto: femto.TileSet, for storing a non-animated set of images.
  • Femto: Fix crash when trying to change game with Mixer enabled.
  • Femto: screen.textWidth, returns the length of a string in pixels with the current font.
  • Java: Fix bug with final static float[].
  • Java: Started doing type-checking. Still has some holes.
  • Java: optimized constant strings.
  • Java: Fix arrays getting GC’d incorrectly.
  • Java: Array-out-of-bounds triggers a crash when in debug mode.
  • Java: Fix super() (constructor call with no arguments).
  • Java: Support for var class fields.
  • Java: Arrays of booleans with optimization for lengths smaller than 33.
  • Java: Stop showing an outdated version of generated.cpp.
  • Java: Automatically jump to the source of an error.
  • IDE: Fix session.getValue is not a function error.
  • IDE: Support for per-project scripts as a build step.
  • IDE: Added Hello Micropython project/template.
  • IDE: Added Commit All option.
  • IDE: Somewhat-intelligent autocomplete for Java code
6 Likes

2
Tilemap.zip (141.7 KB)

This is a little demo showing how to use a pre-build script to convert Tiled TMX files and render them in a game. Edit your tilemap in tiled, save, click “build-and-run”, see your changes instantly.

Since different games will have different requirements, doing this conversion in a project-specific script (scripts/tilemap.js) allows you to customize things as you see fit.

Unzip it into the projects folder in FemtoIDE v0.1.0 and you’ll have all the boilerplate done for a tile-based game.

7 Likes

Hi @FManga

Once again, thanks for adding Python support! I gave your IDE a try today and it seems to work quite well, but is clearly still in beta… One thing I noticed is that despite me changing the font in the settings cpp file, it still doesn’t change the font. I tried it with your hello pokitto example and my game… Is this a known issue or did I miss something I was supposed to do for the new font to “kick” in?

1 Like

Hey,

Python support still has a long way ahead to mature. Some things that PyInSky does behind the scenes haven’t been ported over yet, like setting the font and image/sound conversion. I’m still not sure how that will work here, putting data in the code like PyInSky is not the way FemtoIDE does things.

For now, try this:
Open micropython/main.cpp and add:
game.display.setFont(fontC64); // replace fontC64 with the one you want

before this line:
PyInSkyMain( p, new char[p] );

Thanks! That sorted the font issue.
I presume what you’re saying then, is to rather continue using the Online IDE for the time being until you’ve coded in the equivalents for FemtoIDE?

Yup, unless you don’t mind switching back-and-forth whenever you need to convert another image or something.

I was actually thinking of doing exactly that for the graphics and sounds hehe. The conversion process is nice and quick online, so it’s not a major pain in the ass really.
Your IDE is much quicker and I like the dark colours as it looks more professional :slight_smile: and I can access config files that’s not possible on the online IDE.

2 Likes

Femto v0.1.0 feedback:

  • Copy pasting lines works much better!
  • Automatically goes to the line where the error is :+1:
  • Cannot get context sensitive help to work. Always opens the main help page.
  • “Commit all” in Git helps a lot (thought even better would be committing only added files)
2 Likes

I would like to specify a map for my game using a rom bitmap. Is there any way to read a value of a specified pixel of the bitmap.

Or do I just have to get familiar with “Tiled”?

1 Like

You can’t use an Image/Sprite directly, but you can write a script that uses readImage and write to create a file that would be placed in rom… though getting familiar with Tiled would probably be the better/easier option.

1 Like

@FManga - So I discovered something tonight that I thought I should let you know about. I found a bug in my Pokaquarium game and needed to move some code around to get it working, which I did. However, I did this in FemtoIDE.
So the interesting thing was that the binary your IDE created was 233kb, as apposed to the online IDE that was 208kb. When I tried flashing your binary to the pokitto, it would hang at 96%. I tried both the stock loader and Kraken loader.
So, building to hardware from your IDE is doing something that breaks the flash to rom, or perhaps the binary is just too large to flash, hence the hang at 96% when writing to rom?

My first try with a Tilemap created map ended with an error:

Error: Could not find “map”

The project: ZombieFlock.zip (2.8 MB)

I’ll have to check when I get home, but it’s probably this: the online editor compiles with -Os while FemtoIDE defaults to -O3, which produces bigger/faster binaries. Try changing from one to the other in CPPFlags and LDFlags in project.json.

@Hanski try this: ZombieFlock.zip (3.0 MB)

Edit: about the context-sensitive help, it should kick in after the first compilation, otherwise there is no context yet. Same for autocomplete.

1 Like

Thanks mate. Changing those params worked. Now the binary flashes to the Pokitto perfectly!!
I’ve adjusted the json file for the hello micropython project, as I copy that one to start new projects and then won’t have to faff with it :slight_smile:

2 Likes