Quickie – Neuromancer

I’ve been working on a longer, reverse-engineering piece about Neuromancer, but couldn’t get it finished in time to post this week. In it’s place, a simple javascript implementation of the game’s code wheel.

If you’re inclined to dig into the details of the implementation, you’ll find a fairly faithful re-creation of the game’s logic – 3 bit BCD and all. Here’s a link to the source, since WordPress likes to mangle code, as reproduced below.

// Application object class
function App() {
	// Window shift LUT
	this.lut0 = [0, 0, 1, 1, 2, 3, 3, 4, 5, 5, 6, 6, 7, 8, 9, 9];

	// Window rank LUT
	this.lut1 = [2, 5, 0, 7, 3, 1, 6, 4, 0, 7, 2, 4, 6, 1, 3, 5];

	// BCD data LUT (3-bit, 6-digit, MSD has only 1 bit)
	this.lut2 = [	39889, 9133, 38839, 25052, 45749, 26196, 58580, 30601,
					25260, 44664, 28260, 13310, 13304, 41983, 40698, 5114,
					28243, 15472, 5654, 54494, 54783, 16599, 2507, 21277,
					56979, 23681, 22615, 39146, 44323, 12716, 6487, 46143,
					18634, 29386, 18641, 32153, 25443, 28682, 14840, 18103,
					8960, 27208, 25555, 21430, 12984, 19449, 17103, 25390,
					29334, 25495, 726, 25261, 3826, 25509, 15434, 20567,
					31149, 28319, 14829, 10169, 29652, 134, 9466, 17468,
					275, 2640, 3150, 1617, 127, 2895, 3655, 2114, 120, 2638,
					3184, 2677, 15, 555, 2835, 1659, 3156, 735, 2240, 58,
					2128, 718, 1921, 1767, 1023, 1496, 2263, 451, 3104, 2664,
					3186, 1148, 475, 398, 119, 139, 330, 448, 172, 15, 347,
					443, 219, 284, 192, 264, 44, 203, 67, 37, 158, 460, 20,
					276, 315, 396, 442, 209, 58, 327, 469, 377, 280, 509];

	// Fill in the user interface
	function Populate(s, a)
	{
		while (s.firstChild)
		{
			s.removeChild(s.firstChild);
		}

		var i, o;
		for (i = 0; i < a.length; i++)
		{
			o = s.appendChild(document.createElement('OPTION'));
			o.appendChild(document.createTextNode(a[i]));
			o.value = i;
		}
	}

	var outer = [	'Chatsubo', 'Cyberspace', 'Gemeinschaft', 'Crazy Edo',
					'Microsofts', 'Cheap Hotel', 'Julius Deane', 'Donut World',
					'Lawbot', 'database', 'Shiva', 'Freeside', 'softwarez',
					'Matrix', 'Matt Shaw', 'Night City News'];

	var inner = [	'Ratz', 'Holografix', 'Larry Moe', 'PAX',
					'Skill Chips', "Shin's Pawn", 'Gentleman Loser', 'Maas Biolabs',
					'Justice Booth', 'Cyberdeck', 'Comlink', 'Icebreaker',
					'ROM construct', 'Cowboy', 'Emperor Norton', 'Cyberjack'];

	var names = [	'Zion Cluster', 'Chiba City', 'Asano Computing', 'Hitachi Biotech',
					'Cryptology', 'Space colony', 'Holy Joystick', 'Bank of Berne',
					'Spacedock', 'Ono-Sendai', 'Marcus Garvey', 'Bank of Zurich',
					'Compu-Judge', 'flatline', 'AI', 'Fuji Electric'];

	Populate(document.getElementById('outer'), outer);
	Populate(document.getElementById('inner'), inner);
	Populate(document.getElementById('window'), names);

	this.UpdateCode();

	// Install hooks
	var hook = this.MakeControllerHook();
	document.getElementById('outer').onchange = hook;
	document.getElementById('inner').onchange = hook;
	document.getElementById('window').onchange = hook;
};

// Application object methods
App.prototype.MakeControllerHook = function () {
	var o = this;
	return function () { o.UpdateCode(); };
};

App.prototype.UpdateCode = function () {
	var outer = document.getElementById('outer').selectedIndex;
	var inner = document.getElementById('inner').selectedIndex;
	var windex = document.getElementById('window').selectedIndex;

	var index = ((this.lut0[windex] + outer - inner) & 0xf) + (this.lut1[windex] << 4);
	var bcd = this.lut2[index];

	function Decode(shift) { return String.fromCharCode(((bcd>>shift)&0x7) + 0x30); }
	var s = Decode(15) + Decode(12) + Decode(9) + Decode(6) + Decode(3) + Decode(0);
	var l = 3 + ((7-this.lut1[windex])>>1);
	document.getElementById('code').value = s.slice(6-l);
};

// Global application object
var app = new App();
Share and Enjoy:
  • Twitter
  • Facebook
  • Digg
  • Reddit
  • HackerNews
  • del.icio.us
  • Google Bookmarks
  • Slashdot
This entry was posted in Reverse Engineering. Bookmark the permalink.

Comments are closed.