ok, I said to myself: nice and easy. Let's add to csprogs.dat, another hello.dat which has only one stupid function that prints "hello" in csprogs.dat. Why should it be so difficult, huh? Huh?Huh?Well, it's kinda difficult!

for lack of a better name, a 'friked' progs is one that has been compiled with string constants stripped from the progs.with fteqcc, you should never use -O3 for addons. -O2 is the highest optimisation level supported for addons.

so yeah, strings...in qc, string immediates are stored as an offset from the string table, the first byte of which is always empty, thus the null string is always empty.side note: in 32bit processes, this string offset thing works well enough to refer to any string in the engine's memory space, and this is why you can't just recompile vanilla quake as 64bit (because pointer->string->pointer offsets get truncated and the pointers end up pointing to the wrong place with a crash when its executed).anyway, this string table thing is the text blob that you can normally read inside the progs file. all qc strings are expressed relative to that (unless the engine uses some of the high bits to denote special string types from eg strzone or tempstrings or whatever).this of course is a problem when there are logically multiple string tables, which would make strings in one progs unreadable gibberish while running code in another, so to fix that fteqw loops through some 'defs' table within the progs and biases all the strings that it finds to be relative to the string table within the main progs, allowing entity fields to be read as actual strings, with no special conversions needed for string args between addons, etc.obviously this only works when the defs table actually still includes all the string immediates - if that data was stripped out then those embedded strings will be gibberish. and that's what fteqw is noticing and complaining about in an attempt to avoid total malfunction. obviously you can still end up with false positives if you don't have any string immediates, but that generally only happens in small test mods...note that stripped string immediates is fine within the main progs, as there's no need to rebias when they're already set correctly anyway.

Wow thanks Spike, I didn't know fteqcc did optimisations at all! I'll use O2 from now on for addons

Very interesting the concept of create "hook" functions like Drupal for example does, which it's quite cool for devs that don't want to re-invent the wheel but add only new functionalities. UT mutators-like will be a breeze with this method.

I don't understand if your exporting a value or a function (what is ptr? It seems a func name). I'm sorry but pointers litteraly freak me out!Another thing. You declared test123() func in addons.dat but you initialized it in csprogs.dat. I'd need the opposite: create all the code in addons.dat and jus call the function in csprogs.dat.Is it possible? There's a simpler way that don't involve pointers? Pleease! I could be good enough without using hook functions as first experiment, just putting all the code in addons and using it in csprogsThanks a bunch again

toneddu2000 wrote:Another thing. You declared test123() func in addons.dat but you initialized it in csprogs.dat. I'd need the opposite: create all the code in addons.dat and jus call the function in csprogs.dat.

Just invert things ? Unless there is some CSQC specific issue I am not aware, it's a matter of placing in csprogs.dat:

The only problem/weirdness I see is creating a runtime dependency of addons.dat inside csprogs.dat. Usually this would NOT be desirable (it would be okay if addons.dat does require csprogs.dat though).Personally, I'd avoid making things more complex than required but hey, it's perfectly viable from the technical point of view.

I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC (LordHavoc)

'extern' only works to import from progs which are already loaded. they won't work the other way around (and you don't really know which dat the symbol was copied from either), so be sure to use it only when its meant to exist in the main progs. also, only use it for functions.

I don't know why you're getting a syntax error from that def.origupdateview = externvalue(MAINPROGS, "CSQC_UpdateView");externset(MAINPROGS, wrapperupdateview, "CSQC_UpdateView");those two lines should work the same, to read the prior value and then clobber it with some replacement/wrapper function (which can call the original function as needed). no pointers needed.

note that the CSQC_UpdateView function I wrote provides two alternative ways to call a function from the main progs. one is by name, the other does a name lookup in one (slow) step up then calls by value (which can be repeated without the need for constant lookups).however, I'd personally recommend to make 'register' functions for various things that can then be called from both the main progs or your addon's init functions, then you're not quite so limited in what addons can do when you want to extend them.

frag.machine wrote:The only problem/weirdness I see is creating a runtime dependency of addons.dat inside csprogs.dat. Usually this would NOT be desirable (it would be okay if addons.dat does require csprogs.dat though).Personally, I'd avoid making things more complex than required but hey, it's perfectly viable from the technical point of view.

Thanks frag.machine for the suggestion, I only wanted to make things tidy and to release separated addons that devs could use in their main progs without re-inventing the wheel (UI most of all, because it's a painful process), but, if it's not possible to do, I'll stick with original method to release ui source code + a README file where explain where putting files in progs.src and how to call functions. Just for a moment a dreamed about an Open FTE Marketplace like Unreal or Unity's ones....

Spike wrote:'extern' only works to import from progs which are already loaded. they won't work the other way around (and you don't really know which dat the symbol was copied from either), so be sure to use it only when its meant to exist in the main progs. also, only use it for functions.

mmm..got it. You think there's chances you could add in the future something like this

I don't know why you're getting a syntax error from that def.origupdateview = externvalue(MAINPROGS, "CSQC_UpdateView");externset(MAINPROGS, wrapperupdateview, "CSQC_UpdateView");those two lines should work the same, to read the prior value and then clobber it with some replacement/wrapper function (which can call the original function as needed). no pointers needed.

No more error, thanks! But now, when map starts, it prints on top screen .com.com.com.com.com.....and so on, for 4 lines! I have to comment print function in calledfrommainprogs to make it stop.The problem is that I don't understand the utility to have a function declaration in main progs and call it in additional ones. For things like UI or Skeleton libraries, this method wouldn't help me.

Anyway the code you posted unfortunately doesn't print anything on screen or in console, so it seems that additional progs is loaded(in fact no error "gah"), but parented functions are lost

Anyway the code you posted unfortunately doesn't print anything on screen or in console, so it seems that additional progs is loaded(in fact no error "gah"), but parented functions are lost

Little update to what I wrote: copying exactly your code both in addons and main progs now it prints "dude" and "regular updateview", so it lost "it failed, dude". If I remove comma and space in string("it failed dude"), it prints "ude" and "regular updateview". If I replace string with ftos(somehandle), it prints "ateview" and "regular updateview", but first it printed something like "mmainprogs" (with 2 m, I guess)