Active player (391)
Joined: 12/20/2022
Posts: 39
Location: UK
So I've been speedrunning for a few years now and gained a reputation for running Spectrum games (even though I run lots of other games too, it's just that not many other people do Spectrum games); I decided to get into tool-assisted runs of the games I'm more familiar with, as there aren't many of those for the Spectrum either (especially when it comes to the more classic games) and submitted a couple of movies already. But I have a query which affects future submissions of mine... The Spectrum, like many microcomputers of the era, boots into a BASIC prompt. This allows the user to enter programs and modify memory with simple commands, as normal and expected usage of the computer. On a few occasions, developers have issued patches to their games in the form of programs you type in and run before loading the game, and it would seem silly to not allow it for these cases. On the other hand, this also means you can write your own patches to do literally anything, and completely trivialise any game by removing all enemies, starting in the end room, or just overwriting the code with an entirely new game, and this would obviously not be in the spirit of the game - they're effectively the same as Game Genie codes, which are typically banned. The grey area comes with manipulating memory before loading a game. The aforementioned patches typically work by writing a custom loader, which then ignores the original game's loader and runs its own instructions after loading the game data. If the original game's loader is used, and isn't modified in any way, it's not possible to patch the game as the game data will overwrite data currently in memory. However, it's rare for game data to load and fill the entire RAM, and usually certain areas of memory are deliberately left untouched; especially system variables. Many games use the FRAMES variable (3 bytes at 0x5C78), which counts the number of frames since the computer was turned on, to seed the random number generator. This variable can be set by the user manually before loading the game to manipulate RNG; this doesn't require a special loader and doesn't change any of the game data - should this be allowed? Some games use built-in system routines and fail to set system variables before using them (e.g. using the BASIC keyboard interpreter without setting auto-repeat times); these could easily be changed before loading the game to modify behaviour without modifying the game itself. Should this be allowed? Some games read general memory not loaded or initialised by the game itself; it could easily be the case that, in normal and expected usage of the system, this memory just happens to be set to something beneficial to the run. Should this be allowed? We discussed this a couple of years ago with regards to RTA speedrunning in the Speedtrum Specrunning Discord, and came to the conclusion that as long as the game is loaded from the very start, using the standard LOAD "" in regular Spectrum BASIC, the built-in Tape Loader (for 128K machines and later), or using a type-in program provided by the developer themselves, any prior activity is allowed, including any arbitrary setting of system variables. However, all custom loaders (save for the aforementioned developer provided ones) are prohibited, as is interrupting the loading process to modify memory during or after loading. There are a couple of justifications for this: 1. RNG manipulation can make or break some runs, and runners playing on real hardware are already at a massive disadvantage when it comes to waiting four minutes for the game to load between attempts - imagine if they had to load the game dozens of times just to get the right seed! Allowing the FRAMES variable to be set reduces this discrepancy significantly. (There are still issues with getting the right seed due to tape loading times, and we don't recommend loading from tape as a result, but still...) 2. Other memory addresses not being initialised correctly is an existing bug in the game; no bug or glitch is being introduced or added, merely exploited, and exploiting bugs is a natural part of speedrunning. Obviously 1 is not a consideration for a TAS; but even so I lean towards allowing this as it massively lowers the discrepancy between minimising actual gameplay time and minimising the TAS frame count. (What if waiting 20 minutes before loading the game means you can complete it a few seconds faster? An extreme example for sure, but possible.) I haven't tagged this as [ZXS] as this can also apply to C64 games, as well as CPC in the future. TL;DR: do I have to load a game with LOAD "" or can I load it with POKE 23673,42: LOAD "" ?
DrD2k9
He/Him
Editor, Judge, Expert player (2222)
Joined: 8/21/2016
Posts: 1091
Location: US
I personally don't see a problem with resetting the FRAMES variable usign this POKE command in either ZXS or C64 runs/TASes. To me, this is akin to pre-setting the RTC clock on other systems in order to manipulate RNG--which we currently allow (DOS, some handhelds, etc). The key to allowing something like this for C64 and ZXS, in my opinion, is that the POKE command must be performed before the LOAD command. If it was done after the LOAD but before a RUN command on C64 (and possibly ZXS, as I'm not as familiar with that system), the POKE could potentially modify what the game has written to RAM, which would be more like cheating as the game is already (at least in part) loaded into memory. Therefore, (theoretically) any RAM location could be manipulated by a POKE command prior to loading a game. When the game loads it will either overwrite whatever data is in RAM or ignore it. Any leftover/ignored RAM not specifically set by the game could theoretically be any value, and thus fair game for pre-load manipulation. A pre-load POKE command wouldn't modify the game in any way but simply change pre-load RAM status. If the game reads any of this pre-load RAM information, I see no reason why such modification of that RAM shouldn't be allowed. Ultimately, the site staff will have to make this decision though. FWIW, the console verification of my Gameboy Donkey Kong run required a separeate program to be run first to initialize the RAM (that's not directly initialized by the game) to a specific value to allow RNG to match what was created in BizHawk. Off the top of my head, I cant currently remember if BizHawk pre-initializes all RAM values to 0xFF or 0x00, but the initial RNG seed for Donkey Kong is pulled from a region of RAM not initialized by the game itself--which could be any value on a real system. The separate program just made it match BizHawk for console verification reasons.
Darkman425
He/They
Editor, Judge, Skilled player (1293)
Joined: 9/19/2021
Posts: 263
Location: Texas
For Game Boy games running on Game Boy Color or Game Boy Advance mode some games can have their initial RAM state modified in a meaningful way by switching the initial color pallet in the BIOS splash screen and has been proven to be console accurate. Poking FRAMES seems to be similar to that with RAM being modified before starting the game. I can see that as simply setting something to manipulate RNG as long as it's also correct with real hardware. From my understanding, something like poking the FRAMES variable falls under that category.
Switch friend code: SW-2632-3851-3712
Site Admin, Skilled player (1255)
Joined: 4/17/2010
Posts: 11495
Location: Lake Char­gogg­a­gogg­man­chaugg­a­gogg­chau­bun­a­gung­a­maugg
In the rules we have this:
Movie Rules wrote:
Gameplay must be accurate to hardware Some emulators such as BizHawk allow you to set a custom initial RAM state: This is only allowed if that RAM state is proven to be possible on console. For PC games, environment settings explicitly supported by the game or its documentation are allowed.
  • If a setting is not mentioned in any way, it's allowed if it doesn't cause noticeable audio, video, and/or gameplay-affecting glitches.
Converting a game image from one format to another is only allowed if it's supported on the device meant to run that game, and the game itself remains unchanged.
It looks similar to arbitrarily setting OS time during your PC game movie. The OS allows to set it freely and directly, so as long as you don't change the game it's legitimate. With Spectrum and C64, BASIC was the way to use the system, so setting system variables that way also sounds good. If the game doesn't break from your system tweaks, even the current rules already allow it. And even if it breaks, as long as the system explicitly exposes such a setting to the user, it also feels okay to at least have it as a separate branch. We've had this with Flash games that would work very differently if you resize the window arbitrarily, which was entirely possible with original Adobe Flash Player, but looked like a one-off exception, so it was unclear how to handle it officially. Now I'm getting the bigger picture.
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting.
Active player (391)
Joined: 12/20/2022
Posts: 39
Location: UK
feos wrote:
It looks similar to arbitrarily setting OS time during your PC game movie. The OS allows to set it freely and directly, so as long as you don't change the game it's legitimate. With Spectrum and C64, BASIC was the way to use the system, so setting system variables that way also sounds good. If the game doesn't break from your system tweaks, even the current rules already allow it. And even if it breaks, as long as the system explicitly exposes such a setting to the user, it also feels okay to at least have it as a separate branch. We've had this with Flash games that would work very differently if you resize the window arbitrarily, which was entirely possible with original Adobe Flash Player, but looked like a one-off exception, so it was unclear how to handle it officially. Now I'm getting the bigger picture.
This is clear and essentially matches the consensus, thanks for the confirmation.
Site Admin, Skilled player (1255)
Joined: 4/17/2010
Posts: 11495
Location: Lake Char­gogg­a­gogg­man­chaugg­a­gogg­chau­bun­a­gung­a­maugg
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting.
Joined: 1/13/2007
Posts: 343
Pokes can be used to do many things that are not okay. for example you can poke in a small ML routine, and then redirect a vector to it and that could affect the game later. It's very possible if you are clever enough to add a cheat before load by pure POKEing. For c64, the only thing that should be acceptable is messing with the time of day clock before load, and adjusting the random seed before load. Anything else is either cheating or will lose time. Poking in a trainer, messing with the games program with pokes, and messing with system vectors is right out.
Site Admin, Skilled player (1255)
Joined: 4/17/2010
Posts: 11495
Location: Lake Char­gogg­a­gogg­man­chaugg­a­gogg­chau­bun­a­gung­a­maugg
It's easy to see that something fishy is being done by looking at initial input, and it's as easy as asking what it does, then we can figure out the rest. If games explicitly ask for this, it can't be cheating.
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting.
Active player (391)
Joined: 12/20/2022
Posts: 39
Location: UK
zaphod77 wrote:
Pokes can be used to do many things that are not okay. for example you can poke in a small ML routine, and then redirect a vector to it and that could affect the game later. It's very possible if you are clever enough to add a cheat before load by pure POKEing.
Can you give an example of POKEs done before load that add a cheat to the game in some way? I'm not aware of any way to change the system in such a way that performing the standard LOAD command results in the game being modified, but I'd be interested to see otherwise.
Joined: 1/13/2007
Posts: 343
I will give a real example. Jumpman has a simple ml loader inside basic that uses the kernal routines to load the main program, and then jumps to it's start address. But you can write a small M/L routine to copy the kernel to RAM underneath. You can do it with pokes (easy to do rapidly under TAS conditions), then do another poke to change the vectors to make it start automatically without a sys command, and the routine can restore the vector you just poked. Then you can bank out the kernal with another poke. now kernel is in RAM, and you can directly modify it with pokes. Now you patch the load routine so that after the load is finished, and before the routine returns, it JSRS to another bit of code you poked in that changes the RAM of the game. say, to disable sprite to sprite collision checks. it just patches blind. The code runs after the first load, but does nothing. it also runs after the load of the main program, when it's there to modify. and this time it does something. Now you are cheating, and everything you did was BEFORE the load that kicks off starting the game normally. Alternatively, you can create a TSR with POKEs that messes with the loader to do some similar cheating. For a basic game, you can copy BASIC to ram, and then modify the basic interpreter itself and use THAT to cheat in a BASIC game. Pretty much the only thing that is far is messing with the rng, though if a game is silly enough to make assumptions about the starting background and text colors and not set them by hand, i'd say those are fair game to change.
DrD2k9
He/Him
Editor, Judge, Expert player (2222)
Joined: 8/21/2016
Posts: 1091
Location: US
zaphod77 wrote:
I will give a real example. Jumpman has a simple ml loader inside basic that uses the kernal routines to load the main program, and then jumps to it's start address. But you can write a small M/L routine to copy the kernel to RAM underneath. You can do it with pokes (easy to do rapidly under TAS conditions), then do another poke to change the vectors to make it start automatically without a sys command, and the routine can restore the vector you just poked. Then you can bank out the kernal with another poke. now kernel is in RAM, and you can directly modify it with pokes. Now you patch the load routine so that after the load is finished, and before the routine returns, it JSRS to another bit of code you poked in that changes the RAM of the game. say, to disable sprite to sprite collision checks. it just patches blind. The code runs after the first load, but does nothing. it also runs after the load of the main program, when it's there to modify. and this time it does something. Now you are cheating, and everything you did was BEFORE the load that kicks off starting the game normally. Alternatively, you can create a TSR with POKEs that messes with the loader to do some similar cheating. For a basic game, you can copy BASIC to ram, and then modify the basic interpreter itself and use THAT to cheat in a BASIC game. Pretty much the only thing that is far is messing with the rng, though if a game is silly enough to make assumptions about the starting background and text colors and not set them by hand, i'd say those are fair game to change.
While all this could be done, it wouldn’t be easily done in an obfuscated way. Any POKE commands used in a TAS should be thoroughly explained in the submission notes and verifiable. If a judge can see that the actions taken don’t match the claim in the submission notes, it can be rejected for cheating/disallowed game modification. If POKE commands aren’t explained at all, the submission would (at minimum) require more info before a valid judgment can be made. If the author never responds as to why the POKE commands is present, I feel that it should be an instant rejection; even if it would otherwise have been a legit POKE use.
Active player (391)
Joined: 12/20/2022
Posts: 39
Location: UK
zaphod77 wrote:
Now you patch the load routine so that after the load is finished, and before the routine returns, it JSRS to another bit of code you poked in that changes the RAM of the game. say, to disable sprite to sprite collision checks. it just patches blind.
I'd argue this is where it fails - you're not loading the game with the standard loader anymore, you've created a custom loader, which is explicitly not allowed.
Joined: 1/13/2007
Posts: 343
The loader on the disk is unchanged. you are still using the loader to load it. you essentially poked in a modification to the system libraries. Pokes can be used both to create and execute arbitrary code. its also possible as i said to add a wedge. something interrupt driven that can modify things later without actually changing the code at all. And this would beat the rule against using the unmodified loader My point is that there's no distinction between data and code in early computer memory, and no matter how cleverly you try to write things, the only way that actually works is to whitelist specific POKES as okay, as the poke command is just too powerful to list what you can't do with it, so you have to instead list what is okay to do with it. Messing with the system time is specifically allowed, so doing that with a POKE is fine. Most other uses of pokes simply wouldn't fly. Messing with uninitialized ram is also arguably okay, provided no ram that IS initialized is POKEd. And quite a lot of RAM on the c64 IS initialized by the bootup process. so messing with it is not fair. If it has a consistent default state, then changing this default shouldn't be allowed, unless it's the TOD clock. For example if Cheatmen 2 was a c64 game, POKEing some ram to let you get past the crash would be okay, specifically because it's unintialized RAM. And if a game is really silly enough to use uninitialized ram to seed the RNG, then poking to take advantage should be fine.
Joined: 1/13/2007
Posts: 343
the simplest rule is does the poke have any affect outside of the game at all. if NO, then the poke is fine. note that there are pokes that while they do not have immediately observable effects, it doesn't mean they have no effect outside of the game. If it does have an effect outside of the game, then it should be disallowed on general principle, with the only exceptions allowed being directly manipulating time of day, or manipulating the seed for a built-in RNG/