Sega Randomizer

From TetrisWiki
Jump to navigation Jump to search

Sega's original 1988 System 16 Tetris randomizer works as follows:

  1. Upon system startup, the seed is loaded from NVRAM. The first game started will use the loaded seed.
  2. A 1000 piece sequence is generated upon game start, with the seed changing for each piece. Once the sequence is generated, the seed remains the same during a game.
  3. The 1000 piece sequence restarts every 1000 pieces.
  4. Upon gameover, two choices can be made that affect the seed for the next game:
    1. Hit start and skip to the high score screen, before the monkey animation is shown. The seed after the 1000th piece was generated will be used next game.
    2. Wait for the monkey animation to be shown. The randomizer will be run to select a monkey animation, changing the seed for the next game; think of it as if a 1001st piece was generated.

Erasing NVRAM resets the seed to zero, and the randomizer replaces a zero seed with a built-in constant. Thus, the power-on pattern is observed, since the same default seed is always used in that case.

C code of the randomizer:

#include <stdint.h>
#include <stdio.h>

// The game simply calls rand() once at the gameover screen to select the monkey animation, if the player waits for the display of the animation.

#define DEFAULT_SEED 0x2A6D365A
#define HI(lw) ((lw) & 0xFFFF0000)
#define LO(lw) ((lw) & 0xFFFF)
#define LW(lw) ((lw) << 16)
#define RW(lw) ((lw) >> 16)
uint32_t rand(uint32_t *seedp) {
	uint32_t temp, oldseed;

	temp = (*seedp == 0u) ? DEFAULT_SEED : *seedp;
	oldseed = temp;
	temp *= 41u;
	*seedp = temp + LW(temp);
	return (LO(temp) + RW(temp)) | HI(oldseed);
}

void newsequence(uint8_t *seq, size_t len, uint32_t *seedp) {
	for (size_t i = 0u; i < len; i++) {
		seq[i] = (rand(seedp) & 0x3F) % 7;
	}
}

void printsequence(uint8_t *seq, size_t len) {
	for (size_t i = 0u; i < len; i++) {
		char c;

		switch (seq[i]) {
			case 0: c = 'I'; break;
			case 1: c = 'Z'; break;
			case 2: c = 'S'; break;
			case 3: c = 'O'; break;
			case 4: c = 'T'; break;
			case 5: c = 'L'; break;
			case 6: c = 'J'; break;
			default: c = '?'; break;
		}
		putchar(c);
	}
	putchar('\n');
}

TODO: The randomizers of the other versions.