SDLPoP scripting/modding (concept, ideas, discussion)

Open-source port of PoP that runs natively on Windows, Linux, etc.
Post Reply
Falcury
Calif
Calif
Posts: 565
Joined: June 25th, 2009, 10:01 pm

SDLPoP scripting/modding (concept, ideas, discussion)

Post by Falcury »

Hi all,

I have been thinking about possible modding features for SDLPoP, and I have been working on some prototypes for this.

Of course, some customization of the game is already possible (though not yet as extensive as with CusPoP). Currently it is relatively easy to change the way SDLPoP behaves by editing a configuration file (SDLPoP.ini), and the number of available options can of course be expanded in the future.

But this has some limitations, and we can try to do even better!

Problem: Need to have separate installations of SDLPoP for each mod you want to play.
(This can be circumvented somewhat by running from the command prompt while in a different working directory, but this takes a lot of setting up and may not be an ideal solution for most people. Also, it is not straightforward for mods to override user options specified in SDLPoP.ini - e.g. whether bugfixes should be enabled)

Possible solution:
We could organize mods in a dedicated "mods/" folder, and provide an SDLPoP.ini option that tells SDLPoP from which directory custom files should be loaded:

Code: Select all

; You can choose which levels to play using the 'levelset' option:
;    'original'       --> play the original levels (Default)
;    'Your Mod Name'  --> play a custom levelset (the custom files must be in a directory "mods/Your Mod Name/")

levelset = The Great Escape
So basically you add a mod folder to the "mods/" directory and put the modified files in that (unmodified files can just be loaded from the normal data files).
This way, the mod never interferes with the original game data. If you want to play the original game again, you simply change the "levelset" option back to "original" in SDLPoP.ini and you're done.
To make mods override gameplay configuration options, you could add an INI file into the mod directory itself (e.g. "mod.ini"). For example, this short configuration file will turn off all gameplay fixes only for this mod:

Code: Select all

[Enhancements]
use_fixes_and_enhancements = false
Problem: It is very difficult to add custom features in a mod without changing the SDLPoP source code.
It would of course be possible to add anything as an option to SDLPoP.ini... but this has its limits. And new features that modders might want for their own mods (such as custom potions or new special events) may not always be suitable as core SDLPoP features.

Possible solution:
We could add a scripting system for creating SDLPoP add-ons!
It turns out that implementing such a system is actually quite doable. The most suitable framework that I could find for this purpose was libtcc; this is an embeddable part of the open source Tiny C Compiler, a fast and lightweight compiler for C code.
The libtcc library can be invoked as a single fairly small dll (about 130 kB) - so SDLPoP will not become much bigger when we decide to add libtcc as the basis of a scripting system.

So the basic idea is this:
- Modders can write add-on scripts for SDLPoP in the C language, and distribute a script together with their mod.
- SDLPoP compiles and starts the script upon launch.
- Custom features should then "just work" in-game.

I have been working on experimental SDLPoP support for the mod organization and scripting features. To try everything out for yourself, you can download the test build for Windows (as usual with source code included) in the attachment below (SDLPoP_v1.17b2.zip).
(N.B. this is NOT something like an official beta, just an experimental build!)

I put together some "example" mods in a separate ZIP file (SDLPoP Mods.zip).
Usage: extract the contents of the ZIP file into the "mods/" folder of SDLPoP, then open SDLPoP.ini and change the "levelset" option to any of the mod folder names.

In this ZIP file, I added the first three mods from popot.org (http://www.popot.org/custom_levels.php?sort=id). Each mod has its own folder. Some have modified graphics, but I found that some data files (specifically, customized VDUNGEON.DAT and KID.DAT) caused SDLPoP to crash so I left those out.

I also added an (unfinished) "pure-script" version of my own mod, Secrets of the Citadel. So you can take a look at how I rewrote some of the mod's features as an SDLPoP script (the Readme.txt in that folder contains some additional explanation).

The scripting system (concept)
In the test build, SDLPoP looks for a plain text file called "mod.scr" and tries to compile that as C code.
The "mod.scr" file should always be in a mod directory (it will not work in the main folder of SDLPoP). (The reasoning for this is that scripts are always part of a mod anyway, and having some random script sitting in the main folder by accident could lead to unexpected behavior.)

About the script file extension:
I initially thought about giving scripts a .P1S extension (for Prince of Persia 1 Script), but perhaps this is not the best option. The other PoP1 files all have extensions like .SAV, .DAT, so perhaps the best way to not break the pattern is to use an extension like .SCR (for SCRIPT). (so, incidentally, perhaps replay files should be called .REC instead of .P1R?)

How to write a script:
SDLPoP tries to find specific functions as entry points for the script. These functions then get called at specific times:

Code: Select all

// Called immediately after the script has been compiled and loaded correctly.
void on_init() { /* your code here */ }

// Called every time you begin a new game.
void on_start_game() { /* your code here */ }

// Called right after a level has been loaded (or reloaded again after restarting).
void on_load_level(int level_number) { /* your code here */ }

// Called when a level ends, just before a cutscene or the next level is loaded.
void on_end_level(int level_number) { /* your code here */ }

// Called when a potion is drunk.
void on_drink_potion(int potion_id) { /* your code here */ }

// Called just before the game draws a potion. Bubble color and pot size can be changed here.
void custom_potion_anim(int potion_id) { /* your code here */ }

// Called every game tick.
void custom_timers() { /* your code here */ }
At the top of the script, you should include the header that contains declarations for types, variables and functions that you can use:

Code: Select all

#include <pop_script.h>
The file "pop_script" is located in "data/script/". This is what it looks like currently:
Spoiler: show

Code: Select all

#ifndef POP_SCRIPT_H
#define POP_SCRIPT_H

#define NULL 0

typedef unsigned char byte;
typedef signed char sbyte;
typedef unsigned short word;
typedef unsigned long dword;

typedef struct rect_type {
    short top,left,bottom,right;
} rect_type;

enum tiles {
    TILE_EMPTY = 0,
    TILE_FLOOR = 1,
    TILE_SPIKES = 2,
    TILE_PILLAR = 3,
    TILE_GATE = 4,
    TILE_STUCK = 5,
    TILE_CLOSER = 6, // a.k.a. drop button
    TILE_DOORTOP_WITH_FLOOR = 7, // a.k.a. tapestry
    TILE_BIGPILLAR_BOTTOM = 8,
    TILE_BIGPILLAR_TOP = 9,
    TILE_POTION = 10,
    TILE_LOOSE = 11,
    TILE_DOORTOP = 12, // a.k.a. tapestry top
    TILE_MIRROR = 13,
    TILE_DEBRIS = 14, // a.k.a. broken floor
    TILE_OPENER = 15, // a.k.a. raise button
    TILE_LEVEL_DOOR_LEFT = 16, // a.k.a. exit door
    TILE_LEVEL_DOOR_RIGHT = 17,
    TILE_CHOMPER = 18,
    TILE_TORCH = 19,
    TILE_WALL = 20,
    TILE_SKELETON = 21,
    TILE_SWORD = 22,
    TILE_BALCONY_LEFT = 23,
    TILE_BALCONY_RIGHT = 24,
    TILE_LATTICE_PILLAR = 25,
    TILE_LATTICE_DOWN = 26, // a.k.a. lattice support
    TILE_LATTICE_SMALL = 27,
    TILE_LATTICE_LEFT = 28,
    TILE_LATTICE_RIGHT = 29,
    TILE_TORCH_WITH_DEBRIS = 30
};

#pragma pack(push,1)
typedef struct link_type {
    byte left,right,up,down;
} link_type;

typedef struct level_type {
    byte fg[720];
    byte bg[720];
    byte doorlinks1[256];
    byte doorlinks2[256];
    link_type roomlinks[24];
    byte used_rooms;
    byte roomxs[24];
    byte roomys[24];
    byte fill_1[15];
    byte start_room;
    byte start_pos;
    sbyte start_dir;
    byte fill_2[4];
    byte guards_tile[24];
    byte guards_dir[24];
    byte guards_x[24];
    byte guards_seq_lo[24];
    byte guards_skill[24];
    byte guards_seq_hi[24];
    byte guards_color[24];
    byte fill_3[18];
} level_type;
#pragma pack(pop)

typedef struct char_type {
    byte frame;
    byte x;
    byte y;
    sbyte direction;
    sbyte curr_col;
    sbyte curr_row;
    byte action;
    sbyte fall_x;
    sbyte fall_y;
    byte room;
    byte repeat;
    byte charid;
    byte sword;
    sbyte alive;
    word curr_seq;
} char_type;

enum charids {
    CHAR_KID      = 0,
    CHAR_SHADOW   = 1,
    CHAR_GUARD    = 2,
    //charid_3          = 3,
    CHAR_SKELETON = 4,
    CHAR_PRINCESS = 5,
    CHAR_VIZIER   = 6,
    CHAR_MOUSE   = 0x18
};

enum directions {
    DIR_RIGHT = 0x00,
    DIR_NONE = 0x56,
    DIR_LEFT = -1
};

enum actions {
    ACTION_STAND         = 0,
    ACTION_RUN_JUMP      = 1,
    ACTION_HANG_CLIMB    = 2,
    ACTION_IN_MIDAIR     = 3,
    ACTION_IN_FREEFALL   = 4,
    ACTION_BUMPED        = 5,
    ACTION_HANG_STRAIGHT = 6,
    ACTION_TURN          = 7,
    ACTION_HURT         = 99,
};

enum soundids {
    SOUND_FELL_TO_DEATH             = 0,
    SOUND_FALLING                   = 1,
    SOUND_TILE_CRASHING             = 2,
    SOUND_BUTTON_PRESSED            = 3,
    SOUND_GATE_CLOSING              = 4,
    SOUND_GATE_OPENING              = 5,
    SOUND_GATE_CLOSING_FAST         = 6,
    SOUND_GATE_STOP                 = 7,
    SOUND_BUMPED                    = 8,
    SOUND_GRAB                      = 9,
    SOUND_SWORD_VS_SWORD            = 10,
    SOUND_SWORD_MOVING              = 11,
    SOUND_GUARD_HURT                = 12,
    SOUND_KID_HURT                  = 13,
    SOUND_LEVELDOOR_CLOSING         = 14,
    SOUND_LEVELDOOR_SLIDING         = 15,
    SOUND_MEDIUM_LAND               = 16,
    SOUND_SOFT_LAND                 = 17,
    SOUND_DRINK                     = 18,
    SOUND_DRAW_SWORD                = 19,
    SOUND_LOOSE_SHAKE_1             = 20,
    SOUND_LOOSE_SHAKE_2             = 21,
    SOUND_LOOSE_SHAKE_3             = 22,
    SOUND_FOOTSTEP                  = 23,
    SOUND_DEATH_REGULAR             = 24,
    SOUND_PRESENTATION              = 25,
    SOUND_EMBRACE                   = 26,
    SOUND_CUTSCENE_2_4_6_12         = 27,
    SOUND_DEATH_IN_FIGHT            = 28,
    SOUND_MEET_JAFFAR               = 29,
    SOUND_BIG_POTION                = 30,
    //sound_31 = 31,
    SOUND_SHADOW_MUSIC              = 32,
    SOUND_SMALL_POTION              = 33,
    //sound_34 = 34,
    SOUND_CUTSCENE_8_9              = 35,
    SOUND_OUT_OF_TIME               = 36,
    SOUND_VICTORY                   = 37,
    SOUND_BLINK                     = 38,
    SOUND_LOW_WEIGHT                = 39,
    SOUND_CUTSCENE_12_SHORT_TIME    = 40,
    SOUND_END_LEVEL_MUSIC           = 41,
    //sound_42 = 42,
    SOUND_VICTORY_JAFFAR            = 43,
    SOUND_SKEL_ALIVE                = 44,
    SOUND_JUMP_THROUGH_MIRROR       = 45,
    SOUND_CHOMPED                   = 46,
    SOUND_CHOMPER                   = 47,
    SOUND_SPIKED                    = 48,
    SOUND_SPIKES                    = 49,
    SOUND_STORY_2_PRINCESS          = 50,
    SOUND_PRINCESS_DOOR_OPENING     = 51,
    SOUND_STORY_4_JAFFAR_LEAVES     = 52,
    SOUND_STORY_3_JAFFAR_COMES      = 53,
    SOUND_INTRO_MUSIC               = 54,
    SOUND_STORY_1_ABSENCE           = 55,
    SOUND_ENDING_MUSIC              = 56,
};

enum seqids {
    SEQ_TURN = 5,
    SEQ_FALL = 7,
    SEQ_RUN = 84,
};

enum colorids {
    COLOR_BLACK = 0,
    COLOR_DARKBLUE = 1,
    COLOR_DARKGREEN = 2,
    COLOR_TURQUOISE = 3,
    COLOR_RED = 4,
    COLOR_PURPLE = 5,
    COLOR_GOLD = 6,
    COLOR_GREY = 7,
    COLOR_DARKGREY = 8,
    COLOR_BLUE = 9,
    COLOR_GREEN = 10,
    COLOR_LIGHTBLUE = 11,
    COLOR_RED = 12,
    COLOR_VIOLET = 13,
    COLOR_YELLOW = 14,
    COLOR_WHITE = 15,
};

enum rowids {
    ROW_ABOVE  = -1,
    ROW_TOP    = 0,
    ROW_MIDDLE = 1,
    ROW_BOTTOM = 2,
    ROW_BELOW  = 3,
};

enum potsizeids {
    POT_SMALL = 0,
    POT_BIG = 1,
};

// SCRIPT FUNCTION PROTOTYPES

// Scripts are executed in REVERSE loading order. The main script always runs last.
void load_script(char* filename);

// Registered variables will be saved in and loaded from savestates (replays, quicksave)
void register_savestate_variable_explicitly(void* source, int num_bytes, char* variable_name);
// You can use this macro instead of the explicit function (so you don't need to think too much about addresses, sizes and variable names)
#define register_savestate_variable(var) register_savestate_variable_explicitly(&var, sizeof(var), #var)

// accessible game functions
void play_sound(int sound_id);
void stop_sounds(void);
void draw_kid_hp(short curr_hp, short max_hp);
void take_hp(int count);
void set_hp_full(void);
void set_char_sequence(short seq_index);

// "encapsulated" data accessors:
word get_minutes_remaining(void);
word get_ticks_remaining(void);
void set_time_remaining(word minutes, word ticks);

void select_tile_at_col_row(int room, int column, int row);
void select_tile_at_tilepos(word room, word tilepos);
// select_tile() is "overloaded"; it can be used either with:
//   2 arguments --> calls: select_tile_at_tilepos()
//   3 arguments --> calls: select_tile_at_col_row()
#define GET_OVERLOADED_FUNC(_1, _2, _3, NAME, ...) NAME
#define select_tile(...) GET_OVERLOADED_FUNC(__VA_ARGS__, select_tile_at_col_row, select_tile_at_tilepos)(__VA_ARGS__)

byte get_curr_tile(void);
byte get_curr_modifier(void);

void set_curr_tile(byte new_tile);
void set_curr_modifier(byte new_modifier);
void set_curr_tile_and_modifier(byte new_tile, byte new_modifier);

void set_tile(word room, word tilepos, byte new_tile);
void set_modifier(word room, word tilepos, byte new_modifier);
void set_tile_and_modifier(word room, word tilepos, byte new_tile, byte new_modifier);

word get_hp(void);
void set_hp(word new_hp);
word get_max_hp(void);
void set_max_hp(word new_max_hp);

void set_flash(word color, word duration);

void set_potion_color(word color);        // use only in custom_potion_anim
void set_potion_pot_size(word pot_size);  // use only in custom_potion_anim

void show_time(void);

short have_sword(void);
void set_have_sword(short kid_has_sword);

word get_curr_level(void);
word is_leveldoor_open(void);
void set_next_level(word level_number); // use only in on_end_level

void set_level_start_sequence(word sequence_index); // use only in on_load_level
void disable_level1_music(void);

void show_dialog(char* text);


// DATA

extern level_type* ptr_level;
#define level (*ptr_level)

extern char_type* ptr_kid;
#define kid (*ptr_kid)

extern char_type* ptr_guard;
#define guard (*ptr_guard)

#endif // POP_SCRIPT_H
This is far from complete, many things are missing, but you can already do some interesting things.
You can also use some C library functions (such as printf).

The work ahead is somewhat daunting still, if we decide to go ahead with this...
At the very least I had fun coming this far!

This is only a proposal, so please discuss!

GitHub branch: https://github.com/Falcury/SDLPoP/tree/script
GitHub PR: https://github.com/NagyD/SDLPoP/pull/57
Attachments
SDLPoP_v1.17b2.zip
(4.85 MiB) Downloaded 93 times
SDLPoP Mods.zip
(100.41 KiB) Downloaded 97 times
User avatar
Norbert
The Prince of Persia
The Prince of Persia
Posts: 5743
Joined: April 9th, 2009, 10:58 pm

Re: SDLPoP scripting/modding (concept, ideas, discussion)

Post by Norbert »

This sure is interesting, nice work!
It took me a while to get it to work (on Linux), see below, but it works as advertised. :)
If the available scripting functions will be documented properly, I can see people using this.
This takes modding to a whole new level.

Here's the stuff I did to make it work:
- Added "script.o" to OBJ in Makefile
- Added "-ltcc" to the _second_ LIBS in Makefile
- Installed libtcc. (It cannot be installed directly from the apt repository, because that version gives an error that TCC_RELOCATE_AUTO is undeclared. I had to git clone http://repo.or.cz/tinycc.git; cd tinycc/; ./configure; make; sudo make install. And then I copied /usr/local/lib64/libtcc.* to /usr/lib/)
- Next I tried using the "Prince4D" levelset in SDLPoP.ini, but this gives a "Segmentation fault" because - as GNU Debugger showed me - that mod has no mod.scr. So I used your mod instead.
- pop_script.h has a redefinition of enumerator COLOR_RED, first as 4 then as 12.
- I got an error that x86-64/libtcc1.a could not be found in data/script/. I made a directory x86-64/ and copied libtcc1.a into it.
- After that it worked, although with a warning about the implicit declaration of snprintf. I tried adding "#include <stdio.h>" to second_script.scr, but then stdio.h complains it's unable to find stddef.h. I didn't look into this further.
Falcury
Calif
Calif
Posts: 565
Joined: June 25th, 2009, 10:01 pm

Re: SDLPoP scripting/modding (concept, ideas, discussion)

Post by Falcury »

Norbert wrote:This sure is interesting, nice work!
It took me a while to get it to work (on Linux), see below, but it works as advertised. :)
If the available scripting functions will be documented properly, I can see people using this.
This takes modding to a whole new level.
Thank you, and awesome that you got it to work!

There is still a lot of work to be done on the scripting functions... Some things in particular that I think should be discussed:
- Should the script accessor names always match the source code equivalent exactly? (sometimes I have slightly changed accessor names where I thought it made sense - but this can be reverted)
- Should we provide "naked access" to global variables such as rem_min, rem_tick? (low abstraction, very readable code if direct variable access is all that is needed) Or should we wrap them all in accessor functions like the set_remaining_time() function? (more abstraction, good opportunity to do safety checks or handle side effects, potentially more code bloat) Or should we decide on a case by case basis? (pragmatic approach)

N.B. In pop_script.h "naked access" to data symbols requires a bit of a trick (not ideal but at least it works):

Code: Select all

extern level_type* ptr_level;
#define level (*ptr_level)
Norbert wrote:Here's the stuff I did to make it work:
- Added "script.o" to OBJ in Makefile
- Added "-ltcc" to the _second_ LIBS in Makefile
You mean like this?
LIBS := $(shell pkg-config --libs sdl2 SDL2_image SDL2_mixer) -ltcc
Norbert wrote:- Installed libtcc. (It cannot be installed directly from the apt repository, because that version gives an error that TCC_RELOCATE_AUTO is undeclared. I had to git clone http://repo.or.cz/tinycc.git; cd tinycc/; ./configure; make; sudo make install. And then I copied /usr/local/lib64/libtcc.* to /usr/lib/)
Hm, it sounds like it was a bit of a painful process... So I take it that there are no working Linux binaries of the static libtcc library available for download? Perhaps we could distribute the one that you compiled, so that other people on Linux don't need to repeat the steps? (I don't know if this would be practical, having no experience with programming on Linux!)
Norbert wrote:- Next I tried using the "Prince4D" levelset in SDLPoP.ini, but this gives a "Segmentation fault" because - as GNU Debugger showed me - that mod has no mod.scr. So I used your mod instead.
If I remove mod.scr from the mod folder, for me SDLPoP only prints out a message that mod.scr was not found (I should fix this I think). After that it continues normally. But I do seem to get segmentation faults when e.g. custom versions of VDUNGEON.DAT are present (I haven't yet been able to find out what causes this).
Norbert wrote:- pop_script.h has a redefinition of enumerator COLOR_RED, first as 4 then as 12.
Hm, on screenshots the colors 4 and 12 are RBG(168, 0, 0) and (224, 0, 48) respectively.
Color 12 is used for the red potion bubbles, while color 4 is the red background flash.
So I would guess that color 4 should be renamed COLOR_DARKRED (color_4_darkred in types.h)
Norbert wrote:- I got an error that x86-64/libtcc1.a could not be found in data/script/. I made a directory x86-64/ and copied libtcc1.a into it.
On my system I am currently compiling to 32-bit; perhaps if I changed my setup to output 64-bit executables I might run into the same problem?
Norbert wrote:- After that it worked, although with a warning about the implicit declaration of snprintf. I tried adding "#include <stdio.h>" to second_script.scr, but then stdio.h complains it's unable to find stddef.h. I didn't look into this further.
I suppose that libtcc expects some declaration of the libc functions in the script. We could perhaps copy the header tcclib.h from the folder "tcc/include/" to the "data/script/" directory (as well as stddef.h, stdarg.h, which are in turn included by tcclib.h).
Or we could add the declarations explicitly to pop_script.h.
David
The Prince of Persia
The Prince of Persia
Posts: 2846
Joined: December 11th, 2008, 9:48 pm
Location: Hungary

Re: SDLPoP scripting/modding (concept, ideas, discussion)

Post by David »

I got the library from: http://download.savannah.gnu.org/releas ... 32-bin.zip
I had to make a library (*.a) file for myself using:

Code: Select all

dlltool.exe -d libtcc\libtcc.def -l libtcc.a -m i386 -f --32 libtcc.dll
Norbert wrote:- Next I tried using the "Prince4D" levelset in SDLPoP.ini, but this gives a "Segmentation fault" because - as GNU Debugger showed me - that mod has no mod.scr. So I used your mod instead.
In load_script_text(), add this line after fopen:

Code: Select all

    if (NULL == script_file) return NULL;
Falcury wrote:But I do seem to get segmentation faults when e.g. custom versions of VDUNGEON.DAT are present
It's not related to your changes in SDLPoP, but to the custom DAT files.

EDIT:
In the decompress_rle_* functions, change this:

Code: Select all

			} while (--count);
to this:

Code: Select all

			} while (--count && rem_length);
EDIT:
Fixed this: https://github.com/NagyD/SDLPoP/commit/ ... 48e1b8499a
User avatar
Norbert
The Prince of Persia
The Prince of Persia
Posts: 5743
Joined: April 9th, 2009, 10:58 pm

Re: SDLPoP scripting/modding (concept, ideas, discussion)

Post by Norbert »

Falcury wrote:You mean like this?
Yes.
Falcury wrote:So I take it that there are no working Linux binaries of the static libtcc library available for download?
I've tried to trace back the problem and this are my findings.

David writes he downloaded tcc-0.9.26-win32-bin.zip and created a library file from it, that apparently worked.
My guess is that you also use 0.9.26.
With my Linux distribution, Mint, I can use apt-get to easily retrieve precompiled software packages.
This also provides me with 0.9.26, but I got the error that script.c's TCC_RELOCATE_AUTO was undeclared.
Therefore I used TCC's latest Git files. With these, everything works for me.
This seems to indicate the Git files fixed a related problem, and probably other problems as well.

Version 0.9.26 was released on 15 February 2013, so more than three years ago!

When will these fixes be added to the APT repositories?
Well, this is where it becomes somewhat complicated.
Mint's APT repository currently has 0.9.26.
This is because it relies on Ubuntu's APT repository, which has 0.9.26 (and 0.9.27).
And this is because Ubuntu mostly relies on Debian, which has 0.9.26 (and 0.9.27).
Now, I could contact the Debian maintainers, but even the Git repository says the latest version is still 0.9.26.
Wikipedia also says 0.9.26.
The problem appears to be that Fabrice Bellard, the original TCC developer is "no longer working on TCC".
He points to the TCC mailing list, but the question is: did Bellard leave someone in charge to officially publish new releases?
On 28 February 2016, someone asked on the mailing list "Don't you think it's time to make a stable 0.9.27", but... who's going to release it?
David
The Prince of Persia
The Prince of Persia
Posts: 2846
Joined: December 11th, 2008, 9:48 pm
Location: Hungary

Re: SDLPoP scripting/modding (concept, ideas, discussion)

Post by David »

Norbert wrote:David writes he downloaded tcc-0.9.26-win32-bin.zip and created a library file from it, that apparently worked.
For clarification: The ZIP includes a precompiled libtcc.dll.
I only had to make the libtcc.a file that tells the linker that it can find tcc_* functions in that DLL.
User avatar
Norbert
The Prince of Persia
The Prince of Persia
Posts: 5743
Joined: April 9th, 2009, 10:58 pm

Re: SDLPoP scripting/modding (concept, ideas, discussion)

Post by Norbert »

My point was that you also used 0.9.26 on Windows, and didn't mention any errors.
So apparently the problem I have with 0.9.26 is just on Linux.
David
The Prince of Persia
The Prince of Persia
Posts: 2846
Joined: December 11th, 2008, 9:48 pm
Location: Hungary

Re: SDLPoP scripting/modding (concept, ideas, discussion)

Post by David »

"TCC_RELOCATE_AUTO" is defined in my libtcc.h as: #define TCC_RELOCATE_AUTO (void*)1
So it seems there are different versions labeled 0.9.26 and not all of them contain it?

Yes, I downloaded the *.deb file from https://packages.debian.org/wheezy/libtcc-dev and libtcc.h is different.
Note that the full version number also contains "git20120612", a date before the release.
Falcury
Calif
Calif
Posts: 565
Joined: June 25th, 2009, 10:01 pm

Re: SDLPoP scripting/modding (concept, ideas, discussion)

Post by Falcury »

oitofelix has proposed Guile as an alternative scripting framework (original post):
oitofelix wrote:
Norbert wrote:Falcury made some impressive modifications for a beta release that accompanied his proposal here.
It takes modding to a whole new level.
Indeed. However, the only tangible benefit of using libtcc is not requiring modders to setup a development environment for building SDLPoP, since no higher abstraction or features are added on top of the raw SDLPoP's code. Furthermore, that limits the architectures for which scripted mods work since libtcc must explicitly support them.

Ideally, a scripting language should offer the following features to the users of an extensible program:
  • Architecture neutrality: this means that the scripting code should be able to run on any architecture the host program's binary could be built for.
  • High-level dynamic language: this means that the provided scripting language should abstract hardware and operating system matters, and that symbols may be redefined at run-time.
  • Friendlier interfaces: this means that simple and well-defined interfaces should be provided to access the host program's features.
  • REPL (read-eval-print-loop) running in a separate thread: this means that the game can be (re)programmed on the fly without the need for restart or pause, and a command interface is provided for evaluating language expressions and getting back their results, as well as their side effects on the game.
That's the reason why I've chosen GNU Guile for MININIM. It's the GNU project's implementation of the Scheme language, a powerful and elegant Lisp dialect.
Post Reply