Merge branch 'master' of github.com:sehugg/8bitworkshop
This commit is contained in:
commit
4a8380b730
4
Makefile
4
Makefile
|
@ -21,3 +21,7 @@ archive:
|
|||
git archive --prefix 8bitworkshop- -o release/8bitworkshop-tools.zip HEAD tools
|
||||
|
||||
|
||||
web:
|
||||
ifconfig | grep inet
|
||||
python2 -m SimpleHTTPServer 2>> http.out
|
||||
|
||||
|
|
27
css/ui.css
27
css/ui.css
|
@ -60,14 +60,6 @@ div.editor {
|
|||
line-height:1.25;
|
||||
font-size:12pt;
|
||||
}
|
||||
div.emulator {
|
||||
position:absolute;
|
||||
left:50%;
|
||||
top:0;
|
||||
width:50%;
|
||||
background-color: #666;
|
||||
margin-top: 20px auto 0;
|
||||
}
|
||||
div.debugwindow {
|
||||
position:absolute;
|
||||
left:50%;
|
||||
|
@ -98,6 +90,9 @@ div.mem_info {
|
|||
margin-left:8px;
|
||||
background-color: #666;
|
||||
}
|
||||
.btn_label {
|
||||
color: #ccc;
|
||||
}
|
||||
.btn_group.debug_group {
|
||||
}
|
||||
.btn_group.view_group {
|
||||
|
@ -189,22 +184,30 @@ a.dropdown-toggle {
|
|||
-moz-border-radius:6px 0 6px 6px;
|
||||
border-radius:6px 0 6px 6px;
|
||||
}
|
||||
div.emulator {
|
||||
position:absolute;
|
||||
left:50%;
|
||||
top:0;
|
||||
width:50%;
|
||||
background-color: #666;
|
||||
margin-top: 20px auto 0;
|
||||
height:100%;
|
||||
}
|
||||
.emubevel {
|
||||
width:100%;
|
||||
height:100%;
|
||||
padding:4%;
|
||||
padding:5%;
|
||||
background:#333;
|
||||
}
|
||||
.emuvideo {
|
||||
border-radius:20px;
|
||||
border: 4px solid #222;
|
||||
padding: 30px;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
background: #000;
|
||||
outline-color: #666;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
canvas.pixelated {
|
||||
image-rendering: optimizeSpeed; /* Older versions of FF */
|
||||
|
|
17
index.html
17
index.html
|
@ -39,10 +39,11 @@ ga('send', 'pageview');
|
|||
☰ <span class="caret"></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton">
|
||||
<li><a class="dropdown-item" href="#" id="item_new_file">New File...</a></li>
|
||||
<li><a class="dropdown-item" href="#" id="item_new_file">New File...</a></li>
|
||||
<li><a class="dropdown-item" href="#" id="item_share_file">Share File as GitHub Gist...</a></li>
|
||||
<li><a class="dropdown-item" href="#" id="item_reset_file">Revert to Original...</a></li>
|
||||
<li><a class="dropdown-item" href="#" id="item_download_rom">Download ROM Image...</a></li>
|
||||
<li><a class="dropdown-item" href="#" id="item_download_file">Download File</a></li>
|
||||
<li><a class="dropdown-item" href="#" id="item_download_rom">Download ROM Image</a></li>
|
||||
<li><a class="dropdown-item" href="#" id="item_record_video">Record Video...</a></li>
|
||||
<li class="dropdown dropdown-submenu">
|
||||
<a tabindex="-1" href="#">Debug</a>
|
||||
|
@ -50,6 +51,12 @@ ga('send', 'pageview');
|
|||
<li><a class="dropdown-item" href="#" id="item_debug_expr">Break Expression...</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown dropdown-submenu">
|
||||
<a tabindex="-1" href="#">Options</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><i id="item_low_power_check" style="display:hidden" class="fa fa-check"></i><a class="dropdown-item" href="#" id="item_low_power">Low Power Mode</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<hr>
|
||||
<li class="dropdown dropdown-submenu">
|
||||
<a tabindex="-1" href="#">Platform</a>
|
||||
|
@ -82,7 +89,7 @@ ga('send', 'pageview');
|
|||
<span class="btn_group view_group" id="speed_bar" style="display:none">
|
||||
<button id="dbg_slowest" type="submit" title="Slowest"><span class="glyphicon glyphicon-fast-backward" aria-hidden="true"></span></button>
|
||||
<button id="dbg_slower" type="submit" title="Slower"><span class="glyphicon glyphicon-backward" aria-hidden="true"></span></button>
|
||||
<span id="fps_label">60.00</span> fps
|
||||
<span class="label"><span id="fps_label">60.00</span> fps</span>
|
||||
<button id="dbg_faster" type="submit" title="Faster"><span class="glyphicon glyphicon-forward" aria-hidden="true"></span></button>
|
||||
<button id="dbg_fastest" type="submit" title="Faster"><span class="glyphicon glyphicon-fast-forward" aria-hidden="true"></span></button>
|
||||
</span>
|
||||
|
@ -126,7 +133,7 @@ ga('send', 'pageview');
|
|||
</div>
|
||||
</div>
|
||||
<div class="emulator" id="emulator">
|
||||
<div style="margin:10px">
|
||||
<div id="javatari-div" style="margin:10px; display:none">
|
||||
<div id="javatari-screen" style="margin: 0 auto; box-shadow: 2px 2px 10px rgb(60, 60, 60);"></div>
|
||||
<div id="javatari-console-panel" style="margin: 0 auto; box-shadow: 2px 2px 10px rgb(60, 60, 60);"></div>
|
||||
</div>
|
||||
|
@ -224,8 +231,10 @@ ga('send', 'pageview');
|
|||
</script>
|
||||
|
||||
<script>
|
||||
/*
|
||||
var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
|
||||
if (!isFirefox && platform_id != 'vcs') { $("#best_in_firefox").show(); }
|
||||
*/
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
mov ax,@$4ffe
|
||||
mov dx,@ClearTiles
|
||||
jsr dx
|
||||
mov dx,@ClearSprites
|
||||
jsr dx
|
||||
mov ex,@ClearSprites
|
||||
jsr ex
|
||||
reset
|
||||
InitPageTable:
|
||||
mov ax,@$6000 ; screen buffer
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
|
||||
.include "hvsync_generator.v"
|
||||
.include "font_cp437_8x8.v"
|
||||
.include "ram.v"
|
||||
.include "tile_renderer.v"
|
||||
.include "sprite_scanline_renderer.v"
|
||||
.include "lfsr.v"
|
||||
.include "sound_generator.v"
|
||||
.include "cpu16.v"
|
||||
.include "cpu_platform.v"
|
||||
.module cpu_platform
|
||||
|
||||
.arch femto16
|
||||
.org 0x8000
|
||||
.len 1024
|
||||
|
||||
jmp Start
|
||||
|
||||
Start:
|
||||
mov sp,@$6fff
|
||||
mov fx,@InitPageTable
|
||||
jsr fx
|
||||
mov ax,@$1ffe
|
||||
mov fx,@ClearTiles
|
||||
; jsr ex
|
||||
mov fx,@DrawMaze
|
||||
jsr fx
|
||||
mov bx,@HelloWorld
|
||||
mov cx,@$1f00
|
||||
mov dx,@$6001
|
||||
mov fx,@WriteString
|
||||
jsr fx
|
||||
mov fx,@ClearSprites
|
||||
jsr fx
|
||||
reset
|
||||
WriteString:
|
||||
mov ax,[bx]
|
||||
bz StringDone
|
||||
xor ax,cx
|
||||
mov [dx],ax
|
||||
inc bx
|
||||
inc dx
|
||||
jmp WriteString
|
||||
StringDone:
|
||||
rts
|
||||
|
||||
DrawMaze:
|
||||
mov dx,@$6040
|
||||
mov bx,@MazeData
|
||||
DrawMazeLoop:
|
||||
mov ax,[bx]
|
||||
inc bx
|
||||
mov fx,#4
|
||||
ShiftMazeChar:
|
||||
; rotate high 4 bits to low 4 bits
|
||||
asl ax
|
||||
rol ax
|
||||
rol ax
|
||||
rol ax
|
||||
mov ex,ax
|
||||
and ax,#7
|
||||
adc ax,ex
|
||||
; lookup character in table
|
||||
mov ex,ax
|
||||
and ex,#$f
|
||||
add ex,@MazeChars
|
||||
mov ex,[ex]
|
||||
or ex,@$1e00
|
||||
; store to video buffer
|
||||
mov [dx],ex
|
||||
inc dx
|
||||
dec fx
|
||||
bnz ShiftMazeChar
|
||||
mov ax,dx
|
||||
sub ax,@$6340
|
||||
bnz DrawMazeLoop
|
||||
rts
|
||||
|
||||
InitPageTable:
|
||||
mov ax,@$6000 ; screen buffer
|
||||
mov bx,@$7e00 ; page table start
|
||||
mov cx,#32 ; 32 rows
|
||||
InitPTLoop:
|
||||
mov [bx],ax
|
||||
add ax,#32
|
||||
inc bx
|
||||
dec cx
|
||||
bnz InitPTLoop
|
||||
rts
|
||||
ClearTiles:
|
||||
mov bx,@$6000
|
||||
mov cx,@$3c0
|
||||
ClearLoop:
|
||||
mov [bx],ax
|
||||
inc bx
|
||||
dec cx
|
||||
bnz ClearLoop
|
||||
rts
|
||||
ClearSprites:
|
||||
mov bx,@$7f00
|
||||
mov ax,#0
|
||||
mov cx,#$40
|
||||
ClearSLoop:
|
||||
mov ax,[bx]
|
||||
add ax,@$101
|
||||
mov [bx],ax
|
||||
inc bx
|
||||
dec cx
|
||||
bnz ClearSLoop
|
||||
|
||||
HelloWorld:
|
||||
.string HELLO WORLD
|
||||
.data 0
|
||||
|
||||
MazeData:
|
||||
.data $3111 $1111 $1111 $1114 $3111 $1111 $1111 $1114
|
||||
.data $2000 $0000 $0000 $0002 $2000 $0000 $0000 $0002
|
||||
.data $2031 $1114 $0311 $1402 $2031 $1140 $0311 $1402
|
||||
.data $2051 $1116 $0511 $1605 $6051 $1160 $0511 $1602
|
||||
.data $2000 $0000 $0000 $0000 $0000 $0000 $0000 $0002
|
||||
.data $2031 $1114 $0340 $3111 $1114 $0340 $0311 $1402
|
||||
.data $2051 $1116 $0220 $5114 $3116 $0220 $0511 $1602
|
||||
.data $2000 $0000 $0220 $0002 $2000 $0220 $0000 $0002
|
||||
.data $5111 $1114 $0251 $1402 $2031 $1620 $3111 $1116
|
||||
.data $3111 $1116 $0231 $1605 $6051 $1420 $5111 $1114
|
||||
.data $2000 $0000 $0220 $0000 $0000 $0220 $0000 $0002
|
||||
.data $2031 $1114 $0220 $3111 $1114 $0220 $0311 $1402
|
||||
.data $2051 $1116 $0560 $2ccc $ccc2 $0560 $0511 $1602
|
||||
.data $2000 $0000 $0000 $2ccc $ccc2 $0000 $0000 $0002
|
||||
.data $5111 $1114 $0340 $2ccc $ccc2 $0340 $0311 $1116
|
||||
.data $3111 $1116 $0220 $5111 $1116 $0220 $0511 $1114
|
||||
.data $2000 $0000 $0220 $0000 $0000 $0220 $0000 $0002
|
||||
.data $2031 $1114 $0251 $1403 $4031 $1620 $0311 $1402
|
||||
.data $2051 $1116 $0511 $1605 $6051 $1160 $0511 $1602
|
||||
.data $2000 $0000 $0000 $0000 $0000 $0000 $0000 $0002
|
||||
.data $2031 $1114 $0311 $1403 $4031 $1140 $0311 $1402
|
||||
.data $2051 $1116 $0511 $1602 $2051 $1160 $0511 $1602
|
||||
.data $2000 $0000 $0000 $0002 $2000 $0000 $0000 $0002
|
||||
.data $5111 $1111 $1111 $1116 $5111 $1111 $1111 $1116
|
||||
|
||||
MazeChars:
|
||||
.data $f9 ; empty
|
||||
.data $c4 $b3 ; horizvert
|
||||
.data $da $bf $c0 $d9 ; corners
|
||||
.data $c3 $c1 $c2 $b4 ; 3-way
|
||||
.data $c5 ; 4-way
|
||||
.data $20 ; empty (no dot)
|
||||
|
||||
.data 123 $123
|
||||
.align $10
|
||||
|
|
@ -44,6 +44,7 @@ var VCSPlatform = function() {
|
|||
this.getPresets = function() { return VCS_PRESETS; }
|
||||
|
||||
this.start = function() {
|
||||
$("#javatari-div").show();
|
||||
Javatari.start();
|
||||
}
|
||||
|
||||
|
|
|
@ -372,6 +372,11 @@ function _downloadROMImage(e) {
|
|||
saveAs(blob, getCurrentFilename()+".rom");
|
||||
}
|
||||
|
||||
function _downloadSourceFile(e) {
|
||||
var blob = new Blob([editor.getValue()], {type: "text/plain;charset=utf-8"});
|
||||
saveAs(blob, getCurrentFilename());
|
||||
}
|
||||
|
||||
function populateExamples(sel) {
|
||||
sel.append($("<option />").text("--------- Examples ---------").attr('disabled',true));
|
||||
for (var i=0; i<PRESETS.length; i++) {
|
||||
|
@ -1312,6 +1317,7 @@ function setupDebugControls(){
|
|||
else
|
||||
$("#item_debug_expr").hide();
|
||||
$("#item_download_rom").click(_downloadROMImage);
|
||||
$("#item_download_file").click(_downloadSourceFile);
|
||||
$("#item_record_video").click(_recordVideo);
|
||||
if (platform.setFrameRate && platform.getFrameRate) {
|
||||
$("#speed_bar").show();
|
||||
|
|
|
@ -110,6 +110,39 @@ var Assembler = function(spec) {
|
|||
outwords[ip++ - origin] = (op >> (nb-1-i)*width) & ((1<<width)-1);
|
||||
}
|
||||
}
|
||||
function addWords(data) {
|
||||
asmlines.push({
|
||||
line:linenum,
|
||||
offset:ip,
|
||||
nbits:width*data.length
|
||||
});
|
||||
for (var i=0; i<data.length; i++) {
|
||||
outwords[ip++ - origin] = data[i];
|
||||
}
|
||||
}
|
||||
|
||||
function parseData(toks) {
|
||||
var data = [];
|
||||
for (var i=0; i<toks.length; i++) {
|
||||
data[i] = parseConst(toks[i]);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function stringToData(s) {
|
||||
var data = [];
|
||||
for (var i=0; i<s.length; i++) {
|
||||
data[i] = s.charCodeAt(i);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function alignIP(align) {
|
||||
if (align < 1 || align > codelen)
|
||||
fatal("Invalid alignment value");
|
||||
else
|
||||
ip = Math.floor((ip+align-1)/align)*align;
|
||||
}
|
||||
|
||||
function parseConst(s, nbits) {
|
||||
// TODO: check bit length
|
||||
|
@ -124,24 +157,30 @@ var Assembler = function(spec) {
|
|||
self.buildInstruction = function(rule, m) {
|
||||
var opcode = 0;
|
||||
var oplen = 0;
|
||||
// iterate over each component of the rule output ("bits")
|
||||
for (var i=0; i<rule.bits.length; i++) {
|
||||
var b = rule.bits[i];
|
||||
var n,x;
|
||||
// is a string? then it's a bit constant
|
||||
// TODO
|
||||
if (b.length) {
|
||||
n = b.length;
|
||||
x = parseInt(b,2);
|
||||
} else {
|
||||
// it's an indexed variable, look up its variable
|
||||
var id = m[b+1];
|
||||
var v = spec.vars[rule.varlist[b]];
|
||||
if (!v) {
|
||||
return {error:"Could not find matching identifier for '" + m[0] + "'"};
|
||||
}
|
||||
n = v.bits;
|
||||
// is it an enumerated type? look up the index of its keyword
|
||||
if (v.toks) {
|
||||
x = v.toks.indexOf(id);
|
||||
if (x < 0)
|
||||
return null;
|
||||
} else {
|
||||
// otherwise, parse it as a constant
|
||||
x = parseConst(id, n);
|
||||
// is it a label? add fixup
|
||||
if (isNaN(x)) {
|
||||
|
@ -158,14 +197,16 @@ var Assembler = function(spec) {
|
|||
}
|
||||
if (oplen == 0)
|
||||
warning("Opcode had zero length");
|
||||
else if (oplen > 32)
|
||||
warning("Opcodes > 32 bits not supported");
|
||||
else if ((oplen % width) != 0)
|
||||
warning("Opcode was not word-aligned (" + oplen + " bits)");
|
||||
return {opcode:opcode, nbits:oplen};
|
||||
}
|
||||
|
||||
self.loadArch = function(arch) {
|
||||
if (self.loadFile) {
|
||||
var json = self.loadFile(arch + ".json");
|
||||
if (self.loadJSON) {
|
||||
var json = self.loadJSON(arch + ".json");
|
||||
if (json && json.vars && json.rules) {
|
||||
spec = json;
|
||||
preprocessRules();
|
||||
|
@ -176,20 +217,27 @@ var Assembler = function(spec) {
|
|||
}
|
||||
|
||||
function parseDirective(tokens) {
|
||||
if (tokens[0] == '.define')
|
||||
symbols[tokens[1]] = {value:tokens[2]};
|
||||
else if (tokens[0] == '.org')
|
||||
var cmd = tokens[0].toLowerCase();
|
||||
if (cmd == '.define')
|
||||
symbols[tokens[1].toLowerCase()] = {value:tokens[2]};
|
||||
else if (cmd == '.org')
|
||||
ip = origin = parseInt(tokens[1]);
|
||||
else if (tokens[0] == '.len')
|
||||
else if (cmd == '.len')
|
||||
codelen = parseInt(tokens[1]);
|
||||
else if (tokens[0] == '.width')
|
||||
else if (cmd == '.width')
|
||||
width = parseInt(tokens[1]);
|
||||
else if (tokens[0] == '.arch')
|
||||
else if (cmd == '.arch')
|
||||
fatalIf(self.loadArch(tokens[1]));
|
||||
else if (tokens[0] == '.include')
|
||||
else if (cmd == '.include')
|
||||
fatalIf(self.loadInclude(tokens[1]));
|
||||
else if (tokens[0] == '.module')
|
||||
else if (cmd == '.module')
|
||||
fatalIf(self.loadModule(tokens[1]));
|
||||
else if (cmd == '.data')
|
||||
addWords(parseData(tokens.slice(1)));
|
||||
else if (cmd == '.string')
|
||||
addWords(stringToData(tokens.slice(1).join(' ')));
|
||||
else if (cmd == '.align')
|
||||
alignIP(parseConst(tokens[1]));
|
||||
else
|
||||
warning("Unrecognized directive: " + tokens);
|
||||
}
|
||||
|
@ -197,14 +245,15 @@ var Assembler = function(spec) {
|
|||
self.assemble = function(line) {
|
||||
linenum++;
|
||||
// remove comments
|
||||
line = line.replace(/[;].*/g, '');
|
||||
line = line.trim().toLowerCase();
|
||||
line = line.replace(/[;].*/g, '').trim();
|
||||
// is it a directive?
|
||||
if (line[0] == '.') {
|
||||
var tokens = line.split(/\s+/);
|
||||
parseDirective(tokens);
|
||||
return;
|
||||
}
|
||||
// make it lowercase
|
||||
line = line.toLowerCase();
|
||||
// find labels
|
||||
line = line.replace(/(\w+):/, function(_label, label) {
|
||||
symbols[label] = {value:ip};
|
||||
|
@ -274,7 +323,12 @@ var Assembler = function(spec) {
|
|||
self.assembleFile = function(text) {
|
||||
var lines = text.split(/\n/g);
|
||||
for (var i=0; i<lines.length && !aborted; i++) {
|
||||
self.assemble(lines[i]);
|
||||
try {
|
||||
self.assemble(lines[i]);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
fatal("Exception during assembly: " + e);
|
||||
}
|
||||
}
|
||||
return self.finish();
|
||||
}
|
||||
|
@ -292,13 +346,16 @@ if (typeof module !== 'undefined' && require.main === module) {
|
|||
var stdinBuffer = fs.readFileSync(0);
|
||||
var code = stdinBuffer.toString();
|
||||
var asm = new Assembler();
|
||||
asm.loadFile = function(filename) {
|
||||
return fs.readFileSync(filename, 'utf8');
|
||||
asm.loadJSON = function(filename) {
|
||||
return JSON.parse(fs.readFileSync(filename, 'utf8'));
|
||||
};
|
||||
asm.loadInclude = function(filename) {
|
||||
filename = filename.substr(1, filename.length-2); // remove quotes
|
||||
//return fs.readFileSync(filename, 'utf8');
|
||||
};
|
||||
asm.loadModule = function(top_module) {
|
||||
//TODO
|
||||
};
|
||||
var out = asm.assembleFile(code);
|
||||
if (out.errors) {
|
||||
console.log(out.errors);
|
||||
} else {
|
||||
console.log(out.outwords);
|
||||
}
|
||||
console.log(out);
|
||||
}
|
||||
|
|
|
@ -1126,7 +1126,7 @@ function compileJSASM(asmcode, platform, options, is_inline) {
|
|||
load("assembler");
|
||||
var asm = new Assembler();
|
||||
var includes = [];
|
||||
asm.loadFile = function(filename) {
|
||||
asm.loadJSON = function(filename) {
|
||||
// TODO: what if it comes from dependencies?
|
||||
var path = '../../presets/' + platform + '/' + filename;
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
|
Loading…
Reference in New Issue