Various improvements

- Better score saving with error handling
- Added OPK support (yay!)
- Improved README
main 1.1
MassiveBox 2022-08-30 12:13:26 +02:00
parent db5163c945
commit a3f0d66c2b
9 changed files with 87 additions and 21 deletions

.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@

View File

@ -10,11 +10,19 @@ all: $(EXEC)
$(EXEC): $(OBJS) $(HDRS) Makefile
$(CC) -o $@ $(OBJS) $(CFLAGS)
cp ./jiljil.dge ./ipk/data/home/retrofw/games/jiljil-c/jiljil.dge
ipk: all
cp $(EXEC) ./ipk/data/home/retrofw/games/jiljil-c/jiljil.dge
cp -r assets ./ipk/data/home/retrofw/games/jiljil-c/assets/
opk: all
cp $(EXEC) ./opk/jiljil.dge
cp -r assets ./opk/assets/
mksquashfs opk build.opk -noappend -no-xattrs
rm -rf ./opk/jiljil.dge ./opk/assets
rm -f $(EXEC) $(OBJS)
rm -f $(EXEC) $(OBJS) build.ipk build.opk
.PHONY: all clean

View File

@ -8,29 +8,29 @@ JilJil is a simple **arcade-style** score based game, where you control a weird
While this game is named as a port of JilJil, the actual source code of JilJil is not publicly available, so I decided to rewrite the game from scratch and I've added some tweaks here and there to spice up the gameplay. The physics are not supposed to be 1:1 to actual JilJil!
Some of the assets and resources used to create this game are (c) 1997 Studio Pixel. If you represent mr. Daisuke Amaya, Studio Pixel, or any affiliates, please contact me at
Some of the assets and resources used to create this game are (c) 1997 Studio Pixel. If you represent Mr. Daisuke Amaya, Studio Pixel, or any affiliates, please contact me at
## Make-ing
### For Linux
### On Linux
Simply run `make`.
You'll need `SDL` development libraries (including SDL Mixer and SDL Image), and the C compiler `gcc`.
You will get an executable called `2048.dge`, run it and enjoy your 2048 experience!
### For RetroFW
### On Linux for RetroFW
Run `make -f Makefile.RS97`
You'll need a [working buildroot installation](, that includes the SDL development libraries, and `gcc`. Since RetroFW runs on MIPSel devices, instead of the compiler `gcc`, the Makefile will use `mipsel-linux-gcc`, make sure it is a working command on your machine, if it isn't, make sure that the folder where the `mipsel-linux-gcc` binary is stored is in `$PATH`.
You will get a file called `build.ipk` that you can [install]( on RetroFW devices.
Run `make -f Makefile.rfw ipk` to generate an IPK file, or `make -f Makefile.rfw opk` to generate an OPK (recommended).
You will need the [RetroFW Buildroot]( to cross-compile. Check out my project [RetroFW Docker Buildroot]( to install the Buildroot in an easier and platform-independent way.
### For Windows
### On Windows or MacOS for RetroFW
I have no idea. Just get Linux :P
Run `make -f Makefile.rfw ipk` to generate an IPK file, or `make -f Makefile.rfw opk` to generate an OPK (recommended).
Since these platforms don't natively support Buildroot, I recommend you to use the [RetroFW Docker Buildroot](
## Contributing
Contributions are always welcome! You can contribute by opening a pull request or an issue.
You can also report me stuff via email if you don't want to sign up to whichever Git server I choose to host this project.
My mail is
My mail is

ipk/ Normal file → Executable file
View File

View File

@ -0,0 +1,9 @@
[Desktop Entry]
Comment=Arcade highscore-based game.

opk/jiljil.png Normal file

Binary file not shown.


Width:  |  Height:  |  Size: 766 B

View File

@ -4,8 +4,11 @@
#include <time.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <errno.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include "SDL/SDL_mixer.h"
#include "SDL/SDL_sound.h"
#include "SDL/SDL_sound.h"

View File

@ -1,15 +1,40 @@
#include "include.h"
void get_best_score_path(char* reference) {
sprintf(reference, "%s/.jiljil/best_score", getenv("HOME"));
// get_best_score_from_file loads the best saved score from best_score.txt and puts it to best_score
int get_best_score_from_file(void) {
if(access("./best_score.txt", F_OK) != 0) {
char best_score_path[64];
if(access(best_score_path, F_OK) != 0) {
printf("Couldn't read best score file at %s. This is normal if it's your first play.\n", best_score_path);
errno = 0;
char dirtomake[64];
sprintf(dirtomake, "%s/.jiljil/", getenv("HOME"));
if(mkdir(dirtomake, S_IRWXU) == -1) {
switch (errno) {
case EACCES :
printf("The home directory does not to allow write the .jiljil directory\n");
case EEXIST:
printf("Pathname already exists\n");
printf("Pathname is too long\n");
perror("Error creating directory");
return 0;
FILE *fp;
char buff[10];
fp = fopen("./best_score.txt", "r");
fp = fopen(best_score_path, "r");
fscanf(fp, "%s", buff);
int bs;
sscanf(buff, "%d", &bs);
@ -17,11 +42,21 @@ int get_best_score_from_file(void) {
// save_best_score_to_file puts the best score (from global var best_score) to best_score.txt
// save_best_score_to_file puts the best score to best_score.txt
void save_best_score_to_file(int score) {
char best_score_path[64];
FILE *fp;
int best_score = score;
FILE *fp = fopen("./best_score.txt", "w");
fp = fopen(best_score_path, "w");
if(fp == NULL) {
perror("Best score has NOT ben saved! Error opening file to save score");
char snum[5];
sprintf(snum, "%d", best_score);
fputs(snum, fp);
@ -83,6 +118,7 @@ void lemon_cap(float *speed_x, float *speed_y) {
entity_cap(speed_x, speed_y);
// avoid player flickering because the speed is close to zero, but enough to make it move slightly
void player_approximate(float *player_speed_x, float *player_speed_y) {
if(*player_speed_x > -0.1 && *player_speed_x < 0.1) {
*player_speed_x = 0;
@ -132,4 +168,4 @@ int check_player_inside_prints(int tail_x, int tail_y, int paw1_x, int paw1_y, i
return 0;

View File

@ -33,7 +33,6 @@ int pause_game(SDL_Surface *screen) {
case SDLK_BACKSPACE: //R -> reset
return 2;
case SDLK_LSHIFT: //Y -> clear best score
@ -247,8 +246,13 @@ int match(SDL_Surface *screen) {
Uint32 end = SDL_GetTicks();
float elapsedMS = end - start;
float sleepFor = floor(16.666f - elapsedMS);
SDL_Delay(floor(16.666f - elapsedMS));
if(sleepFor < 0) {
sleepFor = 0; // just to be safe
@ -274,7 +278,9 @@ int match(SDL_Surface *screen) {
switch (event.key.keysym.sym) {
case SDLK_ESCAPE: //select -> pause menu
if(pause_game(screen) == 1){
return 1;
case SDLK_RETURN: //start -> new game
return 0;
@ -348,4 +354,4 @@ int boot_animation(SDL_Surface *screen) {