var debug=window.location.search.indexOf("debug")>0 | window.location.hash.indexOf("debug")>0;
var count=window.location.search.indexOf("count")>0;

// common notes
var WithR   ="~With &reg;",
    NoR     ="~No &reg;",
    NoLimits="~Now, There are no limits.&reg;",
    SM      ="~Now, There are no limits.&#x2120;",
    Reissue ="~Reissue",
    MC      ="~&#x540d;&#x4f5c;&#x30b3;&#x30ec;&#x30af;&#x30b7;&#x30e7;&#x30f3; (Meisaku Collection)";

var NumColumns,NumCellsDone,ImgRow,NumGames,NumGamesNoImage,NumImgs,TotalImgSize,TotalImgPixels,imgpath;

var BasePath='/scans/'; // Path of scans page base
var SystemPaths=new Array('sms','gg','sgsc'),
    SystemNames=new Array('Master System','Game Gear','SG-1000/SC-3000/SF-7000/OMV'),
    SystemNoEntryPages=new Array('','','IX');
    CurrentSystem='',CurrentSystemName='',
    Index='';

var Countries=new Array(
  'eu','Europe',
  'us','United States',
  'ue','Europe & United States',
  'br','Brazil',
  'jp','Japan',
  'ca','Canada',
  'fr','France',
  'au','Australia',
  'nz','New Zealand',
  'kr','Korea',
  'it','Italy',
  'uk','UK',
  'hk','Hong Kong',
  'pt','Portugal',
  'de','Germany',
  'es','Spain',
  'jue','Japan, US and Europe'
);

function getCountryText(country)
{
  for(var i=0;i<Countries.length;i+=2)
  {
    if(country==Countries[i])
    {
      return Countries[i+1];
    }
  }
  return '';
}

// Cell size settings
var cellwidth=193,linewidth=1;

// OverLib settings
var ol_fgcolor='#ffffff',
    ol_bgcolor='#000000',
    ol_border=linewidth,
    ol_status='Click to open the full-size image; hover the mouse to see its properties',
    ol_delay=100,
    ol_width=cellwidth+linewidth*2,
    ol_textsize="8pt",
    ol_captionsize="8pt",
    ol_shadow=1,
    ol_shadowcolor='#000000',
    ol_shadowopacity=30,
    ol_textfont=ol_captionfont=ol_closefont="Verdana,Arial,Helvetica,Meiryo,sans-serif;";

// Useful arrays
var ImgTypes=new Array(
      'f','Front',
      'b','Back',
      '2','Both',
      'c','Cartridge',
      'd','Card',
      'D','Card back',
      's','Side',
      'S','Other side',
      't','Tape',
      'm','Misc',
      'i','Manual',
      'k','Booklet',
      'K','Book',
      'z','Magazine',
      'a','Ad',
      'p','Poster',
      'M','Map',
      'F','Flyer',
      'C','Catalogue',
      'T','Top',
      'B','Bottom',
      'P','Cartridge top',
      'I','Inlay',
      'w','Warranty'),
      // also used:
      // x (internally),
      // n (no scan),
      // N (no scan, isn't one),
      // r (redirect)
      // ~ (note text)
    SMSCartTypes=new Array(0,"card",10,"cartridge",5,"card <img src="+BasePath+"flags/jp.png>",13,"cartridge  <img src="+BasePath+"flags/jp.png>",40,"The Sega Card",
      43,"Parker Bros. <img src="+BasePath+"flags/us.png>",
      45,"The Sega Cartridge",50,"The Mega Cartridge",51,"The Mega Cartridge",55,"The Mega Plus Cartridge",
      60,"The Combo Cartridge",70,"The Two-Mega Cartridge",71,"The Two-Mega Cartridge",
      75,"The Two-Mega Plus Cartridge",80,"The 3-Dimensional Cartridge",90,"The Four-Mega Cartridge",
      95,"The Four-Mega Plus Cartridge",410,"Ariolasoft <img src="+BasePath+"flags/de.png>");

var isMulti,multiImage = '<img class=overlay src="'+BasePath+'multi.png" alt="+" title="This scan has multiple images.">';
var imgCounter = 1;

var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

function parsePagePattern(pattern)
{
  var bits = pattern.split(',');
  var prefix = '';
  var pages = new Array();
  var ext = '.jpg';
  for (var i = 0; i < bits.length; ++i)
  {
    // check for a prefix
    var val = parseInt(bits[i]);
    if (!val)
    {
      // it's text
      if (bits[i].indexOf('+')==0)
      {
        // it's a new prefix
        prefix = bits[i].substr(1);
      }
      else if (bits[i].indexOf('#')==0)
      {
        // it's a new extension type
        ext = '.' + bits[i].substr(1);
      }
      else
      {
        // it's a standalone page
        pages.push(bits[i]+ext);
      }
    }
    else
    {
      // it's a number or a range
      // numbers must be positive
      var dashpos = bits[i].indexOf('-');
      if (dashpos > -1)
      {
        // it's a range
        var start = parseInt(bits[i].substr(0,dashpos));
        var end = parseInt(bits[i].substr(dashpos+1));
        for (var j = start; j <= end; ++j)
        {
          pages.push(prefix + j + ext);
        }
      }
      else
      {
        // it's a single page
        pages.push(prefix + bits[i] + ext);
      }
    }
  }
  return pages;
}

function getNumPagesFromPattern(pattern)
{
  return parsePagePattern(pattern).length;
}

function encode64(input) {
   var output = "";
   var chr1, chr2, chr3;
   var enc1, enc2, enc3, enc4;
   var i = 0;

   do {
      chr1 = input.charCodeAt(i++);
      chr2 = input.charCodeAt(i++);
      chr3 = input.charCodeAt(i++);

      enc1 = chr1 >> 2;
      enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
      enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
      enc4 = chr3 & 63;

      if (isNaN(chr2)) {
         enc3 = enc4 = 64;
      } else if (isNaN(chr3)) {
         enc4 = 64;
      }

      output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) +
         keyStr.charAt(enc3) + keyStr.charAt(enc4);
   } while (i < input.length);
   
   return output;
}

function decode64(input) {
   var output = "";
   var chr1, chr2, chr3;
   var enc1, enc2, enc3, enc4;
   var i = 0;

   // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
   input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

   do {
      enc1 = keyStr.indexOf(input.charAt(i++));
      enc2 = keyStr.indexOf(input.charAt(i++));
      enc3 = keyStr.indexOf(input.charAt(i++));
      enc4 = keyStr.indexOf(input.charAt(i++));

      chr1 = (enc1 << 2) | (enc2 >> 4);
      chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
      chr3 = ((enc3 & 3) << 6) | enc4;

      output = output + String.fromCharCode(chr1);

      if (enc3 != 64) {
         output = output + String.fromCharCode(chr2);
      }
      if (enc4 != 64) {
         output = output + String.fromCharCode(chr3);
      }
   } while (i < input.length);

   return output;
}

function AddIndexLink(LinkHRef,LinkText,OverDivText) {
  var result='<a href="'+LinkHRef+'"';
  if (OverDivText.length>0) result+=' onMouseOver="return overlib(\''+OverDivText+'\');" onMouseOut="nd();"';
  result+='>&nbsp;'+LinkText+'&nbsp;</a>';
  return result;
}

function loadjs(filename)
{
  var fileref=document.createElement('script');
  fileref.setAttribute("type","text/javascript");
  fileref.setAttribute("src", filename);
  document.getElementsByTagName("head")[0].appendChild(fileref);
}

function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      if (oldonload) {
        oldonload();
      }
      func();
    }
  }
}

function Start(Letter,AdCode,IsText,ShowAtoZ) {
  var i;
  NumColumns=0;
  NumCellsDone=0;
  NumGames=0;
  NumGamesNoImage=0;
  NumImgs=0;
  TotalImgSize=0;
  TotalImgPixels=0;

  if (count) ShowAtoZ=false;

  // Extract which subfolder we are in
  CurrentSystem=location.pathname.substr(BasePath.length);
  if (CurrentSystem.length!=0) CurrentSystem=CurrentSystem.substr(0,CurrentSystem.indexOf('/'));

  for (i=0;i<SystemPaths.length;i++) if (SystemPaths[i]==CurrentSystem) CurrentSystemName=SystemNames[i];

  // preload flag images
  var Flags=new Array('au','br','ca','de','eu','fr','it','jp','kr','nz','ue','uk','us'),FlagImages=new Array();
  for (i=0; i<Flags.length; i++) {
    FlagImages[i]=new Image();
    FlagImages[i].src=BasePath+'flags/'+Flags[i]+'.png';
  }

  imgpath=Letter.toLowerCase();

  if(imgpath=='#')imgpath='numbers'; // dirty hack

  document.write('<html><head><title>SMS Power! - ',CurrentSystemName,' scans - ',Letter,'</title><LINK REL="stylesheet" TYPE="text/css" HREF="'+BasePath+'styles.css">');
  document.write('</head><body'+(ShowAtoZ!=0?' onResize="CheckForResize('+(IsText==1?'1':'0')+');"':'')+'>');
  document.write('<DIV ID="overDiv" STYLE="position:absolute; visibility:hidden; z-index:2000;"></DIV>');
  document.write('</DIV>');
  loadjs(BasePath+'overlib.js');
  loadjs(BasePath+'overlib_shadow.js');
  loadjs(BasePath+'highslide-full.packed.js');
  addLoadEvent(function() {
    hs.graphicsDir = BasePath+'graphics/';
    hs.wrapperClassName = "dark borderless";
    hs.align = "center";
    hs.marginBottom=hs.marginTop=40;
    hs.headingOverlay.relativeTo = "viewport";
    hs.headingOverlay.position = "bottom left";
    hs.dragByHeading = false;
    hs.captionOverlay.relativeTo = "viewport";
    hs.captionOverlay.position = "bottom right";
    hs.showCredits=false;
    hs.numberOfImagesToPreload=0;
    hs.dimmingOpacity=0.8;
    hs.dimmingDuration = 300;
    hs.transitions = ['expand', 'crossfade'];
    hs.addSlideshow({useControls: false, interval: 5000});
    hs.stripItemFormatter=stripFormatter;
  });
  document.write('<link rel="stylesheet" type="text/css" href="'+BasePath+'highslide.css" />');
  NumColumns=FitColumns(IsText);

  if (!count)
  {
    document.write('<a name=top><center></a>',AdCode,'<h2>',(debug?'Debugging<p>':''),'<a href=http://www.smspower.org><img src='+BasePath+'smspower.png border=0></a> - ',CurrentSystemName,' scans - ',Letter,'</h2>');
    document.write('<table border="0" cellpadding="0" cellspacing="0"><tr><td class="outertable"><table border="0" cellpadding="2" cellspacing="',linewidth,'" width="',(ShowAtoZ!=0?(cellwidth+linewidth)*NumColumns:1),'" class="maintable">');
  }
  ImgRow='';

  if (ShowAtoZ!=0) {
    Index+='<tr><td ';
    if (!IsText) Index+='colspan="'+NumColumns+'" ';
    Index+='class="atoz">';

    // Non-alphabetical entries
    var s='#ABCDEFGHIJKLMNOPQRSTUVWXYZm?';
    var i,j;
    var longname;
    for (j=0;j<SystemNames.length;j++) {
      Index+='<nobr>'+SystemNames[j]+': [';
      for(i=0; i<s.length; i++) {
        if(s.charAt(i)=='?') longname='other';
        else if(s.charAt(i)=='m') longname='media';
        else longname=s.charAt(i);

        if (SystemNoEntryPages[j].indexOf(s.charAt(i))!=-1) ImgRow='<span class="nopage">&nbsp;'+longname+'&nbsp;</span>'
        else if ((longname==Letter)&&(CurrentSystem==SystemPaths[j])) ImgRow='<span class="currentpage">&nbsp;'+Letter+'&nbsp;</span>';
        else {
          // Non-alphabetical entries
          if      (s.charAt(i)=='#') ImgRow=AddIndexLink(BasePath+SystemPaths[j]+'/numbers','#','Scans for '+SystemNames[j]+' games starting with numbers');
          else if (s.charAt(i)=='?') ImgRow=AddIndexLink(BasePath+SystemPaths[j]+'/other','other','All other '+SystemNames[j]+' scans');
          else if (s.charAt(i)=='m') ImgRow=AddIndexLink(BasePath+SystemPaths[j]+'/media','media',SystemNames[j]+' book, magazine, leaflet, catalogue scans');
          // Normal letters
          else ImgRow=AddIndexLink(BasePath+SystemPaths[j]+'/'+s.toLowerCase().charAt(i),s.charAt(i),'Scans for '+SystemNames[j]+' games starting with letter '+s.charAt(i));
        }
        if (s.charAt(i)=='M') ImgRow+='</nobr><wbr><nobr>';
        Index+=ImgRow;
      }
      Index+=']<br> ';
    }

    if (Letter=='index') Index+='[<span class="currentpage"> index </span>]';
    else Index+='[<a href='+BasePath+'> index </a>]';

    if (!IsText)
      Index+=' [ '+NumColumns+' columns -<a href="javascript:CheckForResize(0);" onMouseOver="return overlib(\'Click here to rearrange the page to fit your browser width\');" onMouseOut="nd();"> fit </a>]';

    Index+='</nobr></td></tr>';
    document.write(Index);
  }

  if (!count)
  {
    if (IsText) {
      document.write('<tr><td class="text">');
    } else {
      document.write('<tr>');
      for (var i=1; i<=NumColumns; i++)
        document.write('<td class="sizer"><img src="'+BasePath+'blank.png" width="'+cellwidth+'" height="1"></td>');
      document.write('</tr><tr>');
    }
  }

  ImgRow='';
}

function EscapeQuotes(s,n) {
  // Unfortunately I can't properly escape " to \" and enclose it in ' and " as is needed, so I'll turn " into ''.
  if (n==1) s=s.replace(/\"/g,'\'\'');
  return s.replace(/\\/g,'\\\\').replace(/\"/g,'\\\"').replace(/\'/g,'\\\'');
}

// not used - regexp instead str.replace(/<char1>.+<char2>/g,'')
/*
function RemoveBetween(str,char1,char2) {
  var StartPos=0,EndPos=0,result='';
  while (EndPos<str.length) {
    EndPos=str.indexOf(char1,StartPos);
    if (EndPos==-1) EndPos=str.length;
    result+=str.slice(StartPos,EndPos);
    StartPos=str.indexOf(char2,EndPos)+1;
  }
  return result;
}
*/

function GetName(longname) {
  //             --remove: brackets at end  -- HTML              -- The..Les..           -- bad chars                 -- brackets at start  --change / to &---        --remove: accented characters
  return longname.replace(/(.)\(.*\)/g,"$1").replace(/<.+?>/g,"").replace(/^The|^Les/,'').replace(/[ $+.'":\-?!]/g,'').replace(/^\(.+\)/,'').replace(/\/|&#x2f;/g,'&').replace(/&#233;|&#234;|&egrave;|&eacute;/g,'e').replace(/&#244;/g,'o').replace(/&#225;|&#227;/g,'a').replace(/&#237;/g,'i').replace(/&#218;|&#249;|&uuml;/g,'u').replace(/&#231;/,'c').toLowerCase();
}

function LinkTo(Before,After) {
  var result=Before;
  for(var i=2; i<arguments.length; i++) {
    if ((arguments.length>3)&&(i>2)) {
      if (i<arguments.length-1)
        result+=', ';
      else
        result+=' and ';
    }
    // look for a system prefix
    var system="";
    for(var s=0;s<SystemPaths.length;s++)
    {
      if(arguments[i].indexOf(SystemPaths[s]+':')==0)
      {
        var colon=arguments[i].indexOf(':');
        system = arguments[i].substr(0,colon);
        arguments[i] = arguments[i].substr(colon+1);
      }
    }

    var slash = arguments[i].indexOf('/');
    var prefix,shortname,longname = arguments[i];
    if (slash == -1)
    {
      shortname = GetName(longname);
      prefix = shortname.charAt(0).replace(/[0-9]/,'numbers');
    }
    else
    {
      prefix = longname.substr(0,slash);
      longname = longname.substr(slash+1);
      shortname = GetName(longname);
    }
    if (system.length>0)
      prefix = "../" + system + "/" + prefix;

//    result+='<a href="'+(imgpath.search(/^sc$|^sg$/)==-1?shortname.charAt(0).replace(/[0-9]/,'numbers'):imgpath)+'.shtml#'+shortname+'">'+arguments[i]+'</a>';
    result+='<a href="'+prefix+'#'+shortname+'">'+longname+'</a>';
  }
  return result+After;
}

function BreakBrackets(text,keepBrackets){
  // Makes text (more text) into text<br>(more text)
  //                          or text<br>more text
  // but not " (text)" into "<br> (text)" ([^^] = not start of line)
  if(keepBrackets) return text.replace(/([^^]) \(/g,'$1<br>(');
  else {
    text=text.replace(/([^^]) \(/g,'$1<br>');
    if(text.indexOf('<br>')>-1)text=text.replace(/\)/g,'');
    return text;
  }
}

function SmallLeadingBrackets(text) {
  // Makes (text) more text into <small>text</small><br>
  var result=text.replace(/^\(/,'<span class="small">');
  if(result.indexOf('class="small"')>-1)result=result.replace(/\) /,'</span><br>');
  return result;
}

function GameNumberToText(Num) {
  var result='';
  if (typeof(Num)=='number') {
    var tt=Math.floor(Num/10000),t=Math.floor(Num/1000),h=Math.floor(Num/100);
    if (CurrentSystem=='sms') {
      // SMS, number format
      if (tt==2) h-=200; // change 2nxxx to nxxx
      if (Num<5005&&Num>=5000&&tt!=2) result=Num+' (US cartridge by Activision'
      else for(var i=0;i<SMSCartTypes.length;i++)if(SMSCartTypes[i]==h){result=Num+' ('+SMSCartTypes[i+1];break;}

      switch (h) {
        case 0:
        case 5: result='C-'+(Num<10?'0':'')+result; break;
        case 10:
        case 13: result='G-'+result;
      }
      if (tt==2) result+=' (3rd party)';
      if (result.indexOf('(')>-1) result+=')';
    } else if (CurrentSystem=='gg') {
      // GG, number format
      if (tt==0) result+='G-'+Num+' (';
      else result+='T-'+Num+' (3rd party - ';
      var Licences=new Array(02,"Sega (Export)",03,"Sega (Japan)",11,"Taito",14,"Namco",15,"SunSoft",22,"Micronet",23,"Vic Tokai/SIMS",25,"NCS",26,"Sigma Enterprises",28,"Genki",32,"Wolf Team",33,"Kaneko",44,"Sanritsu/SIMS",45,"Game Arts/Studio Alex",48,"Tengen/Time Warner",49,"Telenet Japan",50,"EA",51,"SystemSoft",52,"Microcabin",53,"Riverhill Soft",54,"ASCII Corp.",60,"Victor/Loriciel/Infogrames",65,"Tsukuda Ideal",66,"Compile",68,"GRI",70,"Virgin",79,"US Gold",81,"Acclaim",83,"GameTek",87,"Mindscape",88,"Domark",93,"Sony",100,"THQ",103,"SNK",104,"Microprose",112,"Disney",120,"Codemasters",121,"Codemasters",125,"Beam Software P/L",133,"Bandai",139,"Viacom",149,"Infocom/Gremlin",151,"Infogrames",154,"Technos Japan Corp.");
      for (var i=0;i<Licences.length;i+=2) if (Licences[i]==t) {result+=Licences[i+1];break;}
      if (i==Licences.length) result+='Unknown';
      result+=')';
    } else if (CurrentSystem=='sgsc') {
      // SG/SC, number format
      if (h+t+tt==0) result+='C-'+(Num<10?'0':'')+Num+' (Sega My Card)';
      else result+='G-'+Num+' (Sega Cartridge)';
    }
  } else if (typeof(Num)=='string') {
    if (Num=='n')					result=''
    else if (Num.indexOf('OM-G00')==0)    result=Num+' (Tsukuda Original OMV card <img src='+BasePath+'flags/jp.png>)'
    else if (Num.indexOf('Silver-00')>-1) result=Num+' (Salio cartridge <img src='+BasePath+'flags/jp.png>)'
    else if (Num.indexOf('-0160')>-1)     result=Num+' (Tengen <img src='+BasePath+'flags/us.png>)'
    else if (Num.indexOf('GB-800')==0)    result=Num+' (Graphics Board <img src='+BasePath+'flags/jp.png>)'
    else if (Num.indexOf('GB')==0)        result=Num+' (cartridge <img src='+BasePath+'flags/kr.png>)'
    else if (Num.length==7 && Num.charAt(3)=='.')	result=Num+' (TecToy cartridge <img src='+BasePath+'flags/br.png>)'
    else if (Num.indexOf('-RP')>-1)      result=Num+' (Aladdin Boy &#xc54c;&#xb77c;&#xb518; &#xbcf4;&#xc774; cartridge <img src='+BasePath+'flags/kr.png>)'
    else if (Num.indexOf('ST')==0)        result=Num+' (John Sands Sega <img src='+BasePath+'flags/au.png>)'
    else if (Num.indexOf('B-')==0)        result=Num+' (Sega BASIC)'
    else if (Num.indexOf('E-')==0)        result=Num+' (Sega Educational)'
    else if (Num.length==4 && Num.indexOf('S-')==0)        result=Num+' (Samsung <img src='+BasePath+'flags/kr.png>)'
    else if (Num.length==4 && Num.indexOf('G-')==0)        result=Num+' (Samsung <img src='+BasePath+'flags/kr.png>)'
    else if (Num=='')					result='Unknown'
    else 						result=Num;
  } else {
    alert('Unknown type: '+typeof(Num));
  }
  return result;
}

function MakeGameInfoPopup(Num,GameName) {
  var result='';
  if (typeof(Num)=='object') {
    for (var i=0;i<Num.length;i++) {
      result+=GameNumberToText(Num[i]);
      result+=(i<Num.length-1?'<br>':'')
    }
  } else result=GameNumberToText(Num);
  if (result=='') return '';
  return ' onMouseOver="return overlib(\'<b>Product code'+(result.indexOf('<br>')>-1?'s':'')+':</b><br>'+result+'\',STATUS,\''+EscapeQuotes(GameName,1)+'\');" onMouseOut="nd();"';
}

function Add(GameNumber,GameName,Notes) {
  NumGames++;

  // Get number of cells required
  var CellCount=1;
  for(var i=1; i<arguments.length; i++) if(arguments[i]=='-') CellCount++;

  // Start new line if no cells left
  if (NumCellsDone==NumColumns) {
    if (!count) document.write('</tr><tr>',ImgRow,'</tr><tr>');
    NumCellsDone=0;
    ImgRow='';
  }

  // Handle games with more images than will fit on the line
  var NewDataLine='';
  if (CellCount>(NumColumns-NumCellsDone)) {
    NumGames--;
    if (typeof(GameNumber)=='object') {
    	// Parse array
    	// .toSource() should do this, but..?
    	for (var i=0;i<GameNumber.length;i++) {
    	  if (typeof(GameNumber[i])=='string') NewDataLine+='"'+GameNumber[i]+'"'
    	  else NewDataLine+=GameNumber[i];
    	  NewDataLine+=',';
    	}
    	NewDataLine='['+NewDataLine.substring(0,NewDataLine.length-1)+']';
    } else if (typeof(GameNumber)=='string') NewDataLine='"'+GameNumber+'"'
    else NewDataLine=GameNumber;
    NewDataLine+=',"'+EscapeQuotes(GameName);
    NewDataLine+='","'+EscapeQuotes(Notes);
    if (NewDataLine.indexOf('continued')==-1) NewDataLine+=' (continued)';
    NewDataLine+='"';
    var j=0;
    for (var i=3; i<arguments.length; i++) {
      if (j>=(NumColumns-NumCellsDone)) {
        if ((arguments[i]=='')||(typeof(arguments[i])=='string')) {
      		NewDataLine+=',"'+arguments[i]+'"';
      	} else {
      		NewDataLine+=','+arguments[i];
      	}
        arguments[i]='x';
      } else {
        if (arguments[i]=='-') j++;
        if (j==(NumColumns-NumCellsDone)) arguments[i]='x';
      }
    }
    CellCount=j;
  }

  // Start new row if necessary
  if (NumCellsDone+CellCount>NumColumns) {
    if (!count) document.write('</tr><tr>',ImgRow,'</tr><tr>');
    NumCellsDone=0;
    ImgRow='';
  }

  NumCellsDone+=CellCount;

  if (CellCount>NumColumns) (CellCount=NumColumns);

  var ImgName=GetName(GameName);
  var ImgNote;

  // Title
  if (!count) document.write('\n<td class="title',(window.location.hash.substr(1)==ImgName?' highlighted':''),'" colspan="',CellCount,'">',(NumCellsDone==NumColumns?'<a href=#top onMouseOver="return overlib(\'back to top\',WIDTH,80);" onMouseOut="nd();"><img align=right src="'+BasePath+'top.png" border=0></a>':''),'<a name="',ImgName,'"></a><a href="#',ImgName,'" class="nohighlight" ',MakeGameInfoPopup(GameNumber,GameName),' onClick="return false;">',BreakBrackets(SmallLeadingBrackets(GameName),false),'</a>',(Notes!=''?'<br><span class="small">'+BreakBrackets(Notes,true)+'</span>':''),'</td>');

  // Images
  ImgRow+='\n<td class="'+('rnN'.indexOf(arguments[3].charAt(0))>-1?'toplink':'images')+'" colspan="'+CellCount+'" height="108"><table align=center border=0 cellpadding=0 cellspacing=0><tr>';
  for(var i=3; i<arguments.length; i+=6) {
    if (arguments[i]=='x') break;

    ImgRow+='\n<td>';

    if ((arguments[i]=='')||(arguments[i]=='-')) {ImgRow+='<img src="'+BasePath+'blank.png" width="4">';i-=5;}
    else{
      var fullname=arguments[i].charAt(0),ext='.jpg',ImgNumber=arguments[i].substr(1);

      var ImgType='';
      for (var ii=0; ii<ImgTypes.length; ii+=2) {
        if (fullname==ImgTypes[ii]) {
          ImgType=ImgTypes[ii+1];
          break;
        }
      }

      if (ImgType!='') {
        if (String(arguments[i]).indexOf('g')!=-1) {
          ext='.gif';
          ImgNumber=ImgNumber.substr(0,ImgNumber.length-1);
        }
        if (String(arguments[i]).indexOf('png')!=-1) {
          ext='.png';
          ImgNumber=ImgNumber.substr(0,ImgNumber.length-3);
        }
        if (ImgNumber=='') ImgNumber=1;
        fullname=ImgName+'-'+ImgType.toLowerCase().replace(/ /,'')+ImgNumber;
      }

      // Remove any bracketed portion
//      var ProperTitle=arguments[1].replace(/[^^]\(.*\)/,'').replace(/^\(.*\)/,'');
      // Move spaced bracketed parts to new lines
      var ProperTitle=arguments[1].replace(/ \(/g,'<br>').replace(/\)/g,'').replace(/\(/g,'');

      if (ImgType=='') {
        if (fullname=='r') {
          // redirection
          var bits=ImgNumber.split(',');
          for(var ii=0;ii<bits.length;++ii)
            ImgRow+=LinkTo('see ','<br>',bits[ii]);
          NumGames--;
        } else {
          // no image
          if (fullname=='N') NumGames--; else NumGamesNoImage++;
          ImgRow+=(ImgNumber!=''?ImgNumber+'<br><br>':'')+(fullname!='N'?'<a href="'+BasePath+'submit.shtml">Submit this scan</a>':'');
        }
      } else { // images
        var params=
                'system='+CurrentSystem
              +'&path='+escape(imgpath+'/'+fullname+ext)
              +'&type='+ImgType
              +'&width='+arguments[i+1]
              +'&height='+arguments[i+2]
              +'&size='+arguments[i+3]
              +'&contributor='+escape(arguments[i+4])
              +'&country='+arguments[i+5];
        var desc=(debug?fullname+ext+'<br>':'')+'<b>Scan type: </b>'+ImgType;
        var flag=arguments[i+5];
        var note=null;
        var pattern = null;

        if (ImgType=='Magazine') { // Image number is issue number
         desc+='<br><b>Issue: </b>'+ImgNumber;
        }
        if (ImgType=='Booklet'||ImgType=='Manual'||ImgType=='Magazine'||ImgType=='Book'||ImgType=='Catalogue'||ImgType=='Warranty') { // Multiple images for one thumbnail
          var numPages;
          if (typeof(arguments[i+6])=='number')
          {
            numPages = arguments[i+6];
            pattern = '1-'+arguments[i+6];
          }
          else
          {
            pattern = arguments[i+6];
            numPages = getNumPagesFromPattern(pattern);
          }
          isMulti = numPages > 1;
          if (arguments[i+7] && arguments[i+7].indexOf('~')==0)
            note = arguments[i+7].substr(1).replace(/~/g,'<br>');
          params += '&book=true&pages='+numPages+'&pagepattern='+pattern;
          desc+= '<br><b>Number of scans: </b>'+numPages
                +'<br><b>'+(isMulti?'Typical d':'D')+'imensions: </b>'+arguments[i+1]+'&times;'+arguments[i+2]
                +'<br><b>'+(isMulti?'Average f':'F')+'ile size: </b>'+arguments[i+3]+'KB'
                +(arguments[i+4]!=''?'<br><b>Contributor: </b>'+EscapeQuotes(arguments[i+4]):'')
                +(note?'<br><b>Note: </b>'+note:'');
          NumImgs+=numPages;
          TotalImgSize+=numPages*arguments[i+3];
          TotalImgPixels+=numPages*arguments[i+1]*arguments[i+2];
          i++;
        } else { // Other image
          isMulti = false;
          if (arguments[i+6] && arguments[i+6].indexOf('~')==0)
            note=arguments[i+6].substr(1).replace(/~/g,'<br>');
          desc+= '<br><b>Dimensions: </b>'+arguments[i+1]+'&times;'+arguments[i+2]
                +'<br><b>File size: </b>'+arguments[i+3]+'KB'
                +(arguments[i+4]!=''?'<br><b>Contributor: </b>'+EscapeQuotes(arguments[i+4]):'')
                +(note?'<br><b>Note: </b>'+note:'');
          NumImgs++;
          TotalImgSize+=arguments[i+3];
          TotalImgPixels+=arguments[i+1]*arguments[i+2];
        }

        params=encode64(params);

        // Highslide stuff to go into the <a>
        var hsJS = '';
        var hsSlides = '';
        var hsdesc = '';
        if (flag!='')
        {
          hsdesc += '<b>Region of origin:</b> <img src=\''+BasePath+'flags/'+flag+'.png\'> '+getCountryText(flag)+'<br>';
        }
        hsdesc = '\'' + EscapeQuotes(hsdesc) + desc + '\'';

        if (pattern != null)
        {
          var pages = parsePagePattern(pattern);
          var prefix = imgpath + '/' + fullname + '-';

          if (!isMulti)
          {
            hsJS = ' onClick="return hs.expand(this, { headingText: \''+EscapeQuotes(ProperTitle)+'\', src: \'scans/' + prefix + pages[0].toLowerCase() + '\', captionText:'+hsdesc+'})"';
          }
          else
          {
            hsJS = ' onClick="return document.getElementById(\'gallery'+imgCounter+'\').onclick()"';

            // Other stuff to go into the page for the slideshow
            hsSlides = '<div class="hidden-container">\n';
            for (var z = 0; z < pages.length; ++z)
            {
              var imgfilename = prefix + pages[z].toLowerCase();
              var imgdesc = changeExt(pages[z], '');
              hsSlides +=
                '<a href="scans/' + imgfilename + '"'
                + (z == 0 ? ' id = gallery'+imgCounter : '')
                + ' onclick="return hs.expand(this, {'
                +   ' headingText: \''+EscapeQuotes(ProperTitle)+'\','
                +   ' thumbnailId: \'thumb'+imgCounter+'\','
                +   ' slideshowGroup: '+imgCounter+','
                +   ' captionText: '+hsdesc
                + ' })">'
                +'[img src="thumbnails/' + changeExt(imgfilename, '.jpg') + '" onmouseover="return overlib(\'' + imgdesc + '\',WIDTH,10)" onmouseout="nd()"]'
                +'</a>\n';
            }
            hsSlides += '</div>';
            hsSlides += '<script>addLoadEvent(function() {'
              + 'hs.addSlideshow({'
              + 'slideshowGroup:' + imgCounter + ','
              + 'useControls:true,'
              + 'interval:5000,'
              + 'overlayOptions: {className: "text-controls",position:"bottom center",relativeTo:"viewport",offsetX:50,offsetY:-5},'
              + 'thumbstrip:{position:"right middle",mode:"float",relativeTo:"viewport"}'
              + '});'
              + '});</script>';
          }
        }
        else
        {
            hsJS = ' onClick="return hs.expand(this, { headingText: \''+EscapeQuotes(ProperTitle)+'\', src: \'scans/' + imgpath+'/'+fullname+'.jpg\', captionText:'+hsdesc+'})"';
        }

        ImgRow+='<div class="wrap1"><div class="wrap2"><div class="wrap3">'
              +'<a href="'+BasePath+CurrentSystem+'/'+ImgName+'/'+ImgType.toLowerCase().replace(/ /,'')+'/'+ImgNumber+'?'+params+'"'
              +  ' target=_blank'
              +  ' onMouseOver="return overlib('
              +                               '\''+desc+'\''
              +                               ',CAPTION,\''+EscapeQuotes(ProperTitle,1)+'\''
              +                               (flag!=''?',CAPICON,\''+BasePath+'flags/'+flag+'.png\'':'')
              +  ' );"'
              +  ' onMouseOut="nd();"'
              +hsJS
              +'>'
              +'<img class="thumb"'
              +    ' src="thumbnails/'+imgpath+'/'+fullname+'.jpg"'
              +    ' border="0"'
              +    ' id=thumb' + imgCounter + '>'
              +(isMulti?multiImage:'')
              +'</a>'
              +'</div></div></div>'
              +hsSlides;

        if(note)
          i++;

        imgCounter++; // increment counter
      }
    }
    ImgRow+='</td>';
  }
  ImgRow+='</tr></table></td>';

  if (NewDataLine!='') eval('Add('+NewDataLine+');');
}

function formatsize(size) {
  // parameter is number of KB
  var c,sym=new Array("KB","MB","GB"),sizestr,m=new Array(0,100,10,1,1),dp;
  for(c=0;size>1024;++c,size/=1024);
  // figure out where to truncate the text
  sizestr=new String(size);
  dp=sizestr.indexOf(".");
  if(dp>-1){
    sizestr=new String(Math.round(size*m[dp]));
    if(dp<3)
      sizestr=sizestr.substr(0,dp)+'.'+sizestr.substr(dp,3);
  }
  return sizestr+sym[c];
}

function Finish(ShowCount,GamesText) {
  var s="";
  if (arguments.length<2) GamesText='game';
  if (count)
  {
    var NumOther = 0;
    if (GamesText != 'game')
    {
      NumOther = NumGames;
      NumGames = 0;
      NumGamesNoImage = 0; // should be anyway
    }
    s += "<div id=numwithimgs>" + (NumGames-NumGamesNoImage) + "</div>";
    s += "<div id=numgames>"    + NumGames + "</div>";
    s += "<div id=numimgs>"     + NumImgs + "</div>";
    s += "<div id=numkb>"       + TotalImgSize + "</div>";
    s += "<div id=numpx>"       + TotalImgPixels + "</div>";
    s += "<div id=numother>"    + NumOther + "</div>";
    document.write(s);
    document.close();
    return;
  }
  if (ShowCount!=0)
  {
    if(NumCellsDone<NumColumns)
      s+='<td rowspan="2" colspan="'
        +(NumColumns-NumCellsDone)
        +'" class="toplink"><a href=#top onMouseOver="return overlib(\'back to top\',WIDTH,80);" onMouseOut="nd();"> <img src="'
        +BasePath
        +'top.png" border=0> </a></td>';
    s+='</tr><tr>'
      +ImgRow
      +'</tr><tr>'
      +'<td colspan="'+NumColumns+'" class="footer"><nobr>'
      +(NumGames-NumGamesNoImage)+' of '+NumGames+' '
      +GamesText+(NumGames==1?'':'s')
      +' ('+(NumGames?Math.round((NumGames-NumGamesNoImage)/NumGames*100):100)+'%); '
      +NumImgs+' image'+(NumImgs==1?'':'s')
      +' <span onMouseOver="return overlib(\''+TotalImgSize*1024+'&nbsp;bytes<br>'+TotalImgPixels+'&nbsp;pixels\',WIDTH,10);" onMouseOut="nd();">('
      +formatsize(TotalImgSize)
      +', '+
      +Math.round(TotalImgPixels/100000)/10
      +'Mpx total)</span>.</nobr> '
      +'&nbsp; <nobr>[ <a href="'+BasePath+'copy.shtml">copyright info</a> | '
      +'<a href="'+BasePath+'imgs.shtml">image info</a> | '
      +'<a href="'+BasePath+'submit.shtml">submit a scan</a> ] &nbsp;</nobr> '
      +'<nobr>[ <a href=#top>back to top</a> ]</nobr>';
  }
  s+='</td></tr>'+Index+'</table></td></tr></table></center></body></html>';
  document.write(s);
  document.close();
}

function CheckForResize(IsText) {
  var x=FitColumns(IsText);
  if(x!=NumColumns)
    setTimeout("window.location.reload()",0);
}

function FitColumns(IsText) {
  var width=600;
  if(document.body&&document.body.clientWidth)width=document.body.clientWidth;
  else if(window.innerWidth)width=window.innerWidth;
  width = Math.floor(width/(cellwidth+linewidth));
  if(width<2) width=2;
  if((IsText==1)&&width>4)width=4;
  // Wii override
  if (navigator.userAgent.indexOf("Nintendo Wii")>0)
    return 2;
  return width;
}

function SA() {
  var args='';
  for (var i=0; i<arguments.length; i++) args+=',"'+arguments[i]+'"';
  return eval('LinkTo(" (see also ",")"'+args+')');
}


function initExpander(sender)
{
  var s = "The current properties of sender:\n\n";
  for (var x in sender) {
    if (typeof sender[x] != "function")
      s += x +": "+ sender[x] +"\n";
  }
  alert(s);
  return true;
}

function stripFormatter(a)
{
  // Slideshow images are links with the inner HTML changed from <> to []
  if (a.children.length == 0) return a.innerHTML.replace(/\[/,"<").replace(/\]/,">");
  return a.innerHTML;
}

function changeExt(s, ext)
{
  var dotpos = s.lastIndexOf('.');
  if (dotpos < 0)
  {
    return s;
  }
  return s.substr(0, dotpos) + ext;
}
