Chai Chai Chai

ChaiScript is a new scripting language more directly based on C++. That means actual classes and stronger overall capabilities.

ChaiLove is essentially LÖVE with ChaiScript. LÖVE has spoiled me with its mature functionality and many user-provided libraries, but ChaiLove actually seems complete.

 

This puts me at a crossroads. In one thing, ChaiLove combines LÖVE’s ease of use and freedom from compilation with C++’s functionality. On the other hand, ChaiScript requires C++14 since version 6.0.0, which was previously C++11 since version 5.3.0, which was Boost up to version 4.3.0. Stone Soup got those problems with C++11 being too new to old compilers, making my “a game that runs in any platform that runs RetroArch or even just Libretro” difficult.

I shall keep an eye on ChaiLove, but I am not permanently switching from my plans of making a game “from scratch”.

Advertisements

Wrapping up the game package

I think I got together all of the pieces of game-making.

Compilation: From the start, the compiling tool was going to be make, which was simple. (Compiling a Libretro core only needed “make -f Makefile.libretro” or even just “make”!) CMake was too complicated, while Bazel needed the horribly insecure Java. The actual compiler I would use was Clang on top of LLVM. My reason is that LLVM/Clang seems to be compatible with projects that work with GCC, the standard of compilation in C, but brings its own benefits, including keeping closer to the original code in compilation while managing better performance. I am new to makefiles or actually knowing compilers, but I found this tutorial which makes things look actually possible.

Networking: Though Libretro has netplay, there are at least a couple of problems with their current implementation.

  1. The way Libretro’s netlag-hiding works is that, during netplay, Libretro constantly makes savestates. If the savestates of the players are out-of-sync, Libretro loads the last savestate when they were in sync then continues normal gameplay. Notwithstanding that any core I would make would have to support savestates which themselves require serialization, the savestates have to be a certain size, meaning that even Nintendo 64 and Playstation 1 emulators cannot use netplay.
  2. Libretro’s netplay seems to be modeled after a home console (multiple players playing on the same system that runs one game) instead of a handheld (multiple players using their own systems that run their own games and connect each other in some way). Driving home this point is the Libretro crew specifically saying that you cannot trade Pokémon through netplay. This is a problem because one of my games Wuu Shyng, is a spiritual successor of Pokémon. Netplay is, therefore, a big concern with me.

While the FAQ list implies that the Libretro crew is going to make a new form of netplay, I decided that the better option would be to not use on Libretro’s netplay at all and instead use an external library, though I would take cues from Libretro’s implementation of netplay in anticipation of compatibility with any future implementation that may work with me. After browsing the Awesome C(++) list for network tools that use TCP (the protocol that Libretro uses), I decided that Mongoose was the best option due to its small size, ease of implementation, and, most importantly, ease of use.

Cutscenes: I decided from the get-go that the files are going to be .ogg files that use Vorbis audio and Theora video, both of them being open-source standards of lossy audio/video. (I could use lossless formats, but I want to keep my games small, especially when you consider that Retroarch has been ported to the PSP and 3DS.) Actually playing those videos is another matter. While I initially looked into using the libraries themselves, their complication combined with my need to implement subtitles (.srt files, by the way, because they are easily written) and the possibility of me needing to add more features led to my decision to just integrate MPlayer in my game. MPlayer has a “slave mode” (ew) that makes this possible. The controls look great; I think that I can have player control the video through their controlers. The one thing that bothers me here is that there is no way of doing a frame-step backward. After looking into how that mode works, I decided to simulate a frame-step in either direction by telling MPlayer to rewind or fast-forward by a fraction of a second, that is, how long does playing a frame take.

Frames Per Second Seconds of a Single Frame
25 0.04
30 0.033333…
50 0.02
60 0.016666…

The small, finite numbers, combined with how much less work would manually animating things be, led to my decision to make files at 25 frames per second. That suits me just fine; I actually do think that PAL, the European analog television system and source of the 25 fps standard, is “Peace At Last”!

That being resolved, my only real issue here is how I would get MPlayer to display to either SDL2’s SDL_Surface or Libretro’s video_cb, unless MPlayer already takes care of that. If I resolve that, then I finally have a complete framework from where I can make Libretro games free from Lua.

SDL, too!

Despite my deciding to give up on trying to make graphics work using just Libretro, I keep coming back to the subject.

There days, I searched again for how Libretro cores that were not emulators displayed graphics. I hit upon the answer in NX Engine, a core that also seems to have a version for every platform that RetroArch is built for. More specifically, NX Engine’s video_cb (the framebuffer that Libretro uses) is a SDL_Surface that holds the pixels. I ended up giving SDL2 a more serious look. Honestly, SDL2 seems to be easier to use than I thought, being on par with my experiences with LÖVE. I can even do basic collision with this! Using SDL2 also solves the problem with using audio and working with files. (Though SDL2 also gives user input and rumble support, I prefer using the Libretro functions themselves.) All that remains is how to add network support and use make.

I also looked at other game engines and frameworks that probably had what I needed. SFML was the best match, but I needed to convert its RGBA8888 format to ARGB888 format first before I use a couple of Libretro’s functions in converting to RGBA4444, then RGB565. Thankfully, the code to convert from ARGB8888 to ARGB4444 seems to be easily modified to accept RGBA8888, instead.

I am still leaning towards using SDL2 if I ever make a game here without LÖVE, though, especially when I consider my lightweight goals.

SDL2 Targeted at Libretro?

The desire to find a way to handle graphics directly in Libretro came up again since about a couple of weeks ago.

I ended up at several venues of possible solutions, one being sdl-libretro. My big issue with trying this is that the repository uses SDL 1.2.15 when SDL2 already exists. After looking at the code, I made a folder that had the include, src, and test folders of the SDL2 source and the Makefile.libretro file of the sdl-libretro repository.

The compiler wanted EGL/egl.h . I ended up adding EGL, KHR, and X11 (actually a combination of X11 and XProto sources!) folders before the compiler requested sys/syscall.h . A search revealed that sys/syscall.h does not exist in Windows, the operating system I am using now. I temporarily modified the Makefile.libretro file by adding:

platform := win

after line 13 in the file. I also renamed the naming scheme from “SDL” to “SDL2” because I wanted to differentiate my experiment with SDL2 with the official sdl-libretro repository.

I ended up with a libSDL2_win.a file.

I am surprised and relieved that compilation apparently works, but what am I supposed to do with this file?

 

P = NG

After my previous adventures in rendering .png files to a software framebuffer, I realised that I needed to convert between lodepng’s RGBA 4-bits-per-pixel format to Libretro’s RGB565 format. My studies since my last post brought me to pixconv.c which has a function, conv_rgba4444_argb8888, that does just that type of conversion. I need to give the function the following in this order:

  1. the output variable
  2. the input variable
  3. the dimensions of the image file
  4. the output pitch
  5. the input pitch

In theory, all I had to do was add lodepng and pixconv.c to my project, run a test.png file through those two, and put the resulting data in the framebuffer.

The result was a mess. Learning that <iostream>, a stape at my studies of C++, was worthless when working in C, was actually the easy part. Even if I did not exactly know what type of data type were the variables that held the RGBA4444 and RGB565 arrays (I settled on unsigned char when void did not work), the makefile refused to recognize lodepng_decode32_file and logepng_error_text, even after I put those two types in various places (though not at the same time) inside the actual libretro_test.c file. I learned that this issue comes from the linker, which is related to the makefile.

At this point, I decided to give up at least temporarily. I mean, while there is the possibility that this is the last problem and that I actually have everything else right, I decided that this matter requires advanced knowledge that is specialized on C++. I mean, I have a Master’s Degree in Software Engineering, but my actual usage of the fundamentals of C++ and related languages were all in Integrated Development Environments. I barely know anything more than how to run make (not “CMake”, but “make”)!

This lack of specialized knowledge is also the reason why I am no longer pursing either adapting a current C++ engine to Libretro or, per Radius’ suggestion, using OpenGL. I still would have to deal with compiling the C++ code in those situations.

In light of this, I was looking more seriously at Rust, which has bindings to Libretro. While Rust is not object-oriented in the conventional sense, Rust has features that have just about the same functionality anyway. The problem is checking how the current game engines that use Rust render graphics. After all, I want to use software rendering because I want my games to be played at the full range of consoles that run Retroarch, not just the ones that can handle both versions of OpenGL.

I am also seriously considering going back to Lua per my original plans. Not only does LÖVE have no need of a distinct compilation process but also displays graphics through an API that works great and easy. In fact, the ease of use LÖVE provides is the reason why I picked using LÖVE instead of straight C++ in the first place! The main reason why I am not so sure is because that the reason why I wanted to leave Lua in the first place was because Lua did not have any proper support of object-oriented programming. I would much rather use the real deal, especially since Re-Hoard needs object-oriented programming! Even if there is an alternative, this lack of functionality may hamper heavily my plans of future games!

I tried to see how Lutro, Libretro’s interpreter of LÖVE, displays games written in LÖVE. I mean, LÖVE apparently uses SDL, but that does not seem to be a problem to Lutro. However, I got overwhelmed once again.

Eevee is right; if I were to write from scratch, I would be essentially inventing the universe if I needed to get off the ground. Then there is compilation afterwards.

Understanding Graphics

I thought that I was just going to give up on understanding how Libretro renders graphics. However, I still had this urge of solving this problem.

That turned out to be a good thing.

After reading on other engines and thinking just how Libretro handles this stuff directly, I took another look at the example code and actually built the example. I then spent my time reading the code, adding my own comments there. I found out that I was ignorant or mistaken in a few points.

  • A software framebuffer, in the case of Libretro, refers to a 2D array in memory. Each cell in that array represents a pixel.
  • The “cb” in “video_cb” means “callback.”
  • Retro_video_refresh_t, in reality, is a function that renders the actual frame, taking the data, both dimensions, and pitch.
  • Speaking of “pitch”, that actually refers to the number of bytes between any two lines in the buffer, that is, the length of a scanline. The “stride” variable refers to the pitch.
  • The mouse is not involved in the demo; I was looking at variables that had the name “mouse” in them. They actually refer to the pitch.

My plans have me uploading my comments on the code later. Right now, I shall give what seems to be the general procedure in software rendering using Libretro.

In a nutshell:

  1. Declare a bitwise 2D array in memory. This is an abstraction of your framebuffer.
  2. Call retro_video_refresh_t, putting its contents in a static variable.
  3. Call retro_get_system_av_info, putting information that relates to the framebuffer.
  4. Make a static void function.
  5. In that function, copy into a local variable the contents of the array in Step 1.
  6. In the same function, fill the cells you want in that array with pixel data.
  7. In the same function, put the buffer, its dimensions and pitch in the variable in Step 2.
  8. At runtime, call that function.
  9. At the time of actually loading the game, set the pixel format.

The issue now is that I have to figure out how to either convert lodepng’s RGBA format to RGB565 or how to use Libretro’s own rpng.

Either way, I do not feel lost anymore today.

Broken Physics; Broken Graphics

I am starting to change my mind.

I looked into Chipmunk after Box2D warned me about Box2D requiring a lot of C++ experience. However, Chipmunk itself seems too complex. Worse, I could not find an API-indifferent way of putting graphics on the physics objects!

I looked into other game engines, but they, true to my predictions, use SDL or OpenGL and do not seem to have ways of rendering directly to the framebuffer. Speaking of the framebuffer, I am still awaiting on information on what exactly is a framebuffer in the first place. On Radius’ defense, Radius is probably taking time out of a busy day in making an appropriate reply.

I just feel frustrated because I feel lost. Radius gave me a much-needed nudge, but I need more.

I am not going back to Lua because I need the capabilities that C++ or Rust give. Even so, the Rust libraries and engines probably have the same dependencies on SDL or OpenGL that the other game engines have.

I should be spending this time working on my PICO-8 games.

I shall look at rpng, Libretro’s own decoder of .png graphics. That, being of Libretro itself, should have a way of rendering directly to the framebuffer.

The Framebuffer is the Way

Since my last post, I gotten some help at how to render graphics through Libretro. I mean, while I did take 2 classes in rendering graphics through GLUT (from OpenGL) and a bit of familiarity of Unity during my entire college career, I am still essentially new at graphics programming. I am just in a position to learn now.

I asked in the Libretro forums. Radius clarified to me that I am supposed to render to a framebuffer where I would set a pixel there to the color that I want. Physics engines can then be easily built on top of that concept. I then asked Radius about how I can go to learning about framebuffers in the first place. Meanwhile, given this point of clarity, I searched the libretro-samples repository for stuff on framebuffers. There, I found examples on how to use software rendering.

 

Basically, I would:

  • declare a bit-level variable that holds the framebuffer.
  • set the size of that framebuffer.
  • declare a static variable called “video_cb” that is of the retro_video_refresh_t type.
  • get the information of the AV system, including the dimensions, aspect ratio, and frames per second.
  • declare a couple of variables that hold the coordinates of the image I want to render.

I got difficulty going farther because, from reading the source code, the example is rendering a checkerboard. Apparently, the rendering itself involves copying the framebuffer to a separate “line” variable which holds an array, pushing the coordinates of the square to that “line” variable, then setting the value of those coordinates to a color, said color being a variable that holds a point in memory (0xff, specifically) to where you push the value while declaring that color variable.

(The example also apparently relies on the mouse. The mouse coordinates, which come from their own variables, use some “stride” variable that I do not know but is used in an intermediary buffer variable that copies itself to the “line” variable. There, the value of 0xff is put on the buffer variable, which is also an array, to some location that uses both some of its internal coordinates and that “stride” variable. I am not sure. I think I need to actually compile the source code if I were to understand.)

After all that, the example puts into the earlier “video_cb” variable:

  • the buffer variable
  • the specific dimensions
  • that “stride” variable that undergoes a left shift of 2 (whatever that means).

The above is inside a rendering the function that is executed at runtime.

At the time where the Libretro frontend actually loads the example, the example actually sets the retro pixel format. Afterwards, serialization makes a data array that is set to the image coordinates. A size of 2 is also involved in some way.

 

Changing our focus to the Libretro library itself, Libretro uses retro_framebuffer and retro_video_refresh_t. retro_framebuffer is a structure that has the following components:

  • the data that actually holds the framebuffer itself
  • the dimensions of the framebuffer
  • the “pitch”, that is, how many bytes take up the length of a scanline
  • the pixel format
  • access flags that say how “the core will access the memory in the framebuffer”
  • memory flags that tell the “core how the memory has been mapped”

I do not know about the existence, much less proper use, of these flags at the time I am writing this.

Except for the dimensions and access flags, most of the components use GET_CURRENT_SOFTWARE_FRAMEBUFFER, which returns a framebuffer directly to video memory. The thing is that GET_CURRENT_SOFTWARE_FRAMEBUFFER actually returns a pointer that must be writeable. However, actually rendering directly to the video memory instead of using a pixel format is optional. In this case, instead of directly setting the values of the buffer and “stride” variables, I would make a retro_framebuffer structure. In that structure I would:

  • set the dimensions normally.
  • set the access flags to RETRO_MEMORY_ACCESS_WRITE.
  • set the buffer variable to the framebuffer data.
  • set the “stride” variable to the framebuffer pitch that has a right shift 2 (whatever that means).

Of course, there is a fallback to the normal way.

retro_video_refresh_t is actually a type that Libretro defined, this type actually rendering the frame. The components of retro_video_refresh_t are:

  • data  from the above framebuffer
  • the dimensions of the framebuffer
  • a “pitch” which, according to the comments, is the number of bytes that make up the length between two lines in the framebuffer

 

While that is ample coverage of how do render to the framebuffer the data, there is still the issue on how to convert .png files to actual data in the first place. Fortunately, I looked up LodePNG. While that is not Libretro’s internal decoder of .png files, LodePNG has a simple way of decoding the file to pixels. I would simply declare a vector variable that carries the raw pixels, then I would also declare variables that carry the dimensions. I would then run LodePNG’s “decode” function that takes in the above 3 variables and the filename, putting the pixels in the vector variable. There, 4 bytes, representing RGBA in that order, represent each pixel. I am still not sure on how to use this raw .png data in Libretro, though.

 

I still am not sure on what is exactly a “framebuffer,” either.

Hard Work at Figuring out the Graphics

I should be finishing Re-Hoard and Reckless Abandon, but, other than doing most of the sprites at Re-Hoard, I spent most of my time trying to figure out how to display graphics through Libretro.

Basically, because I plan on using software rendering (which is more portable due to not dependent on any specific API), all I need to do is render to a framebuffer… or the backbuffer. I know that I am going to exclusively use .png files and, because of my choice of 2D retro-style graphics, the RGB565 format, but I do not know the exact procedure in displaying and moving graphics while targeting Libretro. I mean, I did not even know of RGB565 before reading the libretro.h file! LÖVE did not give me this much trouble!

I can use a sprite library, but those were made without the knowledge of Libretro, which means that they would render using SDL2 or OpenGL instead of the generic software rendering layer that Libretro uses. Even if I did find one that uses software rendering, I have trouble knowing how to write .png files to a framebuffer or backbuffer! Libretro does have its own png decoder, but I do not know how to use the thing! This is not even taking into account the Box2D or Chipmunk physics engines that I plan on using!

I still plan on going ahead with using straight C++ with Libretro instead of writing in Lua and running the resulting core through Lutro. After all, I prefer to be the closest possible to the Libretro library because I find that the extra control outweighs the difficulty. Besides, this knowledge would be helpful if I ever get a job at another game company. However, if this gets too difficult, then I shall use a Rust engine and rely on Libretro’s Rust wrapper, instead.

Why write in LÖVE?

While I previously wrote of the benefits of writing through the Pico-8, I would need to write larger games through LÖVE, instead. The reason behind this came from a decision during early planning of my Master’s Project, which I wanted to be a game. I wanted to target Libretro, actually, because of the:

  • free license
  • cross-platform support
  • specific, through game-oriented design

However, games that target Libretro would have to be writen in C or C++, both programming languages that, despite my familiarity, were unpleasantly complex. However, I found out about Lutro, a porting of LÖVE to Libretro, the main benefit being an ability to write games in the far more pleasant-to-use Lua. Another benefit was that, though Lutro was still a work in progress, the original LÖVE had benefits that were similar to Libretro. The original LÖVE also achieved similar maturity, which meant that I could write games through original LÖVE, get similar benefits, and still be ready when the Lutro port matures.