<!DOCTYPE html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Wonder Boy III: The Dragon's Trap: The Password Generator</title>
<link id="favicon" rel="icon" type="image/gif" href="data:image/gif;base64,R0lGODlhEAAQAMIGAP+qVeTKAf9VAAAAAP//AFVVAP///////yH5BAEAAAcALAAAAAAQABAAAAM/eLrcPXA4Bc8QAAjpRrmZIEaVRWBZqgLScK4w66JxCL2rqLe4OpYz2Igxo2mGi6Ju9zgtmcTPc9NpkTiTrCMBADs="/>
<script type="text/javascript">
/* This program is free software. It comes without any warranty, to
 * the extent permitted by applicable law. You can redistribute it
 * and/or modify it under the terms of the Do What The Fuck You Want
 * To Public License, Version 2, as published by Sam Hocevar. See
 * http://sam.zoy.org/wtfpl/COPYING for more details. */

/* *****************************************************************************
JavaScript Wonder Boy III Password Generator [0.0.2]                  by Splarka
********************************************************************************

Description:
This is a password generator for "Wonder Boy III: The Dragon's Trap" (released
as "Monster World II: Dragon no Wana" in Japan) for the Sega Master System and
Sega Game Gear.

Notes:
* Yes, this uses string manipulation. Easier than bitwise operations! Especially
with 32 bit (or worse) limitations in most browsers' JavaScript.

================================================================================
Password Specs - Wonder Boy III: The Dragon's Trap                    by Splarka
================================================================================
The password format uses a 70 bit password made from 14 alphanumeric characters.
The alphabet is: "0123456789ABCDEFGHJKLMNPRTUVWXYZ". Each character represents a
5 bit number, and the alphabet is linear, so 0 is 0b00000 and Z is 0b11111. The
last 7 bits form a checksum, and invalid checksums are not accepted. The first
63 bits form the options in the game. There are also 4 base templates which the
passwords are built on, to obfuscate them.

[bits 01-27]
The first 3 sets of 9 bits store the acquired equipment: swords, shields, and
armor. The equipped status is not stored, and the game apparently chooses the
best equipment for your current form on continue. The bits indicate the
position of the equipment in your inventory linearly, except the least powerful
(default) equipment, which comes second in the inventory and is not included.
The memory location in the game for these is CF20-CF3D (single bit, +80h for
"equipped").

[bits 28-32]
The next 5 bits indicate spells. The manual states that spells are not included
on password continue, but there is a single bit for each of the five types, and
when set this bit gives you a pittance of spells. The bit is set upon password
generation in the game if you have at least this many spells to get any. For
Fireballs, Tornados and Arrows, this number is 5, for Boomerangs, it is 1, for
Thunder it is 3. Memory location CF3E-CF42 (single bit, +80h for "equipped").

[bit 33]
If you have one key, this bit is set, and you get it back. Memory location CF49
(single bit, +80h for "equipped").

[bits 34-37]
These bits indicate the opened status of the green doors in the game. There are
four bits, but I have only been able to see the flag changed for three of them:
The Tower, the Meka Dragon's Castle (after you return), and the Sky Castle
entrance. There is a fourth green door (when you originally leave the Meka
Dragon's Castle this is a different door than when you return) but it cannot
be opened with a key. Memory location CF5C (stored as 4 bits, the same order as
the password).

[bits 38-39]
These bits indicate the password template. See below.

[bits 40-42]
These indicate how many extra heart containers you have found (0-7, binary num).
You cannot get heart containers out of sequence, nor can you get more than 8
total, so the heart containers you have already acquired is derived from this
number. Memory location (CF54), stored as one byte, valid values are: 0D 1A 27
34 41 4E 5B 68.

[bits 43-49]
This is a binary 7 bit integer for how many Stones you have found. It is
interesting to note that you can artifically inflate this number above the 99
possible in the game, and it will carry over into passwords generated later.
Your charm score is also proportionally increased, allowing you to buy things
out of sequence. The max value in the password system is 127 (all 7 bits).
Memory location CF48 (00-7F).

[bits 50-57]
This stores an estimate of your acquired gold. As the gold value can range from
0 to 999999, this would normally take 20 bits, probably excessive. The formula
for generating the estimate (rounded down, so you almost always lose gold) seems
to be (with the sub-bits forming two 4-bit binary integers):
  2^[bits 50-53] * 2 * [bits 54-57]
Note that if none of bits 54-57 are set, the value is zero. There is about 47%
overlap with this formula, and using some passwords will give you different
generated results in-game even if the number stays the same. The gold amount
is stored in memory at CF55-CF5A as 6 bytes, each byte holds a value (of
ascending significance) from 00-09, indicating the decimal value.

[bits 58-60]
This is a 3 bit binary number indicating your current form. The forms are:
  00 Hu-Man
  01 Lizard-Man
  02 Mouse-Man
  03 Piranha-Man
  04 Lion-Man
  05 Hawk-Man
  06 *glitch
  07 *glitch
The last two values will highly corrupt the game, pointing to graphics outside
the normal range. The game attempts to start, but is unplayable (though the
pause menu is accessable). It is interesting that passwords can be entered with
no error checking for this. Memory location is C24F (00-07).

[bits 61-63]
This is a 3 bit binary number indicating both the available forms you can change
into, as well as the dragons you have defeated. The values are:
  00 up to Lizard-Man
  01 up to Mouse-Man
  02 up to Piranha-Man
  03 up to Lion-Man
  04 up to Hawk-Man
  05 up to Hawk-Man *
  06 up to Hawk-Man *
  07 up to Hawk-Man *
The last three values will give odd behavior. Doors will be silent, and going
through a "Return" door will make you completely invisible, and door animations
will stop. Yet another interesting thing that the password system allows without
error checking. Memory location is CF5B (00-07). Note that if you get 99 Stones
and access the shortcut doors to the Dragons, this value is reset appropriately.

[bits 64-70]
These bits form the checksum.

Checksum Generation:
The game algorithm takes the available options and combines them into the first
63 bits of the password. The checksum is calculated before the templates are
applied, but includes the bits which determine the template. The 63 bits are
padded with a zero on the left and divided evenly into 8 bytes. Each byte is
then divided by two and rounded down (right shifted 1) and added to a sum. This
sum is then trimmed to the rightmost 7 bits (ANDed with 7Fh), and this value is
the checksum.

Password Templates:
Passwords are obfuscated with a set of 4 base templates, which do not factor
into the checksum (which is only applied to the changes), and randomly seem to
be chosen each time you generate a password at the church. These templates are
XORed against the password before the CRC is applied, but after it has been
calculated. The base password templates seem to be (as set by bits 37-38):
  010100110000011011100001110100000000000000000001000110111000000  [00]
  000011110011111001001001010101000000000000000010011010011100010  [01]
  101100111110011110100000101110000000000000000000111000011100010  [10]
  111000000101111001010100000001000000000000000000000110001110010  [11]
These were derived by unsetting all possible password-indicated options, and
then asking the game for a password, which gave:
  AC3E 3L0 004D R00  [00]
  1WZ4 JM0 209L W80  [01]
  NFKU 1E0 403G W81  [10]
  W1F5 810 600C E81  [11]
The checksum was stripped, and bits 37-38 were zeroed (as those bits do apply
to the checksum, oddly).

Encoding:
A simple chain to encode a password is:
* Combine the 63 bits.
* Calculate the checksum.
* XOR against the indicated template.
* Append the checksum.
* Divide into 5 bit integers (n) and select the (n)th alphanumeric character
from the available alphabet: "0123456789ABCDEFGHJKLMNPRTUVWXYZ".

Decoding:
* Replace each alphanumeric character with its 5 bit location in the alphabet.
* Combine these, strip the last 7 bits.
* XOR it against the indicated template, based on bits 37-38.

Password Weirdness:
* The password "WE5T 0NE 0000 000" is not a valid password, but a hard-coded
alias to "MKWH WBZ TY3J 0GP".
* Life, Revival Potions, and opened treasure chests are not stored in the
password system. You do, however, get some money for Revival Potions when you
generate a password. Equipped status is also not saved, the game seems to choose
the best equipment for your form each continue.
* Where is the fourth green door!
* As noted above, Stones, forms, available forms, and opened green doors can be
set via the password system to values not possible in the game, sometimes with
odd side effects.
* The gold estimation formula is very inefficient and has a lot of overlap.
* Some penultimate valid passwords:
  0000 000 0000 017
  ZZZZ ZZW ZZZZ ZZW
  ZZZZ ZZZ ZZZZ ZWL

***************************************************************************** */
var wb3alpha = '0123456789ABCDEFGHJKLMNPRTUVWXYZ';
var wb3templates = {
  '00':'010100110000011011100001110100000000000000000001000110111000000', //AC3E 3L0 004D R00
  '01':'000011110011111001001001010101000000000000000010011010011100010', //1WZ4 JM0 209L W80
  '10':'101100111110011110100000101110000000000000000000111000011100010', //NFKU 1E0 403G W81
  '11':'111000000101111001010100000001000000000000000000000110001110010'  //W1F5 810 600C E81
};
var wb3selects = [
  {'id':'wb3-heart','bit':40,'len':3},
  {'id':'wb3-stone','bit':43,'len':7},
  {'id':'wb3-gold','bit':50,'len':8},
  {'id':'wb3-form','bit':58,'len':3},
  {'id':'wb3-available','bit':61,'len':3}
];


function binpad(str,pad) {
  while(str.length < pad) str = '0' + str
  return str;
}

function wb3decode(code) {
  var bin = '';
  code = code.substring(0,14).toUpperCase().replace(/ /ig,'');
  if(code.length != 14 || code.replace(/[0-9A-HJ-NPRT-Z]/g,'') != '') return false
  for(var i=0;i<code.length;i++) {
    bin += '' + binpad(wb3alpha.indexOf(code[i]).toString(2),5);
  }
  return bin;
}

function wb3encode(bin) {
  if(bin.length != 70) return false
  var code = '';
  for(var i=0;i<14;i++) {
    var nibb = wb3alpha[parseInt(bin.substr(i*5,5),2)];
    code += nibb;
    if(i == 3 || i == 6 || i == 10) code += ' '
  }
  return code;
}

function wb3checksum(bits) {
  bits = '0' + bits;
  var bytes = [];
  for(var i=0;i<8;i++) bytes.push(bits.substr(i*8,8))
  var total = 0;
  for(var i=0;i<8;i++) {
    var num = parseInt(bytes[i],2);
    num = Math.floor(num / 2);
    total += num;
  }
  while(total > 127) total = total - 128
  var cs = binpad(total.toString(2),7);
  return cs;
}

function stringXOR(a,b) {
  var xor = '';
  for(var i=0;i<a.length;i++) xor += (a[i] == b[i]) ? '0' : '1'
  return xor;
}

function wb3formClick(e) {
  var e = window.event || e;
  var target = e.target || e.srcElement;
  if(target.tagName.toLowerCase() != 'input' || !target.type || target.type != 'checkbox') return
  wb3updateForm();
}

function wb3pwchange() {
  var pw = document.getElementById('wb3-password').value;
  pw = pw.replace(/[^0-9A-HJ-NPRT-Z]/ig,'');
  while(pw.length < 14) pw += '0'
  var code = wb3decode(pw);
  if(!code) return false
  var base = wb3templates[code.substr(37,2)];
  var binary = stringXOR(code.substr(0,63),base);
  for(var i=1;i<64;i++) {
    var chk = document.getElementById('wb3-bit-' + i);
    chk.checked = (binary.substr(i-1,1) == '1') ? 'checked' : false;
  }
  wb3updateForm(); //also fixes checksum in typed passwords
}

function wb3updateForm() {
  var code = document.getElementById('wb3-password');
  var binary = '';
  for(var i=1;i<64;i++) {
    var bit = (document.getElementById('wb3-bit-' + i).checked) ? 1 : 0;
    binary += bit;
  }
  var base = wb3templates[binary.substr(37,2)];
  var cs = wb3checksum(binary);
  var xorcsbin = stringXOR(binary,base) + cs;
  code.value = wb3encode(xorcsbin);

  for(var i=0;i<wb3selects.length;i++) {
    var sel = document.getElementById(wb3selects[i].id);
    var index = 0;
    for(var k=0;k<wb3selects[i].len;k++) {
      var chk = document.getElementById('wb3-bit-' + (k+wb3selects[i].bit));
      if(chk.checked) index += Math.pow(2,wb3selects[i].len - k - 1);
    }
    sel.selectedIndex = index;
  }
}

function wb3selectChanged() {
  for(var i=0;i<wb3selects.length;i++) {
    var sel = document.getElementById(wb3selects[i].id);
    var selbin = sel[sel.selectedIndex].value;
    for(var k=0;k<wb3selects[i].len;k++) {
      var chk = document.getElementById('wb3-bit-' + (k + wb3selects[i].bit));
      chk.checked = (selbin.substr(k,1) == '1') ? 'checked' : false;
    }
  }
  wb3updateForm();
}

function wb3init() {
  wb3updateForm();
  var forms = ['Hu-Man','Lizard-Man','Mouse-Man','Piranha-Man','Lion-Man','Hawk-Man','freeze game *','freeze game *'];
  var available = ['Lizard-Man','Mouse-Man','Piranha-Man','Lion-Man','Hawk-Man','silent doors *','silent doors *','silent doors *'];
  for(var i=0;i<wb3selects.length;i++) {
    var sel = document.getElementById(wb3selects[i].id);
    var len = wb3selects[i].len;
    for(var k=0;k<Math.pow(2,len);k++) {
    var val = '';
      switch(i) {
        case 0: case 1: val = k; break;
        case 2: val = Math.pow(2,Math.floor(k / 16)) * 2 * (k % 16); break;
        case 3: val = k + ' ' + forms[k]; break;
        case 4: val = k + ' ' + available[k]; break;
      }
      insertOption(sel,val,binpad(k.toString(2),len));
    }
  }
  wb3updateForm();

  function insertOption(parent,text,val) {
    var op = document.createElement('option');
    op.setAttribute('value',val);
    op.appendChild(document.createTextNode(text));
    parent.appendChild(op);
    op.appendChild(document.createTextNode('\n'));
  }
}

function wb3randomize() {
  for(var i=1;i<64;i++) {
    var cb = document.getElementById('wb3-bit-' + i);
    cb.checked = (Math.floor(Math.random() * 2) == 1) ? 'checked' : false;
  }
  wb3updateForm();
}

</script>
<style type="text/css">
#wb3-password {font-family:monospace;font-size:130%;margin-bottom:1em;}
.wb3ops {float:left;margin:.25em;}
.wb3checks {float:left;white-space:nowrap;font-size:70%;margin:.25em;font-family:arial;}
.wb3selects {text-align:right;}
.tiny {font-size:70%;}
.clear {clear:both;}
</style>
</head><body>

<form action="javascript:void(0);" onclick="wb3formClick(event);">
<div class="wb3ops">
<input id="wb3-password" type="text" size="18" maxlength="17" onchange="wb3pwchange()" onblur="wb3pwchange()"/><br/>
<div class="wb3selects">
Extra Heart Containers: <select id="wb3-heart" onchange="wb3selectChanged();"></select><br/>
Stones: <select id="wb3-stone" onchange="wb3selectChanged();"></select><br/>
Gold: <select id="wb3-gold" onchange="wb3selectChanged();"></select><br/>
Form: <select id="wb3-form" onchange="wb3selectChanged();"></select><br/>
Available: <select id="wb3-available" onchange="wb3selectChanged();"></select><br/>
</div>
<input type="button" value="random" onclick="wb3randomize();"/><br/>
</div>
<div class="wb3checks">
<input type="checkbox" id="wb3-bit-1"/><label for="wb3-bit-1">Legendary Sword</label><br/>
<input type="checkbox" id="wb3-bit-2"/><label for="wb3-bit-2">Mithril Sword</label><br/>
<input type="checkbox" id="wb3-bit-3"/><label for="wb3-bit-3">Shogun Blade</label><br/>
<input type="checkbox" id="wb3-bit-4"/><label for="wb3-bit-4">Crystal Sword</label><br/>
<input type="checkbox" id="wb3-bit-5"/><label for="wb3-bit-5">Thunder Saber</label><br/>
<input type="checkbox" id="wb3-bit-6"/><label for="wb3-bit-6">Magical Saber</label><br/>
<input type="checkbox" id="wb3-bit-7"/><label for="wb3-bit-7">Lucky Sword</label><br/>
<input type="checkbox" id="wb3-bit-8"/><label for="wb3-bit-8">Muramasa Blade</label><br/>
<input type="checkbox" id="wb3-bit-9"/><label for="wb3-bit-9">Tasmanian Sword</label><br/>
<input type="checkbox" id="wb3-bit-10"/><label for="wb3-bit-10">Legendary Shield</label><br/>
<input type="checkbox" id="wb3-bit-11"/><label for="wb3-bit-11">Mithril Shield</label><br/>
<input type="checkbox" id="wb3-bit-12"/><label for="wb3-bit-12">Shogun Shield</label><br/>
<input type="checkbox" id="wb3-bit-13"/><label for="wb3-bit-13">Crystal Shield</label><br/>
</div>
<div class="wb3checks">
<input type="checkbox" id="wb3-bit-14"/><label for="wb3-bit-14">Knight Shield</label><br/>
<input type="checkbox" id="wb3-bit-15"/><label for="wb3-bit-15">Dancing Shield</label><br/>
<input type="checkbox" id="wb3-bit-16"/><label for="wb3-bit-16">Aqua Shield</label><br/>
<input type="checkbox" id="wb3-bit-17"/><label for="wb3-bit-17">Master Shield</label><br/>
<input type="checkbox" id="wb3-bit-18"/><label for="wb3-bit-18">Heavenly Shield</label><br/>
<input type="checkbox" id="wb3-bit-19"/><label for="wb3-bit-19">Legendary Armor</label><br/>
<input type="checkbox" id="wb3-bit-20"/><label for="wb3-bit-20">Mithril Armor</label><br/>
<input type="checkbox" id="wb3-bit-21"/><label for="wb3-bit-21">Shogun Lamellar</label><br/>
<input type="checkbox" id="wb3-bit-22"/><label for="wb3-bit-22">Crystal Armor</label><br/>
<input type="checkbox" id="wb3-bit-23"/><label for="wb3-bit-23">Goblin Mail</label><br/>
<input type="checkbox" id="wb3-bit-24"/><label for="wb3-bit-24">Samurai Armor</label><br/>
<input type="checkbox" id="wb3-bit-25"/><label for="wb3-bit-25">Dragon Mail</label><br/>
<input type="checkbox" id="wb3-bit-26"/><label for="wb3-bit-26">Prince Armor</label><br/>
</div>
<div class="wb3checks">
<input type="checkbox" id="wb3-bit-27"/><label for="wb3-bit-27">Hades Armor</label><br/>
<input type="checkbox" id="wb3-bit-28"/><label for="wb3-bit-28">5 Fireballs</label><br/>
<input type="checkbox" id="wb3-bit-29"/><label for="wb3-bit-29">5 Tornados</label><br/>
<input type="checkbox" id="wb3-bit-30"/><label for="wb3-bit-30">5 Arrows</label><br/>
<input type="checkbox" id="wb3-bit-31"/><label for="wb3-bit-31">1 Boomerang</label><br/>
<input type="checkbox" id="wb3-bit-32"/><label for="wb3-bit-32">3 Thunders</label><br/>
<input type="checkbox" id="wb3-bit-33"/><label for="wb3-bit-33">1 Key</label><br/>
<input type="checkbox" id="wb3-bit-34"/><label for="wb3-bit-34">Green door, ?????</label><br/>
<input type="checkbox" id="wb3-bit-35"/><label for="wb3-bit-35">Green door, Castle</label><br/>
<input type="checkbox" id="wb3-bit-36"/><label for="wb3-bit-36">Green door, Sky</label><br/>
<input type="checkbox" id="wb3-bit-37"/><label for="wb3-bit-37">Green door, Tower</label><br/>
<input type="checkbox" id="wb3-bit-38"/><label for="wb3-bit-38">Obfuscation bit 1</label><br/>
<input type="checkbox" id="wb3-bit-39"/><label for="wb3-bit-39">Obfuscation bit 2</label><br/>
</div>
<div class="wb3checks">
<input type="checkbox" id="wb3-bit-40"/><label for="wb3-bit-40">+4 Heart Containers</label><br/>
<input type="checkbox" id="wb3-bit-41"/><label for="wb3-bit-41">+2 Heart Containers</label><br/>
<input type="checkbox" id="wb3-bit-42"/><label for="wb3-bit-42">+1 Heart Containers</label><br/>
<input type="checkbox" id="wb3-bit-43"/><label for="wb3-bit-43">+64 Stones</label><br/>
<input type="checkbox" id="wb3-bit-44"/><label for="wb3-bit-44">+32 Stones</label><br/>
<input type="checkbox" id="wb3-bit-45"/><label for="wb3-bit-45">+16 Stones</label><br/>
<input type="checkbox" id="wb3-bit-46"/><label for="wb3-bit-46">+8 Stones</label><br/>
<input type="checkbox" id="wb3-bit-47"/><label for="wb3-bit-47">+4 Stones</label><br/>
<input type="checkbox" id="wb3-bit-48"/><label for="wb3-bit-48">+2 Stones</label><br/>
<input type="checkbox" id="wb3-bit-49"/><label for="wb3-bit-49">+1 Stones</label><br/>
<input type="checkbox" id="wb3-bit-50"/><label for="wb3-bit-50">Gold [bit 8]</label><br/>
<input type="checkbox" id="wb3-bit-51"/><label for="wb3-bit-51">Gold [bit 7]</label><br/>
<input type="checkbox" id="wb3-bit-52"/><label for="wb3-bit-52">Gold [bit 6]</label><br/>
</div>
<div class="wb3checks">
<input type="checkbox" id="wb3-bit-53"/><label for="wb3-bit-53">Gold [bit 5]</label><br/>
<input type="checkbox" id="wb3-bit-54"/><label for="wb3-bit-54">Gold [bit 4]</label><br/>
<input type="checkbox" id="wb3-bit-55"/><label for="wb3-bit-55">Gold [bit 3]</label><br/>
<input type="checkbox" id="wb3-bit-56"/><label for="wb3-bit-56">Gold [bit 2]</label><br/>
<input type="checkbox" id="wb3-bit-57"/><label for="wb3-bit-57">Gold [bit 1]</label><br/>
<input type="checkbox" id="wb3-bit-58"/><label for="wb3-bit-58">Current Form +4</label><br/>
<input type="checkbox" id="wb3-bit-59"/><label for="wb3-bit-59">Current Form +2</label><br/>
<input type="checkbox" id="wb3-bit-60"/><label for="wb3-bit-60">Current Form +1</label><br/>
<input type="checkbox" id="wb3-bit-61"/><label for="wb3-bit-61">Available Form +4</label><br/>
<input type="checkbox" id="wb3-bit-62"/><label for="wb3-bit-62">Available Form +2</label><br/>
<input type="checkbox" id="wb3-bit-63"/><label for="wb3-bit-63">Available Form +1</label><br/>
</div>
<br class="clear"/>
* The password "WE5T 0NE 0000 000" is not a valid password, but a hard-coded alias to "MKWH WBZ TY3J 0GP".<br/>
* I have no idea what the first "Green Door" unlocks. It doesn't seem to be used.<br/>
* If you choose "silent doors *" from "Available", doors make no sound, and if you use a "Return" door, your sprite becomes invisible.<br/>
* If you choose "freeze game *", the game graphics become glitched and you can't move.<br/>
* You can set 127 Stones just fine. Yes the money formula sucks, you need at least one low bit (1-4) set or it is zero.<br/>
* The "obfuscation" bits just determine the XOR template, which the game gives you semirandomly.
</form>

<script type="text/javascript">wb3init();</script></body></html>