"use strict"; // catch errors function installErrorHandler() { if (typeof window.onerror == "object") { window.onerror = function (msgevent, url, line, col, error) { console.log(msgevent, url, line, col); console.log(error); //$("#editor").hide(); if (window.location.host.endsWith('8bitworkshop.com')) { ga('send', 'exception', { 'exDescription': msgevent + " " + url + " " + " " + line + ":" + col + ", " + error, 'exFatal': true }); } alert(msgevent+""); }; } } function uninstallErrorHandler() { window.onerror = null; } function gotoNewLocation() { uninstallErrorHandler(); window.location = "?" + $.param(qs); } // make sure VCS doesn't start Javatari.AUTO_START = false; // 8bitworkshop IDE user interface var PRESETS; // presets array var platform_id; var platform; // platform object var originalFileID; var originalText; var toolbar = $("#controls_top"); function getBiggestItems(storage) { var items = []; for (var i = 0; i < storage.length; i++) { var key = storage.key(i); items.push([lpad(storage.getItem(key).length+"", 12), key]); } items.sort(); var s = ""; for (var i=items.length-5; i/ prefix var files = []; for (var i = 0; i < storage.length; i++) { var key = storage.key(i); if (key.startsWith(prefix + prefix2)) { var name = key.substring(prefix.length + prefix2.length); files.push(name); } } return files; } this.deleteFile = function(name) { storage.removeItem(prefix + name); storage.removeItem(prefix + 'local/' + name); } } var SourceFile = function(lines, text) { lines = lines || []; this.text = text; this.offset2line = {}; this.line2offset = {}; for (var info of lines) { if (info.offset >= 0) { this.offset2line[info.offset] = info.line; this.line2offset[info.line] = info.offset; } } this.findLineForOffset = function(PC) { if (this.offset2line) { for (var i=0; i<16; i++) { var line = this.offset2line[PC]; if (line >= 0) { return line; } PC--; } } return 0; } this.lineCount = function() { return this.line2offset.length; } } var TOOL_TO_SOURCE_STYLE = { 'dasm': '6502', 'acme': '6502', 'cc65': 'text/x-csrc', 'ca65': '6502', 'z80asm': 'z80', 'sdasz80': 'z80', 'sdcc': 'text/x-csrc', } var worker = new Worker("./src/worker/workermain.js"); var main_editor; var current_output; var current_preset_index = -1; var current_preset_id; var assemblyfile; var sourcefile; var symbolmap; var addr2symbol; var compparams; var trace_pending_at_pc; var store; var pendingWorkerMessages = 0; var editor; var disasmview = CodeMirror(document.getElementById('disassembly'), { mode: 'z80', theme: 'cobalt', tabSize: 8, readOnly: true, styleActiveLine: true }); scrollProfileView(disasmview); var memorylist; var profilelist; function scrollProfileView(_ed) { _ed.on('scroll', function(ed, changeobj) { if (profilelist) { profilelist.container.scrollTop = ed.getScrollInfo().top; } }); } function newEditor(mode) { var isAsm = (mode != 'text/x-csrc'); editor = CodeMirror(document.getElementById('editor'), { theme: 'mbo', lineNumbers: true, matchBrackets: true, tabSize: 8, indentAuto: true, gutters: isAsm ? ["CodeMirror-linenumbers", "gutter-offset", "gutter-bytes", "gutter-clock", "gutter-info"] : ["CodeMirror-linenumbers", "gutter-offset", "gutter-info"], }); var timer; editor.on('changes', function(ed, changeobj) { clearTimeout(timer); timer = setTimeout(function() { setCode(editor.getValue()); }, 200); }); scrollProfileView(editor); editor.setOption("mode", mode); } function getCurrentPresetTitle() { if (current_preset_index < 0) return "ROM"; else return PRESETS[current_preset_index].title || PRESETS[current_preset_index].name || "ROM"; } function setLastPreset(id) { if (platform_id != 'base_z80') { // TODO localStorage.setItem("__lastplatform", platform_id); localStorage.setItem("__lastid_"+platform_id, id); } } function updatePreset(current_preset_id, text) { if (text.trim().length && (originalFileID != current_preset_id || text != originalText)) { store.saveFile(current_preset_id, text); } } function loadCode(text, fileid) { var tool = platform.getToolForFilename(fileid); main_editor = newEditor(tool && TOOL_TO_SOURCE_STYLE[tool]); editor.setValue(text); // calls setCode() editor.clearHistory(); current_output = null; setLastPreset(fileid); originalFileID = fileid; originalText = text; } function loadFile(fileid, filename, index) { current_preset_id = fileid; current_preset_index = index; var text = store.loadFile(fileid) || ""; if (text) { loadCode(text, fileid); } else if (!text && index >= 0) { if (filename.indexOf('.') <= 0) filename += ".a"; console.log("Loading preset", fileid, filename, index, PRESETS[index]); if (text.length == 0) { console.log("Fetching", filename); $.get( filename, function( text ) { console.log("GET",text.length,'bytes'); loadCode(text, fileid); }, 'text') .fail(function() { alert("Could not load preset " + fileid); loadCode("", fileid); }); } } else { var ext = platform.getToolForFilename(fileid); $.get( "presets/"+platform_id+"/skeleton."+ext, function( text ) { loadCode(text, fileid); }, 'text') .fail(function() { alert("Could not load skeleton for " + platform_id + "/" + ext); loadCode("", fileid); }); } } function loadPreset(preset_id) { // TODO var index = parseInt(preset_id+""); for (var i=0; i= 0) { // load the preset loadFile(preset_id, "presets/" + platform_id + "/" + PRESETS[index].id, index); } else { // no preset found? load local loadFile(preset_id, "local/" + platform_id + "/" + preset_id, -1); } } function gotoPresetAt(index) { var index = (index + PRESETS.length) % PRESETS.length; qs['file'] = PRESETS[index].id; gotoNewLocation(); } function gotoPresetNamed(id) { qs['platform'] = platform_id; qs['file'] = id; gotoNewLocation(); } function _createNewFile(e) { var filename = prompt("Create New File", "newfile" + platform.getDefaultExtension()); if (filename && filename.length) { if (filename.indexOf(".") < 0) { filename += platform.getDefaultExtension(); } qs['file'] = "local/" + filename; gotoNewLocation(); } return true; } function getCurrentFilename() { var toks = current_preset_id.split("/"); return toks[toks.length-1]; } function _shareFile(e) { if (current_output == null) { alert("Please fix errors before sharing."); return true; } var github = new Octokat(); var files = {}; var text = editor.getValue(); files[getCurrentFilename()] = {"content": text}; var gistdata = { "description": '8bitworkshop.com {"platform":"' + platform_id + '"}', "public": true, "files": files }; var gist = github.gists.create(gistdata).done(function(val) { var url = "http://8bitworkshop.com/?sharekey=" + val.id; window.prompt("Copy link to clipboard (Ctrl+C, Enter)", url); }).fail(function(err) { alert("Error sharing file: " + err.message); }); return true; } function _resetPreset(e) { if (current_preset_index < 0) { alert("Can only reset built-in file examples.") } else if (confirm("Reset '" + PRESETS[current_preset_index].name + "' to default?")) { qs['reset'] = '1'; gotoNewLocation(); } return true; } function _downloadROMImage(e) { if (current_output == null) { alert("Please fix errors before downloading ROM."); return true; } var blob = new Blob([current_output], {type: "application/octet-stream"}); saveAs(blob, getCurrentFilename()+".rom"); } function populateExamples(sel) { sel.append($("