diff --git a/css/ui.css b/css/ui.css
index f3ca98bf..d64b7cd3 100644
--- a/css/ui.css
+++ b/css/ui.css
@@ -48,13 +48,13 @@
left:0;
right:0;
background-color: #666;
- overflow: hidden;;
+ overflow: hidden;
}
-div.workspace {
- background-color:#999;
+#workspace {
+ background-color:#333;
+ width:50%;
}
div.editor {
- width:50%;
line-height:1.25;
font-size:12pt;
}
@@ -182,6 +182,8 @@ a.dropdown-toggle {
border-radius:6px 0 6px 6px;
}
.emubevel {
+ width:100%;
+ height:100%;
padding:4%;
background:#333;
}
@@ -204,3 +206,13 @@ canvas.pixelated {
image-rendering: pixelated; /* Awesome future-browsers */
-ms-interpolation-mode: nearest-neighbor; /* IE */
}
+.palbtn {
+ width:2em;
+ height:2em;
+ border-style:none;
+}
+.selected {
+ border-width:2px;
+ border-color:white;
+ border-style:dotted;
+}
diff --git a/index.html b/index.html
index e2253e89..7e38bf5d 100644
--- a/index.html
+++ b/index.html
@@ -7,6 +7,21 @@ body {
overflow: hidden !important;
font-size: 11px;
}
+.pixeditback {
+ position:absolute;
+ z-index:100;
+ width:100%;
+ height:100%;
+ padding:50px;
+ border-width:4px;
+ border-color:#333;
+ border-style:solid;
+ background-color:rgba(64, 64, 64, 0.5);
+}
+#pixeditframe {
+ width:100%;
+ height:100%;
+}
@@ -61,6 +76,9 @@ body {
+
+
+
Note: Works best in Firefox
-
-
-
-
-
-
-
What would you like to start programming?
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
diff --git a/pixels.html b/pixels.html
new file mode 100644
index 00000000..23aa56e8
--- /dev/null
+++ b/pixels.html
@@ -0,0 +1,71 @@
+
+
+
+
8bitworkshop Pixel Editor
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/presets/williams-z80/game1.c b/presets/williams-z80/game1.c
index 4fdfba51..518a0a39 100644
--- a/presets/williams-z80/game1.c
+++ b/presets/williams-z80/game1.c
@@ -63,7 +63,6 @@ struct {
//
void main();
-void _sdcc_heap_init(void); // for malloc()
// start routine @ 0x0
// set stack pointer, enable interrupts
@@ -79,7 +78,6 @@ __asm
LDIR
__endasm;
- _sdcc_heap_init();
main();
}
diff --git a/src/emu.js b/src/emu.js
index 8c9c3cd8..65982aa2 100644
--- a/src/emu.js
+++ b/src/emu.js
@@ -11,8 +11,6 @@ function noise() {
function __createCanvas(mainElement, width, height) {
// TODO
var fsElement = document.createElement('div');
- fsElement.style.position = "relative";
- fsElement.style.overflow = "hidden";
fsElement.classList.add("emubevel");
var canvas = document.createElement('canvas');
diff --git a/src/pixed/pixeleditor.js b/src/pixed/pixeleditor.js
new file mode 100644
index 00000000..3ddfee0e
--- /dev/null
+++ b/src/pixed/pixeleditor.js
@@ -0,0 +1,304 @@
+"use strict";
+
+function PixelEditor(parentDiv, width, height, palette, initialData) {
+
+ function createCanvas() {
+ var c = document.createElement('canvas');
+ c.width = width;
+ c.height = height;
+ c.classList.add("pixels");
+ c.classList.add("pixelated");
+ //canvas.tabIndex = "-1"; // Make it focusable
+ $(parentDiv).empty().append(c);
+ return c;
+ }
+
+ function updateImage() {
+ ctx.putImageData(pixdata, 0, 0);
+ }
+
+ function fitCanvas() {
+ var w = $(parentDiv).width();
+ var h = $(parentDiv).height();
+ pixcanvas.style.height = Math.floor(h)+"px";
+ // TODO
+ }
+ this.resize = fitCanvas;
+
+ palette = new Uint32Array(palette);
+ var pixcanvas = createCanvas();
+ var ctx = pixcanvas.getContext('2d');
+ var pixdata = ctx.createImageData(pixcanvas.width, pixcanvas.height);
+ var pixints = new Uint32Array(pixdata.data.buffer);
+ for (var i=0; i
> 0) & 0xff) << 16;
+ y |= ((x >> 8) & 0xff) << 8;
+ y |= ((x >> 16) & 0xff) << 0;
+ return y;
+ }
+
+ function createPaletteButtons() {
+ var span = $("#palette_group").empty();
+ for (var i=0; i');
+ var rgb = palette[i] & 0xffffff;
+ var color = "#" + hex(revrgb(rgb), 6);
+ btn.click(setCurrentColor.bind(this, i));
+ btn.attr('id', 'palcol_' + i);
+ btn.css('backgroundColor', color).text(i.toString(16));
+ if ((rgb & 0x808080) != 0x808080) { btn.css('color', 'white'); }
+ span.append(btn);
+ }
+ setCurrentColor(1);
+ }
+
+ function getPixelByOffset(ofs) {
+ var oldrgba = pixints[ofs];
+ for (var i=0; i= 0)
+ $("#palcol_" + curpalcol).removeClass('selected');
+ curpalcol = col;
+ $("#palcol_" + col).addClass('selected');
+ }
+ }
+ this.setCurrentColor = setCurrentColor;
+
+ var curpalcol = -1;
+ setCurrentColor(1);
+
+ var dragcol = 1;
+ var dragging = false;
+
+ var pxls = $(pixcanvas);
+ pxls.mousedown(function(e) {
+ var pos = getPositionFromEvent(e);
+ dragcol = getPixel(pos.x, pos.y) == curpalcol ? 0 : curpalcol;
+ setPixel(pos.x, pos.y, curpalcol);
+ dragging = true;
+ })
+ .mousemove(function(e) {
+ var pos = getPositionFromEvent(e);
+ if (dragging) {
+ setPixel(pos.x, pos.y, dragcol);
+ }
+ })
+ .mouseup(function(e) {
+ var pos = getPositionFromEvent(e);
+ setPixel(pos.x, pos.y, dragcol);
+ dragging = false;
+ });
+
+ this.getImageColors = function() {
+ var pixcols = new Uint8Array(pixints.length);
+ for (var i=0; i>(8-shift-fmt.bpp) : byte>>shift) & mask) << (p*fmt.bpp);
+ }
+ imgdata.push(color);
+ shift += fmt.bpp;
+ if (shift >= 8) {
+ ofs += 1;
+ shift = 0;
+ }
+ }
+ }
+ images.push(imgdata);
+ }
+ return images;
+}
+
+function convertImagesToBytes(images, fmt) {
+ var count = fmt.count ? fmt.count : 1;
+ var width = fmt.w;
+ var height = fmt.h;
+ var bytesperline = fmt.sl ? fmt.sl : Math.ceil(fmt.w * fmt.bpp / 8);
+ var mask = (1 << fmt.bpp)-1;
+ var nplanes = fmt.np ? fmt.np : 1;
+ var i = 0;
+ var bytes = new Uint8Array(bytesperline * height * nplanes * count);
+ for (var n=0; n>(8-shift-fmt.bpp) : byte>>shift) & mask) << (p*fmt.bpp);
+ */
+ }
+ shift += fmt.bpp;
+ if (shift >= 8) {
+ ofs += 1;
+ shift = 0;
+ }
+ }
+ }
+ }
+ return bytes;
+}
+
+function convertPaletteBytes(arr,r0,r1,g0,g1,b0,b1) {
+ var result = [];
+ for (var i=0; i> r0) & ((1<> g0) & ((1<> b0) & ((1<= 0)
+ palette = convertPaletteBytes(palbytes, 0, rr, rr, gg, rr+gg, bb);
+ else
+ palette = convertPaletteBytes(palbytes, rr+gg, bb, rr, gg, 0, rr);
+ }
+ currentPixelEditor = new PixelEditor(maineditor, e.data.fmt.w, e.data.fmt.h, palette, allimages[0]);
+}
+
+function postToParentWindow(data) {
+ if (data.save) {
+ allimages[0] = currentPixelEditor.getImageColors();
+ data.bytes = convertImagesToBytes(allimages, currentFormat);
+ data.bytestr = replaceHexBytes(currentByteStr, data.bytes);
+ }
+ parentSource.postMessage(data, "*");
+}
+
+function pixelEditorResize(e) {
+ if (currentPixelEditor) {
+ currentPixelEditor.resize();
+ }
+}
+
+function pixelEditorKeypress(e) {
+ if (!currentPixelEditor) return;
+ var c = e.charCode;
+ if (c >= 48 && c <= 57) {
+ currentPixelEditor.setCurrentColor(c-48);
+ } else if (c >= 97 && c <= 102) {
+ currentPixelEditor.setCurrentColor(c-97+10);
+ }
+}
diff --git a/src/ui.js b/src/ui.js
index 131916fe..1b063cd7 100644
--- a/src/ui.js
+++ b/src/ui.js
@@ -390,6 +390,7 @@ function invertMap(m) {
}
function setCompileOutput(data) {
+ // TODO: kills current selection
sourcefile = new SourceFile(data.lines);
if (data.asmlines) {
assemblyfile = new SourceFile(data.asmlines, data.intermediate.listing);
@@ -1006,6 +1007,61 @@ function toggleProfileWindow() {
}
}
+function handleWindowMessage(e) {
+ console.log("window message", e.data);
+ if (e.data.bytes) {
+ editor.replaceSelection(e.data.bytestr);
+ }
+ if (e.data.close) {
+ $("#pixeditback").hide(250);
+ }
+}
+
+function openBitmapEditorWithParams(fmt, bytestr, palfmt, palstr) {
+ $("#pixeditback").show(250);
+ pixeditframe.contentWindow.postMessage({fmt:fmt, bytestr:bytestr, palfmt:palfmt, palstr:palstr}, '*');
+}
+
+function lookBackwardsForJSONComment(line) {
+ var re = /[/][*]([{].+[}])[*][/]/;
+ while (--line >= 0) {
+ var s = editor.getLine(line);
+ var m = re.exec(s);
+ if (m) {
+ var jsontxt = m[1].replace(/([A-Za-z]+):/g, '"$1":'); // fix lenient JSON
+ var obj = JSON.parse(jsontxt);
+ var start = {obj:obj, line:line, ch:s.indexOf(m[0])+m[0].length};
+ line--;
+ while (++line < editor.lineCount()) {
+ if (editor.getLine(line).indexOf(';') >= 0) {
+ var end = {line:line, ch:editor.getLine(line).length};
+ return {obj:obj, start:start, end:end};
+ }
+ }
+ }
+ }
+}
+
+function openBitmapEditorAtCursor() {
+ if ($("#pixeditback").is(":visible")) {
+ $("#pixeditback").hide(250);
+ return;
+ }
+ var data = lookBackwardsForJSONComment(getCurrentLine());
+ if (data && data.obj && data.obj.w>0 && data.obj.h>0 && data.obj.bpp>0) {
+ var paldata = lookBackwardsForJSONComment(data.start.line-1);
+ var palbytestr;
+ if (paldata) {
+ palbytestr = editor.getRange(paldata.start, paldata.end);
+ paldata = paldata.obj;
+ }
+ editor.setSelection(data.end, data.start);
+ openBitmapEditorWithParams(data.obj, editor.getSelection(), paldata, palbytestr);
+ } else {
+ alert("No bitmap spec found in format /*{w:,h:,bpp:,count:...}*/");
+ }
+}
+
function setupDebugControls(){
$("#dbg_reset").click(resetAndDebug);
$("#dbg_pause").click(pause);
@@ -1027,6 +1083,7 @@ function setupDebugControls(){
$("#dbg_disasm").click(toggleDisassembly).show();
}
$("#disassembly").hide();
+ $("#dbg_bitmap").click(openBitmapEditorAtCursor);
$(".dropdown-menu").collapse({toggle: false});
$("#item_new_file").click(_createNewFile);
$("#item_share_file").click(_shareFile);
@@ -1076,7 +1133,6 @@ function showWelcomeMessage() {
tour.init();
setTimeout(function() { tour.start(); }, 2000);
}
- if (qs['redir']) delete qs['redir'];
}
///////////////////////////////////////////////////
@@ -1155,7 +1211,6 @@ function startPlatform() {
// try to load last file (redirect)
var lastid = localStorage.getItem("__lastid_"+platform_id) || localStorage.getItem("__lastid");
localStorage.removeItem("__lastid");
- qs['redir'] = '1';
gotoPresetNamed(lastid || PRESETS[0].id);
return false;
}
@@ -1186,6 +1241,7 @@ function loadSharedFile(sharekey) {
// start
function startUI(loadplatform) {
installErrorHandler();
+ window.addEventListener("message", handleWindowMessage, false);
// add default platform?
platform_id = qs['platform'] || localStorage.getItem("__lastplatform");
if (!platform_id) {