fteqw/engine/web/fteshell.html

359 lines
13 KiB
HTML
Raw Normal View History

<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Added sys_openfile console command(and menu option) to web and flatpak(via cmake+dbus) builds, to 'install' packages on sandboxed systems a bit more easily. Cmake: Add FTE_WERROR option, defaults to true in debug builds and off in release builds (in case future compilers have issues). Cmake: Pull in libXscreensaver so we don't get interrupted by screensavers when playing demos. Make: Added `make webcl-rel` for a web build without server bloat (eg for sites focused on demo playback. Yes, this means you XantoM). fteqcc: Include the decompiler in fteqcc (non-gui) builds ('-d' arg). fteqcc: Decompiler can now mostly handle hexen2 mods without any unknown opcodes. Allow ezHud and OpenSSL to be compiled as in-engine plugins, potentially for web and windows ports respectively. Web: Fix support for ogg vorbis. Add support for voip. Web: Added basic support for WebXR. QTV: Don't try seeking on unseekable qtv streams. Don't spam when developer 1 is set. QTV: add support for some eztv extensions. MVD: added hack to use ktx's vweps in mvd where mvdsv doesn't bother to record the info. qwfwd: hack around a hack in qwfwd, allowing it to work again. recording: favour qwd in single player, instead of mvd. Protocol: reduce client memory used for precache names. Bump maximum precache counts - some people are just abusive, yes you Orl. hexen2: add enough clientside protocol compat to play the demo included with h2mp. lacks effects. in_xflip: restored this setting. fs_hidesyspaths: new cvar, defaults to enabled so you won't find your username or whatever turning up in screenshots or the like. change it to 0 before debuging stuff eg via 'path'. gl_overbright_models: Added cvar to match QS. netchan: Added MTU determination, we'll no longer fail to connect when routers stupidly drop icmp packets. Win: try a few other versions of xinput too. CSQC: Added a CSQC_GenerateMaterial function, to give the csqc a chance to generate custom materials. MenuQC: Added support for the skeletal objects API.
2024-04-09 17:13:59 +00:00
<link rel="manifest" href="fte_pwa.json" />
<meta name=viewport content="width=device-width, initial-scale=1">
Added sys_openfile console command(and menu option) to web and flatpak(via cmake+dbus) builds, to 'install' packages on sandboxed systems a bit more easily. Cmake: Add FTE_WERROR option, defaults to true in debug builds and off in release builds (in case future compilers have issues). Cmake: Pull in libXscreensaver so we don't get interrupted by screensavers when playing demos. Make: Added `make webcl-rel` for a web build without server bloat (eg for sites focused on demo playback. Yes, this means you XantoM). fteqcc: Include the decompiler in fteqcc (non-gui) builds ('-d' arg). fteqcc: Decompiler can now mostly handle hexen2 mods without any unknown opcodes. Allow ezHud and OpenSSL to be compiled as in-engine plugins, potentially for web and windows ports respectively. Web: Fix support for ogg vorbis. Add support for voip. Web: Added basic support for WebXR. QTV: Don't try seeking on unseekable qtv streams. Don't spam when developer 1 is set. QTV: add support for some eztv extensions. MVD: added hack to use ktx's vweps in mvd where mvdsv doesn't bother to record the info. qwfwd: hack around a hack in qwfwd, allowing it to work again. recording: favour qwd in single player, instead of mvd. Protocol: reduce client memory used for precache names. Bump maximum precache counts - some people are just abusive, yes you Orl. hexen2: add enough clientside protocol compat to play the demo included with h2mp. lacks effects. in_xflip: restored this setting. fs_hidesyspaths: new cvar, defaults to enabled so you won't find your username or whatever turning up in screenshots or the like. change it to 0 before debuging stuff eg via 'path'. gl_overbright_models: Added cvar to match QS. netchan: Added MTU determination, we'll no longer fail to connect when routers stupidly drop icmp packets. Win: try a few other versions of xinput too. CSQC: Added a CSQC_GenerateMaterial function, to give the csqc a chance to generate custom materials. MenuQC: Added support for the skeletal objects API.
2024-04-09 17:13:59 +00:00
<title>FTE Engine</title>
<style>
html,body { background-color:#000000; color:#808080; height:100%;width:100%;margin:0;padding:0;}
.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
div.emscripten { text-align: center; padding:0; margin: 0;}
/* the canvas *must not* have any border or padding, or mouse coords will be wrong */
canvas.emscripten { border: 0px none; width:100%; height:100%; padding:0; margin: 0;}
</style>
</head>
<body ondrop="gotdrop(event);" ondragover="event.preventDefault()">
<div class="emscripten" id="status">Please allow/unblock our javascript to play.</div>
<div id="dropzone" ondrop="gotdrop(event);" ondragover="event.preventDefault()" hidden=1>Drop Zone</div>
<button type="button" onclick="adduserfile()" id="addfile" hidden=1>Add File(s)</button>
<button type="button" onclick="begin()" id="begin" hidden=1>Click To Begin!</button>
<div class="emscripten">
<progress value="0" max="100" id="progress" hidden=1></progress>
</div>
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" hidden=1></canvas>
<script type='text/javascript'>
Added sys_openfile console command(and menu option) to web and flatpak(via cmake+dbus) builds, to 'install' packages on sandboxed systems a bit more easily. Cmake: Add FTE_WERROR option, defaults to true in debug builds and off in release builds (in case future compilers have issues). Cmake: Pull in libXscreensaver so we don't get interrupted by screensavers when playing demos. Make: Added `make webcl-rel` for a web build without server bloat (eg for sites focused on demo playback. Yes, this means you XantoM). fteqcc: Include the decompiler in fteqcc (non-gui) builds ('-d' arg). fteqcc: Decompiler can now mostly handle hexen2 mods without any unknown opcodes. Allow ezHud and OpenSSL to be compiled as in-engine plugins, potentially for web and windows ports respectively. Web: Fix support for ogg vorbis. Add support for voip. Web: Added basic support for WebXR. QTV: Don't try seeking on unseekable qtv streams. Don't spam when developer 1 is set. QTV: add support for some eztv extensions. MVD: added hack to use ktx's vweps in mvd where mvdsv doesn't bother to record the info. qwfwd: hack around a hack in qwfwd, allowing it to work again. recording: favour qwd in single player, instead of mvd. Protocol: reduce client memory used for precache names. Bump maximum precache counts - some people are just abusive, yes you Orl. hexen2: add enough clientside protocol compat to play the demo included with h2mp. lacks effects. in_xflip: restored this setting. fs_hidesyspaths: new cvar, defaults to enabled so you won't find your username or whatever turning up in screenshots or the like. change it to 0 before debuging stuff eg via 'path'. gl_overbright_models: Added cvar to match QS. netchan: Added MTU determination, we'll no longer fail to connect when routers stupidly drop icmp packets. Win: try a few other versions of xinput too. CSQC: Added a CSQC_GenerateMaterial function, to give the csqc a chance to generate custom materials. MenuQC: Added support for the skeletal objects API.
2024-04-09 17:13:59 +00:00
//set up a service worker, so that we can actually be installed if so, instead of living in the more general browser cache. Yay for running an online game offline...
if ("serviceWorker" in navigator)
navigator.serviceWorker.register("fte_pwa_sw.js", { scope: "./" }).catch((error) => {console.error(`Service worker registration failed: ${error}`);});
function str2ab(str)
{ //helper function. Not utf-8, so stick to ascii chars
var buf = new ArrayBuffer(str.length);
var bufView = new Uint8Array(buf);
for (var i=0, strLen=str.length; i < strLen; i++)
bufView[i] = str.charCodeAt(i);
return buf;
}
// connect to canvas
var Module = {
files:
{ //these can be arraybuffers(you'll need a helper to define those) or promises(fte will block till they complete), or strings (which will be interpretted as urls and downloaded before any C code is run)
//note that the code below will skip the file-drop prompt if there's any files specified here (or there's a #foo.fmf file specified)
Added sys_openfile console command(and menu option) to web and flatpak(via cmake+dbus) builds, to 'install' packages on sandboxed systems a bit more easily. Cmake: Add FTE_WERROR option, defaults to true in debug builds and off in release builds (in case future compilers have issues). Cmake: Pull in libXscreensaver so we don't get interrupted by screensavers when playing demos. Make: Added `make webcl-rel` for a web build without server bloat (eg for sites focused on demo playback. Yes, this means you XantoM). fteqcc: Include the decompiler in fteqcc (non-gui) builds ('-d' arg). fteqcc: Decompiler can now mostly handle hexen2 mods without any unknown opcodes. Allow ezHud and OpenSSL to be compiled as in-engine plugins, potentially for web and windows ports respectively. Web: Fix support for ogg vorbis. Add support for voip. Web: Added basic support for WebXR. QTV: Don't try seeking on unseekable qtv streams. Don't spam when developer 1 is set. QTV: add support for some eztv extensions. MVD: added hack to use ktx's vweps in mvd where mvdsv doesn't bother to record the info. qwfwd: hack around a hack in qwfwd, allowing it to work again. recording: favour qwd in single player, instead of mvd. Protocol: reduce client memory used for precache names. Bump maximum precache counts - some people are just abusive, yes you Orl. hexen2: add enough clientside protocol compat to play the demo included with h2mp. lacks effects. in_xflip: restored this setting. fs_hidesyspaths: new cvar, defaults to enabled so you won't find your username or whatever turning up in screenshots or the like. change it to 0 before debuging stuff eg via 'path'. gl_overbright_models: Added cvar to match QS. netchan: Added MTU determination, we'll no longer fail to connect when routers stupidly drop icmp packets. Win: try a few other versions of xinput too. CSQC: Added a CSQC_GenerateMaterial function, to give the csqc a chance to generate custom materials. MenuQC: Added support for the skeletal objects API.
2024-04-09 17:13:59 +00:00
//string values are deemed to be URLs, so use the str2ab("") helper if you want to embed raw file data instead.
// "default.fmf": "default.fmf",
// "id1/pak0.pak": "pak0.pak",
// "id1/default.cfg": "webdefaults.cfg", //autoexec.cfg is evil.
/* "id1/touch.cfg": str2ab("showpic_removeall\n"
"showpic touch_moveforward.tga fwd -128 -112 bm 32 32 +forward 5\n"
"showpic touch_moveback.tga back -128 -80 bm 32 32 +back 5\n"
"showpic touch_moveleft.tga left -160 -88 bm 32 32 +moveleft 5\n"
"showpic touch_moveright.tga rght -96 -88 bm 32 32 +moveright 5\n"
"showpic touch_attack.tga fire -160 -160 bm 32 32 +attack 5\n"
"showpic touch_jump.tga jump 128 -80 bm 32 32 +jump 5\n"
"showpic touch_weapons.tga weap 80 -80 bm 32 32 +weaponwheel 5\n"
"showpic touch_menu.tga menu -32 0 tr 32 32 togglemenu 10\n"),
*/ },
// quiturl: "/", //url to jump to when 'quitting' (otherwise uses history.back).
// arguments:["+alias","f_startup","connect","wss://theservertojoin", "-manifest","default.fmf"], //beware the scheme registration stuff (pwa+js methods).
// manifest: "index.html.fmf", // '-manifest' arg if args are not explicit. also inhibits the #foo.fmf thing.
print: function(msg)
{ //stdout...
console.log(msg);
},
printErr: function(text)
{ //stderr...
console.log(text);
},
canvas: document.getElementById('canvas'), //for webgl to attach to
setStatus: function(text)
{ //gets spammed some prints during startup. blame emscripten.
if (Module.setStatus.interval)
clearInterval(Module.setStatus.interval);
var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
var statusElement = document.getElementById('status');
var progressElement = document.getElementById('progress');
if (m) {
text = m[1];
progressElement.value = parseInt(m[2])*100;
progressElement.max = parseInt(m[4])*100;
progressElement.hidden = false;
} else {
progressElement.value = null;
progressElement.max = null;
progressElement.hidden = true;
}
statusElement.innerHTML = text;
statusElement.hidden = text.length==0;
},
// preRun: [],
totalDependencies: 0,
monitorRunDependencies: function(left)
{ //progress is progress...
this.totalDependencies = Math.max(this.totalDependencies, left);
Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
},
// onRuntimeInitialized: function(){},
postRun:
[ //each of these are called after main was run. we should have our mainloop set up now
function()
{
if (Module["sched"] === undefined)
{ //our main function failed to set up the main loop. ie: main didn't get called. panic.
alert("Unable to initialise. You may need to restart your browser. If you get this often and inconsistently, consider using a 64bit browser instead.");
Module.setStatus("Initialisation Failure");
}
}
],
};
function begin()
{
if (Module.began)
return;
Module.began = true;
document.getElementById('dropzone').hidden = true;
Added sys_openfile console command(and menu option) to web and flatpak(via cmake+dbus) builds, to 'install' packages on sandboxed systems a bit more easily. Cmake: Add FTE_WERROR option, defaults to true in debug builds and off in release builds (in case future compilers have issues). Cmake: Pull in libXscreensaver so we don't get interrupted by screensavers when playing demos. Make: Added `make webcl-rel` for a web build without server bloat (eg for sites focused on demo playback. Yes, this means you XantoM). fteqcc: Include the decompiler in fteqcc (non-gui) builds ('-d' arg). fteqcc: Decompiler can now mostly handle hexen2 mods without any unknown opcodes. Allow ezHud and OpenSSL to be compiled as in-engine plugins, potentially for web and windows ports respectively. Web: Fix support for ogg vorbis. Add support for voip. Web: Added basic support for WebXR. QTV: Don't try seeking on unseekable qtv streams. Don't spam when developer 1 is set. QTV: add support for some eztv extensions. MVD: added hack to use ktx's vweps in mvd where mvdsv doesn't bother to record the info. qwfwd: hack around a hack in qwfwd, allowing it to work again. recording: favour qwd in single player, instead of mvd. Protocol: reduce client memory used for precache names. Bump maximum precache counts - some people are just abusive, yes you Orl. hexen2: add enough clientside protocol compat to play the demo included with h2mp. lacks effects. in_xflip: restored this setting. fs_hidesyspaths: new cvar, defaults to enabled so you won't find your username or whatever turning up in screenshots or the like. change it to 0 before debuging stuff eg via 'path'. gl_overbright_models: Added cvar to match QS. netchan: Added MTU determination, we'll no longer fail to connect when routers stupidly drop icmp packets. Win: try a few other versions of xinput too. CSQC: Added a CSQC_GenerateMaterial function, to give the csqc a chance to generate custom materials. MenuQC: Added support for the skeletal objects API.
2024-04-09 17:13:59 +00:00
document.getElementById('addfile').hidden = true;
document.getElementById('begin').hidden = true;
Module.setStatus('Downloading...');
// make a script. do it the hard way for the error.
var s = document.createElement('script');
// set it up
s.setAttribute('src',"ftewebgl.js");
s.setAttribute('type',"text/javascript");
s.setAttribute('charset',"utf-8");
s.addEventListener('error', function() {alert("Oh noes! we got an error!"); Module.setStatus("Unable to download engine javascript");}, false);
// add to DOM
document.head.appendChild(s);
}
//stuff to facilitate our drag+drop filesystem support
function fixupfilepath(fname, path)
{ //we just have a filename, try to guess where to put it.
if (path != "")
return path+fname; //already has a path. use it. this allows people to drag+drop gamedirs.
var ext = fname.substr(fname.lastIndexOf('.') + 1);
if (ext == 'fmf' || ext == 'kpf') //these are the only files that really make sense in the root.
return fname;
if (ext == 'bsp' || ext == 'map' || ext == 'lit' || ext == 'lux')
return "id1/maps/" + fname; //bsps get their own extra subdir
return "id1/" + fname; //probably a pak. maybe a cfg, no idea really.
}
function remfile(fname)
{
delete Module.files[fname];
showfiles(); //repaint
}
function renamefile(fname)
{
const nname = prompt("Please enter new name", fname);
if (nname != null)
{
Module.files[nname] = Module.files[fname];
delete Module.files[fname];
showfiles();
}
}
function remcfile(fname)
{
Module['cache'].delete("/_/"+fname);
Module['cache'].keys().then((keys)=>{Module['cachekeys'] = keys; showfiles();}); //repaint
}
function remlfile(fname)
{
window.localStorage.removeItem(fname);
showfiles(); //repaint
}
function savelfile(fname)
{
window.showSaveFilePicker({id: "openfile", startIn: "documents", suggestedName: fname})
.then(async (h)=>{
let data = await window.localStorage.getitem(fname);
let f = await h.createWriteable();
await f.write(data);
await f.close();
});
}
function adduserfile()
{
window.showOpenFilePicker(
{ types:[
{
description: "Packages",
accept:{"text/*":[".pk3", ".pak", ".pk4", ".zip"]}
},
{
description: "Maps",
accept:{"text/*":[".bsp.gz", ".bsp", ".map"]}
},
{
description: "Demos",
accept:{"application/*":[".mvd.gz", ".qwd.gz", ".dem.gz", ".mvd", ".qwd", ".dem"]} //dm2?
},
{
description: "FTE Manifest",
accept:{"text/*":[".fmf"]}
},
//model formats?... nah, too many/weird. they can always
//audio formats? eww
//image formats? double eww!
{
description: "Configs",
accept:{"text/*":[".cfg", ".rc"]}
}],
excludeAcceptAllOption:false, //let em pick anything. we actually support more than listed here (and bitrot...)
id:"openfile", //remember the dir we were in for the next invocation
multiple:true
})
.then((r)=>
{
let gamedir = prompt("Please enter gamedir", "id1");
if (gamedir != "")
gamedir = gamedir+"/";
for (let i of r)
{
i.getFile().then((f)=>
{
var n = fixupfilepath(f.name, gamedir);
Module.files[n]=f.arrayBuffer(); //actually a promise...
Module.files[n].then(buf=>{Module.files[n]=buf;showfiles();}); //try and resolve it now.
});
}
}).catch((e)=>{console.log("showOpenFilePicker() aborted", e);});
}
function showfiles()
{ //print the pending file list in some pretty way
if (Module.began)
return;
Module.setStatus('');
document.getElementById('dropzone').hidden = false;
document.getElementById('begin').hidden = false;
let nt = "<H1>FTE Engine (Browser Port)</H1>";
nt = nt + "Drag gamedirs or individual package files here to make them available!<pre>";
let keys = Object.keys(Module.files);
nt += "Session Files ("+keys.length+"):<br/>";
for(let i = 0; i < keys.length; i++)
{
let rem = " <a href=\"javascript:remfile('"+keys[i]+"');\">[forget]</a>" +
" <a href=\"javascript:renamefile('"+keys[i]+"');\">[rename]</a>";
if (Module.files[keys[i]] instanceof ArrayBuffer)
{
let sz = Module.files[keys[i]].byteLength;
if (sz > 512*1024)
sz = (sz / (1024*1024)) + "mb";
else if (sz > 512)
sz = (sz / 1024) + "kb";
else
sz = (sz) + " bytes";
nt += " " + keys[i] + " ("+sz+")"+rem+"<br/>";
}
else
nt += " " + keys[i] + rem + "<br/>";
}
//cache is for large data files. for any pk3s the user might add in-engine. large stuff that's easy to fix if it gets wiped.
const cache = Module['cache'];
const ckeys = Module['cachekeys'];
if (ckeys !== undefined && ckeys.length)
{
nt += "<br/>Cached Files ("+ckeys.length+"):<br/>";
for(let r of ckeys)
{
const idx = r.url.indexOf("/_/")
if (idx < 0)
continue; //wtf? that entry should not have been in this cache object.
const fn = r.url.substr(idx+3);
let rem = " <a href=\"javascript:remcfile('"+fn+"');\">[forget]</a>";
nt += " " + fn + rem + "<br/>";
}
}
//local storage is used for slightly more persistent things, like user configs and saved games. we have quite limited storage, and this is basically text only.
try
{
const ls = window.localStorage;
if (ls && ls.length)
{
nt += "<br/>Local Files ("+ls.length+"):<br/>";
for (let i = 0; i < ls.length; i++)
{
const fn = ls.key(i);
const rem = " <a href=\"javascript:remlfile('"+fn+"');\">[forget]</a>" + (window.showSaveFilePicker!==undefined?" <a href=\"javascript:savelfile('"+fn+"');\">[export]</a>":"");
nt += " " + fn + rem + "<br/>";
}
}
}
catch(e){}
nt += "</pre>";
nt += "<p/>Cookie Disclaimer:<small> This page does not use cookies, however it does use local storage to save configs+games (consistent with natively installed games).<br/>frag-net (our matchmaking service) does not utilise any tracking beyond the session in question, but it does allow connecting to third-party servers which may incorporate ranking systems or accounts or other tracking according to that server's privacy/tracking policies.</small>"
document.getElementById('dropzone').innerHTML = nt;
}
function scanfiles(item,path)
{ //for directory drops
if (item.isFile)
{
if (path=="")
{
path = prompt("Please enter gamedir", "id1");
if (path != "")
path = path+"/";
}
item.file(function(f)
{
let n = fixupfilepath(f.name, path);
Module.files[n]=f.arrayBuffer(); //actually a promise...
Module.files[n].then(buf=>{Module.files[n]=buf;showfiles();}); //try and resolve it now.
});
}
else if (item.isDirectory)
{
// Get folder contents
var dirReader = item.createReader();
dirReader.readEntries(function(entries)
{
for (var i=0; i<entries.length; i++)
scanfiles(entries[i], path + item.name + "/");
});
}
}
function gotdrop(ev)
{ //user drag+dropped something.
ev.preventDefault();
for (var i = 0; i < ev.dataTransfer.items.length; i++)
if (ev.dataTransfer.items[i].webkitGetAsEntry)
{
var d = ev.dataTransfer.items[i].webkitGetAsEntry();
if (d)
scanfiles(d, "");
}
else if (ev.dataTransfer.items[i].kind === 'file')
{
var f = ev.dataTransfer.items[i].getAsFile();
var n = fixupfilepath(f.name, "");
Module.files[n]=f.arrayBuffer(); //actually a promise...
Module.files[n].then(buf=>{Module.files[n]=buf;showfiles();}); //try and resolve it now.
}
showfiles();
}
Added sys_openfile console command(and menu option) to web and flatpak(via cmake+dbus) builds, to 'install' packages on sandboxed systems a bit more easily. Cmake: Add FTE_WERROR option, defaults to true in debug builds and off in release builds (in case future compilers have issues). Cmake: Pull in libXscreensaver so we don't get interrupted by screensavers when playing demos. Make: Added `make webcl-rel` for a web build without server bloat (eg for sites focused on demo playback. Yes, this means you XantoM). fteqcc: Include the decompiler in fteqcc (non-gui) builds ('-d' arg). fteqcc: Decompiler can now mostly handle hexen2 mods without any unknown opcodes. Allow ezHud and OpenSSL to be compiled as in-engine plugins, potentially for web and windows ports respectively. Web: Fix support for ogg vorbis. Add support for voip. Web: Added basic support for WebXR. QTV: Don't try seeking on unseekable qtv streams. Don't spam when developer 1 is set. QTV: add support for some eztv extensions. MVD: added hack to use ktx's vweps in mvd where mvdsv doesn't bother to record the info. qwfwd: hack around a hack in qwfwd, allowing it to work again. recording: favour qwd in single player, instead of mvd. Protocol: reduce client memory used for precache names. Bump maximum precache counts - some people are just abusive, yes you Orl. hexen2: add enough clientside protocol compat to play the demo included with h2mp. lacks effects. in_xflip: restored this setting. fs_hidesyspaths: new cvar, defaults to enabled so you won't find your username or whatever turning up in screenshots or the like. change it to 0 before debuging stuff eg via 'path'. gl_overbright_models: Added cvar to match QS. netchan: Added MTU determination, we'll no longer fail to connect when routers stupidly drop icmp packets. Win: try a few other versions of xinput too. CSQC: Added a CSQC_GenerateMaterial function, to give the csqc a chance to generate custom materials. MenuQC: Added support for the skeletal objects API.
2024-04-09 17:13:59 +00:00
if (window.showOpenFilePicker)
addfile.hidden = false;
if (window.location.hash != "" || Module["autostart"])
begin(); //if the url has a #foo.fmf then just begin instantly,
else
{
try {
caches.open('user').then((c)=>{Module['cache']=c;return c.keys();}).then((keys)=>{Module['cachekeys'] = keys; showfiles();});
} catch(e){
} finally {
showfiles(); //otherwise show our lame file dropper and wait for the user to click 'go'.
}
}
</script>
</body>
</html>