TIC-80 icon indicating copy to clipboard operation
TIC-80 copied to clipboard

Feature Request: Check TIC-80 version within the script portion of a cartridge

Open sorucoder opened this issue 2 years ago • 12 comments

Maybe a global constant, like how Lua uses _VERSION. Or replace that constant outright.

sorucoder avatar Apr 13 '22 00:04 sorucoder

May I ask what is your purpose for this?

nesbox avatar Apr 13 '22 05:04 nesbox

Implement polyfills. For example, implementing the BOOT callback pre-version 1.0.

sorucoder avatar Apr 13 '22 10:04 sorucoder

I don't think this is necessarily good if it encourages users to continue to design for OLDER versions of the software after newer ones are released... what I do think would be nice if is the cartridge had compiled in the "minimal viable version" or some such so that if someone downloads a 1.2 cartridge it can't say "Sorry, this doesn't run on 0.9, you'll need to upgrade your TIC-80 to v1.2 to run this cartridge".

joshgoebel avatar Apr 14 '22 01:04 joshgoebel

Late to the party, I know, but I think this would definitely be useful for polyfills of features that haven't been released. For instance, the only people who currently have access to 1.0.whatever builds of TIC are (1) the people who build it from source and (2) the people who get it from 1 (or from nightlies, etc.)

Most people are still on 0.90.1723 most likely. So (assuming a _TIC80_VERSION variable that stores a semver list {major,minor,patch}):

function BOOT()
    trace("do boot stuff")
end

function TIC()
    trace("do TIC stuff")
end

if _TIC80_VERSION[1]<1 then BOOT() end

That way, if the cart is being played on TIC-80 pre-1.0, it (the cart) will call the BOOT() function, since TIC-80 pre-1.0 doesn't know that it's supposed to call BOOT(). If the cart is being played on TIC-80 1.0 or later, then it won't, since TIC-80 will call it itself. Same goes for any feature that hasn't shipped in an officially released build.

MineRobber9000 avatar Apr 18 '22 18:04 MineRobber9000

Even if we decide to add it it wouldn't be added until the 1.0 release anyways, so BOOT() would already be off the table - since it would be included in every version that knew that it's version was... so at the time of 1.0's release, it would be useful for nothing... it only might have utility given future post 1.0 versions.

joshgoebel avatar Apr 19 '22 18:04 joshgoebel

Well that's easy:

function BOOT()
    trace("do boot stuff")
end

function TIC()
    trace("do TIC stuff")
end

if (not _TIC80_VERSION) or _TIC80_VERSION[1]<1 then BOOT() end

I'm not really on board with how dismissive you are of the idea. 1.0 probably isn't going to be the last time an API change occurs. Not to mention you say:

Even if we decide to add it it wouldn't be added until the 1.0 release anyways, so BOOT() would already be off the table - since it would be included in every version that knew that it's version was... so at the time of 1.0's release, it would be useful for nothing... it only might have utility given future post 1.0 versions.

But in your first response you said:

what I do think would be nice if is the cartridge had compiled in the "minimal viable version" or some such so that if someone downloads a 1.2 cartridge it can't say "Sorry, this doesn't run on 0.9, you'll need to upgrade your TIC-80 to v1.2 to run this cartridge".

0.9 wouldn't know how to read that chunk (not to mention I'm not a fan of that idea to begin with) so it would only work for versions post 1.0.

MineRobber9000 avatar Apr 19 '22 21:04 MineRobber9000

I'm not really on board with how dismissive you are of the idea.

Don't take it personally. You're obviously enthusiastic about it, I'm simply not. We're all entitled to our opinions. I'm always trying to discover the underlying problem... often what users ask for initially isn't actually the best solution - just the first one they thought of. (see thoughts further below)

Well that's easy:

You've mentioned Lua only... How this might work would need to be considered for all languages we support, not just Lua. For compiled languages it would need to be added to the API itself since there are no such things as "magic variables"... ie, it's not something you could "probe" for before the API exists. That's probably only a viable idea for scripting runtimes (and perhaps not even ALL scripting runtimes)

Also (in scripting runtimes at least), might this possibly be done just by sniffing which API functions are defined - without the need to add any additional API at all?

1.0 probably isn't going to be the last time an API change occurs

Of course not, I only mentioned that so far as the main example you provided (BOOT) wouldn't really be relevant by the time this feature was added.


If the goal is to get more people using 1.0 features I think a better plan might be to make the pre-releases more visible and easier to access (not sure what effects this might have on support though)... BOOT is a nice, but overly simplistic example. Supporting the new line and triangle floating point APIs would require MUCH more complex polyfills (and could also suffer from performance issues).

And any polyfills would need to be written per language. Personally, I'm against promoting one language above the others. Upgrading to 1.0 beta and coding against that allows all languages to benefit equally (from API improvements), while writing polyfills in Lua only benefits Lua.

joshgoebel avatar Apr 19 '22 21:04 joshgoebel

I'm not really on board with how dismissive you are of the idea.

Don't take it personally. You're obviously enthusiastic about it, I'm simply not. We're all entitled to our opinions. I'm always trying to discover the underlying problem... often what users ask for initially isn't actually the best solution - just the first one they thought of. (see thoughts further below)

It's admirable that you're looking to find the real underlying cause and solve it-- but your tone in your messages comes more across as "that's dumb don't do that" rather than "what's the underlying cause of this issue".

Well that's easy:

You've mentioned Lua only... How this might work would need to be considered for all languages we support, not just Lua. For compiled languages it would need to be added to the API itself since there are no such things as "magic variables"... ie, it's not something you could "probe" for before the API exists. That's probably only a viable idea for scripting runtimes (and perhaps not even ALL scripting runtimes)

I mentioned Lua because it's the one I use. Obviously, a complete solution would have to take all of the languages into account, but I figured for the sake of illustrating the use case, I'd stick to the language I know how to use.

I would actually agree on the point that it would be best as an API function, mainly because Wren can't probe for it (undefined variables are nil in Lua/Moonscript/Fennel, we can use a try/catch in JS, we can use defined?(_TIC80_VERSION) in Ruby, but Wren will throw a compile error if you attempt to even think about using a nonexistent variable). Probably, a version function that returns the list in question (in Wren you can use Fiber.try on a Fiber to catch the error that TIC doesn't implement the given function).

Also (in scripting runtimes at least), might this possibly be done just by sniffing which API functions are defined - without the need to add any additional API at all?

Yes, I suppose one could fingerprint the defined functions, but that's a lot of work for something that could be provided for us (and as you imply in your parenthetical, it wouldn't work for compiled langs, and given you made the WASM support, I'm sure you can see why that answer wouldn't be satisfactory).

1.0 probably isn't going to be the last time an API change occurs

Of course not, I only mentioned that so far as the main example you provided (BOOT) wouldn't really be relevant by the time this feature was added.

BOOT() was just a topical example. I'm sure if I think about it long enough I could find a better one.

If the goal is to get more people using 1.0 features I think a better plan might be to make the pre-releases more visible and easier to access (not sure what effects this might have on support though)...

This I can get behind 100%. We'd want people to be testing for bugs before the official release anyways 😁.

BOOT is a nice, but overly simplistic example. Supporting the new line and triangle floating point APIs would require MUCH more complex polyfills (and could also suffer from performance issues).

I'd probably argue that the floating point APIs are a good example of stuff you wouldn't be able to polyfill well if at all. Older versions of TIC-80 simply don't have the capacity to do the floating-point precision stuff.

And any polyfills would need to be written per language.

Well, presumably, all it takes is one person who writes in a language to write a polyfill and share it, and then we're set.

Personally, I'm against promoting one language above the others. Upgrading to 1.0 beta and coding against that allows all languages to benefit equally (from API improvements), while writing polyfills in Lua only benefits Lua.

Adding a version check (whether as a magic variable or as a function) would help people writing in any language, not just Lua. Adding it as a function would even allow Wren and WASM to get in on it (we won't have to worry about WASM lacking the ability to check for the existence of the function given that WASM is releasing with 1.0 presumably with this function in it).

MineRobber9000 avatar Apr 20 '22 02:04 MineRobber9000

I know I said polyfills was my use case for this feature, but really the main reason that this feature should be included is simply that if a user is using an older version of TIC-80 to run a more modern cartridge, with this feature it would be trivial to detect this and simply inform the user that they need the target version. Yes, it opens a Pandora's box of sorts (polyfills), but that's just because I am insane enough to implement those for myself (it's a fun exercise for me).

sorucoder avatar Apr 20 '22 14:04 sorucoder

but your tone in your messages comes more across as "that's dumb don't do that"

Not my intent. I have a very dead-pan/flat tone sometimes. Just because I don't like an idea doesn't mean I feel that it's "dumb". :-). I don't think it's a dumb idea, just one with downsides. It's just one solution to a problem; there are others.

with this feature it would be trivial to detect this and simply inform the user that they need the target version

Except TIC-80 should do that itself, not require every single game to implement this functionality over and over.. I'm just not sure at all that TIC-80 should be treated "as an OS" where a given game tries to detect it's environ and then adapt. That's a lot of complexity (for every single game to include). Rather I think our strong promises of backwards compatibility and people developing/testing (once) on the oldest version they plan to support is a better strategy.

IE, without strong automated testing I could imagine letting games do this type of detection is more likely to resort in more broken in the future. IE, a game uses the version API incorrectly - it works for 1.1 and 1.2 but breaks when 2.0 comes out - where-as if it was just coded normally without any fancy checks it would continue working just fine - because of our backwards compatible guarantees.

I've seen this play out in the real world... software that is overly conservative about which OS versions it supports... so it breaks on a new version (for no good reason) when if there were no in-built version checks it would not. Perhaps your personal usage of version would avoid this downfall, but others would not. Meanwhile the API that doesn't exist can't be abused or used incorrectly. :-)

I tend to be a minimalist when it comes to the API. Ultimately of course this is all up to @nesbox. I'm just laying out the "no" case as you've laid out the "yes" case. :-)

This I can get behind 100%.

So what is the issue now, just that downloads are too hidden?

joshgoebel avatar Apr 20 '22 14:04 joshgoebel

but your tone in your messages comes more across as "that's dumb don't do that"

Not my intent. I have a very dead-pan/flat tone sometimes. Just because I don't like an idea doesn't mean I feel that it's "dumb". :-). I don't think it's a dumb idea, just one with downsides. It's just one solution to a problem; there are others.

Fair enough. =D

(I cut the discussion about TIC-80 implementing a minimum viable version check, largely because it would require code analysis and I believe it's an argument worthy of its own issue instead of being stuck in the comments of this one; not to mention I don't have much more to add to it than I already have.)

This I can get behind 100%.

So what is the issue now, just that downloads are too hidden?

The nightly builds are linked right below the page telling you where to find the mainline releases. Awareness probably plays a bit of a factor, plus ease of use (it's a lot easier to just grab one of the individually linked binary downloads from the website/download from the releases than it is to find the nightlies link, click on it, develop against it, etc). And this is before we get into the fact that cartridges built for a version of TIC-80 that's still in beta is inaccessible to pretty much anybody who isn't on one of those beta versions.

MineRobber9000 avatar Apr 20 '22 23:04 MineRobber9000

To be honest, I don't like this idea with version access within script, sorry, this will clutter the cartridge code, and more elegant solutions could be found like you could check if BOOT() function exists and call it in this case if you want to support old clients.

nesbox avatar Apr 25 '22 10:04 nesbox