1 2
6 7
Active player (378)
Joined: 9/25/2011
Posts: 652
This is a thread to help DrD2k9 figure out the slot machine, and any other time savings in his SQ1 run.
Active player (378)
Joined: 9/25/2011
Posts: 652
Radient, when I try AGIHack, I get the following error:
This version of e:\Old Games\AGIHack\AGIHACK.EXE is not compatible with the version of Windows you're running. Check your computer's system information to see whether you need a x86 (32-bit) or x64 (64-bit) version of the program, and then contact the software publisher.
What version of Windows are you running it in? I'm using Windows 7. DrD2k9, I created a similar spreadsheet to list the numbers. I was hoping it'd cycle after a few thousand, but it looks like the RNG is complete and it doesn't cycle until all 65536 numbers have been used. <sigh> I've written lua scripts to search memory for when memory changes and when it doesn't change. Since we have no idea what the starting value is that's the best I think of to do. Now I've got to use that to hunt a memory address that changes when Random is called, and doesn't change otherwise. EDIT: I just had another idea. I'm going to give it a try and let you know how it goes. :)
DrD2k9 wrote:
It also appears based on LOGIC.000 that the random number is changed when certain instructions are typed. For example : if (said("use","anyword")) { random(79,80,v64); print.v(v64); } If I'm reading it correctly, this instruction appears to set the random variable to a number from 79-80. Different instructions set the value to different numbers. This may help in allowing us to set the value to a given range using text input while in the slot machine.
This sounds useful and may be worth more investigation.[/quote]
Active player (378)
Joined: 9/25/2011
Posts: 652
Hmm.. I was sure that'd work. Would you please check my lua recreation of the slot logic:
-- Populate RNG nums
for i=0,65536 do
	slotRNG[i] = (i*31821+1)%65536;
end

-- Return the random number for an RNG value
function calcRnd(rng,min,max)
	return (bxor(rng,rshift(rng,8))%(max-min+1))+min
end

-- Get the next RNG value after a spin
function getNextRNG(rng,slotRNG)
	nextRng=slotRNG[rng]
	slotRoll = calcRnd(nextRng,1,100)
	if slotRoll > 9 then
		repeat
			nextRng=slotRNG[nextRng]
			firstSlot=calcRnd(nextRng,0,3) 
		until firstSlot ~= 1
		if slotRoll > 16 then
			nextRng=slotRNG[nextRng]
			secondSlot=calcRnd(nextRng,0,3)
			if slotRoll > 32 then
				repeat
					nextRng=slotRNG[nextRng]
					lastSlot=calcRnd(nextRng,0,3)
				until lastSlot ~= firstSlot or lastSlot ~= secondSlot or firstSlot ~= secondSlot
				nextRng=slotRNG[nextRng] -- Random lose comment
			end
		end
	end
	return nextRng
end
DrD2k9
He/Him
Editor, Judge, Expert player (2214)
Joined: 8/21/2016
Posts: 1090
Location: US
Here's Logic.114 from AGI Studio. I think this is the logic for the spinning symbols. I know v124 is the variable for Buckazoids. (confirmed with ALT-D)(also not in this particular logic tree) I believe v64 is the random number; v125, v127, and v128 are the slot symbols; and v129 is the result. But I can't confirm those.
if (v134 > 0) {
  v134--;
  if (v134 == 0) {
    v129 = 1;
  }
  if (v134 == 1) {
    v129 = 5;
  }
  if (v134 == 2) {
    v129 = 7;
  }
  if (v134 > 2) {
    v134 = 3;
    v129 = 6;
  }
  v125 = v134;
  v127 = v134;
  v128 = v134;
}
else {
  random(1,100,v64);
  if (v64 < 3) {
    v125 = 0;
    v127 = 0;
    v128 = 0;
    v129 = 1;
  }
  else {
    if (v64 == 4) {
      v125 = 2;
      v127 = 2;
      v128 = 2;
      v129 = 7;
    }
    else {
      if (v64 < 6) {
        v125 = 3;
        v127 = 3;
        v128 = 3;
        v129 = 6;
      }
      else {
        if (v64 < 10) {
          v125 = 1;
          v127 = 1;
          v128 = 1;
          v129 = 5;
        }
        else {
          if (v64 < 17) {
            v125 = 1;
            v127 = 1;
Label1:
            random(0,3,v128);
            if ((v128 == v127 ||
                v128 == v125)) {
              goto(Label1);
            }
            v129 = 4;
          }
          else {
            if (v64 < 33) {
              v125 = 1;
Label2:
              random(0,3,v127);
              if (v127 == 1) {
                goto(Label2);
              }
              random(0,3,v128);
              v129 = 3;
            }
            else {
Label3:
              random(0,3,v125);
              if (v125 == 1) {
                goto(Label3);
              }
              random(0,3,v127);
Label4:
              random(0,3,v128);
              if (v127 == v125 &&
                  v128 == v127) {
                if (v128 == v127) {
                  goto(Label4);
                }
              }
              v129 = 2;
            }
          }
        }
      }
    }
  }
}
if (v129 != 8) {
  set(f126);
  v134 = 0;
  return();
}
return();

// Messages
DrD2k9
He/Him
Editor, Judge, Expert player (2214)
Joined: 8/21/2016
Posts: 1090
Location: US
I'm my assumption of v129 as result is corrent, it appears that v64 is set to a specific number after each spin depending on the v129 result. From Logic.115
if (v26 == 2 &&
    v20 == 0) {
  v245 = 18;
}
else {
  v245 = 16;
}
v246 = 13;
if (v129 == 1) {
  set(f123);
  set(f233);
  v64 = 0;
}
else {
  if (v129 == 2) {
    v64 = 0;
  }
  else {
    if (v129 == 7) {
      if (v123 == 1) {
        v64 = 20;
      }
      else {
        if (v123 == 2) {
          v64 = 40;
        }
        else {
          v64 = 60;
        }
      }
    }
    else {
      if (v129 == 6) {
        if (v123 == 1) {
          v64 = 10;
        }
        else {
          if (v123 == 2) {
            v64 = 20;
          }
          else {
            v64 = 30;
          }
        }
      }
      else {
        if (v129 == 5) {
          if (v123 == 1) {
            v64 = 5;
          }
          else {
            if (v123 == 2) {
              v64 = 10;
            }
            else {
              v64 = 15;
            }
          }
        }
        else {
          if (v129 == 4) {
            if (v123 == 1) {
              v64 = 3;
            }
            else {
              if (v123 == 2) {
                v64 = 6;
              }
              else {
                v64 = 9;
              }
            }
          }
          else {
            if (v129 == 3) {
              if (v123 == 1) {
                v64 = 1;
              }
              else {
                if (v123 == 2) {
                  v64 = 2;
                }
                else {
                  v64 = 3;
                }
              }
            }
          }
        }
      }
    }
  }
}
if (v26 == 2 &&
    v20 == 0) {
  display(18,13,"               ");
}
else {
  display(16,13,"               ");
}
if (v129 != 2 &&
    v129 != 1) {
  if (v26 == 2 &&
      v20 == 0) {
    display(18,13," You Win  $%v64 ");
  }
  else {
    display(16,13," You Win  $%v64 ");
  }
}
else {
  random(6,12,v247);
  display.v(v245,v246,v247);
}
v123 = 0;
v126 = 250;
v126 -= v124;
if (v124 <= 0) {
  drop("buckazoid(s)");
}
if (v126 <v64> 0 &&
    !has("buckazoid(s)")) {
  get("buckazoid(s)");
}
if (v26 == 2 &&
    v20 == 0) {
  display(20,13," You Have $%v124");
}
else {
  display(18,13," You Have $%v124");
}
reset(f134);
v129 = 8;
if (!isset(f123)) {
  accept.input();
}
reset(f95);
return();
return();
Also, v123 may be the variable for amount bet
DrD2k9
He/Him
Editor, Judge, Expert player (2214)
Joined: 8/21/2016
Posts: 1090
Location: US
Ok Last one of these. I think this relates to entering the slot machine. Here's Logic.113
if (isset(f5)) {
  load.view(91);
  load.view(93);
  load.view(99);
  load.sound(25);
  load.sound(26);
  load.sound(27);
  animate.obj(o1);
  set.view(o1,91);
  set.cel(o1,0);
  position(o1,43,83);
  stop.cycling(o1);
  animate.obj(o2);
  set.view(o2,91);
  set.cel(o2,0);
  position(o2,74,83);
  stop.cycling(o2);
  animate.obj(o3);
  set.view(o3,91);
  set.cel(o3,0);
  position(o3,105,83);
  stop.cycling(o3);
  animate.obj(o4);
  set.view(o4,93);
  set.cel(o4,0);
  position(o4,49,39);
  stop.cycling(o4);
  animate.obj(o5);
  set.view(o5,93);
  set.cel(o5,0);
  position(o5,80,39);
  stop.cycling(o5);
  animate.obj(o6);
  set.view(o6,93);
  set.cel(o6,0);
  position(o6,111,39);
  stop.cycling(o6);
  draw(o1);
  draw(o2);
  draw(o3);
  draw(o4);
  draw(o5);
  draw(o6);
  v54 = 3;
  v131 = 18;
  v132 = 13;
  return();
}
if (isset(f126) &&
    isset(f162)) {
  sound(25,f162);
}
if (isset(f124)) {
  reset(f231);
  if (v124 > 0) {
    reset(f124);
    v124 -= v123;
    if (v26 == 2 &&
        v20 == 0) {
      display(18,13,"               ");
      display(19,13,"               ");
      display(20,13,"               ");
      display(21,13,"               ");
      display(18,13," You Bet  $%v123");
      display(20,13," You Have $%v124");
    }
    else {
      display(16,13,"               ");
      display(17,13,"               ");
      display(18,13,"               ");
      display(19,13,"               ");
      display(16,13," You Bet  $%v123");
      display(18,13," You Have $%v124");
    }
    set.view(o1,91);
    set.view(o2,91);
    set.view(o3,91);
    start.cycling(o4);
    start.cycling(o5);
    start.cycling(o6);
    start.cycling(o1);
    start.cycling(o2);
    start.cycling(o3);
    random(10,23,v230);
    random(26,38,v231);
    random(42,53,v232);
    sound(25,f162);
  }
  else {
    if (v124 <= 0) {
      reset(f124);
      print("You're broke!  Hit the road, freeloader!");
      new.room(70);
    }
  }
}
v230--;
v231--;
v232--;
if (v230 == 1) {
  set.cel.v(o1,v125);
  stop.cycling(o1);
  stop.cycling(o4);
  set.cel(o4,0);
}
if (v231 == 1) {
  set.cel.v(o2,v127);
  stop.cycling(o2);
  stop.cycling(o5);
  set.cel(o5,0);
}
if (v232 == 1) {
  set(f230);
}
if (isset(f230)) {
  current.cel(o3,v233);
  if (v233 == v128) {
    reset(f230);
    set.cel.v(o3,v128);
    stop.cycling(o3);
    stop.cycling(o6);
    set.cel(o6,0);
    set(f231);
    stop.sound();
  }
}
if (isset(f231)) {
  if ((v129 == 7 ||
      v129 == 6 ||
      v129 == 5 ||
      v129 == 1)) {
    reset(f126);
    set.view(o1,99);
    set.view(o2,99);
    set.view(o3,99);
    set.loop.v(o1,v125);
    set.loop.v(o2,v127);
    set.loop.v(o3,v128);
    set.cel(o1,0);
    set.cel(o2,1);
    set.cel(o3,0);
    start.cycling(o1);
    start.cycling(o2);
    start.cycling(o3);
    set(f134);
  }
  else {
    if (v129 == 4) {
      reset(f126);
      set.view(o1,99);
      set.view(o2,99);
      set.loop.v(o1,v125);
      set.loop.v(o2,v127);
      set.cel(o1,0);
      set.cel(o2,1);
      start.cycling(o1);
      start.cycling(o2);
      set(f134);
    }
    else {
      if (v129 == 3) {
        reset(f126);
        set.view(o1,99);
        set.loop.v(o1,v125);
        set.cel(o1,0);
        start.cycling(o1);
        set(f134);
      }
      else {
        if (v129 == 1) {
          reset(f126);
          set.view(o1,99);
          set.view(o2,99);
          set.view(o3,99);
          set.loop.v(o1,v125);
          set.loop.v(o2,v127);
          set.loop.v(o3,v128);
          set.cel(o1,0);
          set.cel(o2,1);
          set.cel(o3,0);
          start.cycling(o1);
          start.cycling(o2);
          start.cycling(o3);
          set(f134);
        }
        else {
          reset(f126);
          set(f134);
        }
      }
    }
  }
  if (v129 != 2 &&
      v129 != 1) {
    sound(26,f162);
  }
  else {
    sound(27,f162);
  }
}
return();
I'm confident v123 is bet amount based on this logic tree.
DrD2k9
He/Him
Editor, Judge, Expert player (2214)
Joined: 8/21/2016
Posts: 1090
Location: US
Based on
if (isset(f231)) { 
  if ((v129 == 7 || 
      v129 == 6 || 
      v129 == 5 || 
      v129 == 1)) { 
    reset(f126); 
    set.view(o1,99); 
    set.view(o2,99); 
    set.view(o3,99); 
    set.loop.v(o1,v125); 
    set.loop.v(o2,v127); 
    set.loop.v(o3,v128); 
    set.cel(o1,0); 
    set.cel(o2,1); 
    set.cel(o3,0); 
    start.cycling(o1); 
    start.cycling(o2); 
    start.cycling(o3); 
    set(f134); 
from above, I'm confident v129 is the result. As a value of 1, 5, 6, or 7 results in cycling graphics objects (winning slot symbols).
Active player (378)
Joined: 9/25/2011
Posts: 652
v64 is the amount won:
    -- Big win, all diamonds (LOGIC.114)
    if (v64 == 4) {
      v125 = 2;
      v127 = 2;
      v128 = 2;
      v129 = 7;
    }

    -- Payout depends on bet (LOGIC.115)
    if (v129 == 7) {
      if (v123 == 1) {
        v64 = 20;
      }
      else {
        if (v123 == 2) {
          v64 = 40;
        }
        else {
          v64 = 60;
        }
      }
    }
DrD2k9
He/Him
Editor, Judge, Expert player (2214)
Joined: 8/21/2016
Posts: 1090
Location: US
c-square wrote:
v64 is the amount won:
    -- Big win, all diamonds (LOGIC.114)
    if (v64 == 4) {
      v125 = 2;
      v127 = 2;
      v128 = 2;
      v129 = 7;
    }

    -- Payout depends on bet (LOGIC.115)
    if (v129 == 7) {
      if (v123 == 1) {
        v64 = 20;
      }
      else {
        if (v123 == 2) {
          v64 = 40;
        }
        else {
          v64 = 60;
        }
      }
    }
Yea it appears so in Logic.115. In Logic.114 though it's set randomly...and the outcome determines v129 (win/lose result?). It must be used for multiple things. EDIT: Confirmed with cheat engine. v64 is visible as random number during spin, then changes to $ won when the last symbol locks. :END EDIT Anyway...I've done some memory searching using Cheat Engine and the v(n) variables line up in memory. i.e. v125 = 0A71B3D2 v124 = 0A71B3D1 v64 = 0A71B395 These memory addresses change when a save-state is loaded. I could not find pointer addresses.
Player (26)
Joined: 8/29/2011
Posts: 1206
Location: Amsterdam
c-square wrote:
Radient, when I try AGIHack, I get the following error:
This version of e:\Old Games\AGIHack\AGIHACK.EXE is not compatible with the version of Windows you're running. Check your computer's system information to see whether you need a x86 (32-bit) or x64 (64-bit) version of the program, and then contact the software publisher.
What version of Windows are you running it in? I'm using Windows 7.
Run it from Dosbox.
DrD2k9, I created a similar spreadsheet to list the numbers. I was hoping it'd cycle after a few thousand, but it looks like the RNG is complete and it doesn't cycle until all 65536 numbers have been used. <sigh>
I'm not surprised. If you have a decent mathematician on your game design team then he'll be implementing one of these.
Since we have no idea what the starting value is that's the best I think of to do.
The starting value is the amount of milliseconds since midnight.
If I'm reading it correctly, this instruction appears to set the random variable to a number from 79-80.
Yes, that is correct. Then it prints either message 79 or message 80, both of which are variants of "I don't understand this input". For our purpose, it only matters that it advances the random seed by one step. In fact, every call to random() regardless of parameters will advance it by one step.
Player (26)
Joined: 8/29/2011
Posts: 1206
Location: Amsterdam
DrD2k9 wrote:
I believe v64 is the random number; v125, v127, and v128 are the slot symbols; and v129 is the result. But I can't confirm those.
That is correct. v129 is the only one of the four that actually matters, the animation is window dressing. v64 is filled with the result from calling the random() function. v134 is used for an animation delay.
DrD2k9 wrote:
I'm my assumption of v129 as result is corrent, it appears that v64 is set to a specific number after each spin depending on the v129 result.
In logic 115, v64 is used for the payout, based on the earlier value of v129, and on v123 which is the amount of buckazoids you bet. Note that if you win nothing, random() isl called once more to pick a random 'you lose' message in v247. v26 and v20 determine where the text is displayed (using v246 and v245 as coordinates); this is not relevant to our purpose. Entering the slot screen calls random() three times, to pick the initial position of the wheels. Leaving (entering the bar again) calls random() once for the band, and once for the barkeeper's delay. Playing the slots calls random() only once; turns out the spinning wheels are just for show, the result is picked immediately by generating a random number from 1 to 100 inclusive. 1-2: 000 kills you 4: 222 pays 20x 3,5: 333 pays 10x 6-9: 111 pays 5x 10-16: 11X pays 3x, and calls random(0,3) until it gets a value for X other than 1 17-32: 1XY pays 1x, and calls random(0,3) until it gets a value for X other than 1, then calls it precisely once more for Y 33-100: XYZ pays nothing, and calls random(0,3) until it gets a value for X other than 1, then precisely once more for Y, than calls random(0,3) for Z until is different from X or Y. It is important to note that randomness does not increment unless the random() function is called, meaning that idling is not going to help you.
Player (26)
Joined: 8/29/2011
Posts: 1206
Location: Amsterdam
DrD2k9 wrote:
Ok Last one of these. I think this relates to entering the slot machine. Here's Logic.113
Yes, it sets up the animation and sound, notably calling random() three times to set the initial icon on each wheel.
DrD2k9 wrote:
from above, I'm confident v129 is the result. As a value of 1, 5, 6, or 7 results in cycling graphics objects (winning slot symbols).
Correct.
Player (26)
Joined: 8/29/2011
Posts: 1206
Location: Amsterdam
So how to approach this? If you start your emulator and it's set up to directly open this game, then the intial value of random_seed should always be the same. We should double-check this; but it's obvious that if this weren't the case, then the run would desync at the first instance in the game where randomness matters (e.g. the skimmer sequence). Aside from the slot machine, there's not a lot of places in the game where randomness actually matters to speedrunning. I'm pretty sure that the skimmer sequence is timed, and won't be any faster regardless of where exactly the rocks are. However, the first scene of the game (Arcada) and the last (Deltaur) have random encounters which could be manipulated away. Most importantly, of course, there's the slot machine. It is important that every call to random() advances the seed by one step. Furthermore, just delaying for a couple frames will not advance the seed. This makes manipulating it much more straightforward. Finally, advancing the seed is hex-friendly; meaning that if you'd get one extra call to random() in the first room, the seed will have been advanced by precisely one step in the last room too. I'm not sure if the rest of the run is hex-friendly though, please confirm? (this is not entirely true as in some instances a certain random() value may result in more random() calls, but it is usually true). The easy way to advance the seed, which can be done at any time, is typing N + enter or Y + enter. These are the shortest inputs that give a randomized message (all other one-letter inputs are either not recognized, which give a non-random message, or are ignored). Of course, this does pop up a text box, wasting a couple frames to get rid of it. (edit) importantly, this works WHILE playing the slot machine, meaning that if there's a triple-skull in the seed sequence you can skip it. Another way is that a number of rooms make a few random() calls when entered. For instance, entering the bar in Ulence Flats calls it twice, and 'entering' the slot machine calls it three more times. During the Arcada or Kerona sequences, you could advance the seed by swapping rooms a few times; I can compile a list if you like. A third is with saved games. The random seed is explicitly NOT stored in a saved game, so it's possible to go to one place that advances the seed by a lot, then restore to an earlier game and you'll have that game position with the new seed. Finally, and most importantly, JPC-RR has a parameter "Initial RTC time". Since the random seed is initialized as the amount of milliseconds since midnight, altering this parameter is an easy way to get a different pattern. I believe this is legit by the site rules, but we should probably check that.
Player (26)
Joined: 8/29/2011
Posts: 1206
Location: Amsterdam
c-square wrote:
DrD2k9, I created a similar spreadsheet to list the numbers.
Please upload it somewhere so we can all use the same one. I'm guessing it's in Excel?
Active player (378)
Joined: 9/25/2011
Posts: 652
Radiant wrote:
If you start your emulator and it's set up to directly open this game, then the intial value of random_seed should always be the same.
I agree. Unfortunately, since we don't know on what frame the game sets this value, we can't know the initial value.
The easy way to advance the seed, which can be done at any time, is typing N + enter or Y + enter. These are the shortest inputs that give a randomized message (all other one-letter inputs are either not recognized, which give a non-random message, or are ignored).
Great! Looks like that'll be the best way to do RNG manipulation here.
Finally, and most importantly, JPC-RR has a parameter "Initial RTC time". Since the random seed is initialized as the amount of milliseconds since midnight, altering this parameter is an easy way to get a different pattern. I believe this is legit by the site rules, but we should probably check that.
Since the game initializes the seed only once on startup, wouldn't this only be useful then? Changing this mid-game would have no effect on the seed. Radiant, would you check the lua code I posted to see if I missed anything? If we can find the memory address for the seed, then we can know every slot outcome coming up and how best to manipulate them.
DrD2k9
He/Him
Editor, Judge, Expert player (2214)
Joined: 8/21/2016
Posts: 1090
Location: US
Radiant wrote:
Finally, and most importantly, JPC-RR has a parameter "Initial RTC time". Since the random seed is initialized as the amount of milliseconds since midnight, altering this parameter is an easy way to get a different pattern. I believe this is legit by the site rules, but we should probably check that.
If we can figure out when the game first sets the seed, this may be beneficial to change. Radiant, do you know how quickly this is set? If we can even narrow down the frame region to even as many as 20 frames it may make it easier to find the starting 'ms from midnight' seed.
Radiant wrote:
Please upload it somewhere so we can all use the same one. I'm guessing it's in Excel?
Here The initial seed is probably not correct for when the game sets it; it's based off 1:46:00.00am Also, I'm not 100% sure the math is correct, but I believe it is.
c-square wrote:
Since the game initializes the seed only once on startup, wouldn't this only be useful then? Changing this mid-game would have no effect on the seed.
If we can figure it out when it's set, I'll redo the run from the beginning. It'd be worth it, if it makes RNG manipulation easier.
Radiant wrote:
So how to approach this?... The easy way to advance the seed, which can be done at any time, is typing N + enter or Y + enter. These are the shortest inputs that give a randomized message (all other one-letter inputs are either not recognized, which give a non-random message, or are ignored).
Could we use this information to isolate the random_seed? I don't have time to test it right now, but here's a testing possibility using a memory searching program : Stand in one spot in a room without any room based RNG. Search unknown value Use the Y or N text input to change the seed search changed value use 1 letter text input to NOT change the seed search equal value alternate these, or create a custom sequence of change/no-change searching appropriately to isolate the memory location. Once we have that, we have the seed number. Then we should be able to compare it to known variable memory locations and be able to find the seed value at any point in a game. Even if we don't know the initial seed to plug in the spreadsheet, if we can find any random seed with this method, we can plug it into the spreadsheet. If we could somehow find the pointer to the random memory address we could watch the memory frame by frame from emulator startup until the initial seed is set. Though this may become a moot point if we can obtain the seed value at any point using the above.
Player (26)
Joined: 8/29/2011
Posts: 1206
Location: Amsterdam
DrD2k9 wrote:
If we can figure out when the game first sets the seed, this may be beneficial to change. Radiant, do you know how quickly this is set? If we can even narrow down the frame region to even as many as 20 frames it may make it easier to find the starting 'ms from midnight' seed.
Oddly enough, it is not set when the game starts up, but the first time random() is called. Due to random encounters, this is certainly when you enter the first playable room (logic 2); I haven't checked the title sequence to see if it does anything random.
DrD2k9
He/Him
Editor, Judge, Expert player (2214)
Joined: 8/21/2016
Posts: 1090
Location: US
Radiant wrote:
Due to random encounters, this is certainly when you enter the first playable room (logic 2); I haven't checked the title sequence to see if it does anything random.
This should drastically reduce the potential range of frames where the initial is set. Possibly within 3-7 frames.
DrD2k9
He/Him
Editor, Judge, Expert player (2214)
Joined: 8/21/2016
Posts: 1090
Location: US
OK, I've successfully found a memory address for the random seed that follows the expected pattern (0x7C4D * agi_rand_seed + 1) of change when using the 'Y' or 'N' input. Unfortunately the random seed memory address isn't always the same distance from the variable memory address. :( Now I'm going to try and see if the return values follow as expected (because I'm dense and didn't check that at the same time as checking the basic sequence).
DrD2k9
He/Him
Editor, Judge, Expert player (2214)
Joined: 8/21/2016
Posts: 1090
Location: US
Radiant wrote:
...this is certainly when you enter the first playable room
I can confirm the address is written to once in this room, at least when restarting a game after death.
DrD2k9
He/Him
Editor, Judge, Expert player (2214)
Joined: 8/21/2016
Posts: 1090
Location: US
OK...more concrete info. Use this savestate and do the following using a memory search program (Cheat Engine is what I used). Let Roger enter the slot machine. Enter 'Y' 6 times search value 63453 enter 'Y' 1 more time search value 39290 This should yield the agi_rand_seed memory address of the emulator...not the internal memory address. You LUA smarter people may be able to use that info to find the internal memory address (which I'm guessing will be static internally).
Active player (378)
Joined: 9/25/2011
Posts: 652
Woo hoo! I think we've got it. The RNG memory address in JPC-rr is both 246039 and 1294615 (both store the same value). It's initially populated at JPC-rr clock time 2954901700, which is almost 2955 ms into the game. The initial value is 46218 (using the save file you sent me, DrD2k9). There are 586 random calls from the start of the game until you first get to the slot machine. Based on all this, we should be able to figure out a lot! I'll put more work into this tonight.
Post subject: Re: Space Quest 1
DrD2k9
He/Him
Editor, Judge, Expert player (2214)
Joined: 8/21/2016
Posts: 1090
Location: US
c-square wrote:
This is a thread to help DrD2k9 figure out the slot machine, and any other time savings in her/his (?) SQ1 run.
His
Post subject: Re: Space Quest 1
Active player (378)
Joined: 9/25/2011
Posts: 652
DrD2k9 wrote:
c-square wrote:
This is a thread to help DrD2k9 figure out the slot machine, and any other time savings in her/his (?) SQ1 run.
His
Fixed! :)
Active player (378)
Joined: 9/25/2011
Posts: 652
What's the minimum cash you need to be able to buy the ship and the droid?
1 2
6 7