Last active
October 24, 2016 20:56
-
-
Save kirjavascript/999422d40d8ee3817e85 to your computer and use it in GitHub Desktop.
Sonic Disassembly Opcode Frequency
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<meta charset="utf-8"> | |
<head><title>sonic.asm</title></head> | |
<body> | |
<div class="input"> | |
<input type="button" value="Sonic 1" onclick="update(s1, 'Sonic 1')" /> | |
<input type="button" value="Sonic 2" onclick="update(s2, 'Sonic 2')" /> | |
<input type="button" value="Sonic 3&K" onclick="update(s3, 'Sonic 3&K')" /> | |
</div> | |
</body> | |
<style> | |
.label { | |
font: 14px sans-serif | |
} | |
.axis text { | |
font: 12px sans-serif; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: #000; | |
shape-rendering: crispEdges; | |
} | |
</style> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script> | |
<script> | |
/* | |
created by snkenjoi/kirjava/colourful/cake | |
*/ | |
window.addEventListener("load", function() { | |
update(s1, "Sonic 1"); | |
}); | |
// config array for width/height/margin | |
var c = { | |
w: 1200, | |
h: 800, | |
m: 40 | |
} | |
// setup svg and set viewbox based on w/h/margins | |
var s = d3.select("body").append("svg") | |
.attr("width",c.w).attr("height",c.h) | |
.attr("viewBox",[-c.m,-c.m,c.w+(c.m*2),c.h+(c.m*2)].join(" ")) | |
// adjust scale if viewBox modification breaks stuff | |
.style("transform", "scale(1.1)") | |
.style("transform-origin", "0 0") | |
// for bg and grid | |
var bg = s.append("g") | |
// create bar container layer to get appended before the axis | |
var g = s.append("g"); | |
// axis container | |
var axis = s.append("g") | |
// calculate linear (numeric) scale for y (qty) axis | |
var y = d3.scale.linear() | |
.range([c.h, 0]); | |
// calculate ordinal (non-numeric) scale for x (data.name) axis | |
// ordinal scales require discrete datapoints, so we use .map to | |
// create the correct array for domain and rangebands for range | |
var x = d3.scale.ordinal() | |
// rangeRoundBands produces ints vs rangeBands | |
// second param is padding | |
.rangeRoundBands([0, c.w], .2) | |
var xAxis = d3.svg.axis().scale(x) | |
.orient("bottom") | |
var yAxis = d3.svg.axis().scale(y) | |
.orient("left").ticks(20) | |
// background | |
bg | |
.append("rect") | |
.style("fill", "#666") | |
.attr("width", c.w) | |
.attr("height", c.h) | |
// prepare x axis | |
axis | |
.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + c.h + ")") | |
//.call(xAxis) | |
// label | |
s | |
.append("text") | |
.attr("y", -20) | |
.attr("x", c.w) | |
.attr("dy", ".71em") | |
.attr("class", "label") | |
.style("text-anchor", "end") | |
.style("font-weight", "bold") | |
// prepare y axis | |
axis | |
.append("g") | |
.attr("class", "y axis") | |
function update(data, dataname) { | |
// update domains | |
y.domain([0, d3.max(data, function(d){return d.qty})]) | |
x.domain(data.map(function(d){return d.opcode})) | |
grid(bg) | |
// update selection | |
u = s.transition() | |
// update axis label | |
u.select(".label") | |
.text("Frequency of processor opcodes in "+dataname) | |
// update x axis | |
u.select(".x.axis") // change the x axis | |
.duration(750) | |
.call(xAxis) | |
.selectAll("text") | |
.style("text-anchor", "end") | |
.attr("dx", "-.8em") | |
.attr("dy", ".15em") | |
.attr("transform", function(d) { | |
return "rotate(-45)" | |
}) | |
u.select(".y.axis") // change the y axis | |
.duration(750) | |
.call(yAxis); | |
// save reference to databind | |
bars = g | |
.selectAll(".bars") | |
// the second function passed to data defines the data key for data prone to shifting positions | |
.data(data, function(d) {return d.opcode}) | |
// enter // | |
bars | |
.enter() | |
.append("rect") | |
.attr("class","bars") | |
.style("fill", "steelblue") | |
.style("stroke", '#FFF') | |
.style("stroke-width", "1px") | |
// update // | |
d3.transition(bars) | |
.transition() | |
.duration(500) | |
.ease("quad") | |
// stagger animation | |
.delay(function(d,i){return i*40}) | |
// set height based on data | |
.attr("height", function(d){return y(0)-y(d.qty)}) | |
// set y position to data value | |
.attr("y", function(d){return y(d.qty)}) | |
.attr("width", x.rangeBand()) | |
.attr("x", function(d,i) { return x(d.opcode)}) | |
// exit // | |
d3.transition(bars.exit()) | |
.style("fill-opacity", 0) | |
.remove(); | |
} | |
function grid(container) { | |
var grid = container.selectAll("line.hgrid") | |
.data(y.ticks(20)) | |
grid | |
.enter() | |
.append("line") | |
.attr("class","hgrid") | |
.attr("x1",0) | |
.attr("x2",c.w) | |
.attr("y1",function(d){ return y(d)}) | |
.attr("y2",function(d){ return y(d)}) | |
.attr("stroke","#444") | |
//.attr('stroke-width','20') | |
.attr('stroke-linecap','round') | |
.attr('stroke-dasharray','1,2') | |
d3.transition(grid) | |
.transition() | |
.duration(500) | |
.ease("quad") | |
.attr("x", function(d,i) { return x(d.opcode)}) | |
.attr("y1",function(d){ return y(d)}) | |
.attr("y2",function(d){ return y(d)}) | |
d3.transition(grid.exit()) | |
.style("fill-opacity", 0) | |
.remove(); | |
return grid; | |
} | |
// data was produced from the drx/Stealth disassemblies with this; | |
// c={};require("fs").readFileSync("s1.asm","utf-8").split("\n").forEach(function | |
// (d){d=d.match(/\s([A-Za-z]+)(\s|.)/);if(d&&c[d[1]])c[d[1]]++;else if(d)c[d[1]] | |
// =1});l={};for(ke in c){if(c[ke]>7*8)l[ke]=c[ke]}console.log(JSON.stringify(l)) | |
var _s1 = {"bra":703,"tst":770,"bne":865,"lea":834,"move":7642,"andi":540,"beq":786,"moveq":1230,"movea":298,"add":639,"dbf":292,"btst":320,"cmpi":798,"cmp":221,"bcc":273,"bsr":917,"jsr":522,"rts":967,"addq":707,"addi":266,"bcs":283,"subq":451,"clr":321,"lsl":131,"sub":496,"adda":116,"asl":78,"lsr":128,"ext":140,"jmp":292,"bmi":190,"bpl":408,"swap":78,"neg":238,"bhi":91,"subi":221,"bset":206,"bclr":185,"asr":80,}; | |
var _s2 = {"nop":94,"bra":1709,"tst":1323,"bne":1668,"lea":1920,"movem":134,"move":15588,"andi":1042,"beq":1831,"moveq":2206,"movea":542,"add":1348,"dbf":452,"btst":693,"cmpi":1478,"cmp":478,"bcc":497,"bsr":2578,"jsr":511,"jmp":975,"addq":1422,"subq":794,"rts":1737,"bcs":476,"S":285,"bge":77,"addi":710,"blt":152,"eori":77,"subi":383,"bgt":92,"lsr":281,"clr":529,"ori":215,"lsl":197,"or":130,"sub":720,"bpl":520,"swap":337,"adda":150,"asl":125,"ext":216,"bmi":388,"neg":495,"bhi":124,"bchg":58,"bset":353,"bclr":346,"st":68,"muls":69,"asr":188}; | |
var _s3 = | |
{"lea":5893,"tst":3835,"bne":4509,"movem":351,"move":36167,"andi":2040,"beq":4511,"moveq":4968,"movea":1786,"add":3151,"dbf":814,"btst":2121,"bra":2278,"cmp":1308,"jmp":3560,"bsr":2427,"S":1565,"cmpi":3519,"rts":4338,"jsr":6930,"addq":2037,"subq":1673,"clr":2011,"eori":82,"bcc":1350,"bclr":1147,"ori":348,"subi":755,"bcs":1278,"sub":2529,"adda":265,"addi":1723,"swap":726,"lsl":485,"or":159,"not":62,"and":231,"bpl":1488,"bhi":317,"cmpa":69,"lsr":526,"asl":134,"ext":393,"bmi":916,"neg":1234,"divu":70,"bchg":117,"bls":201,"blt":181,"asr":557,"bset":1405,"muls":162,"bgt":105,"st":398,"ble":75,"bge":146,"mulu":57,"ds":326}; | |
function o2oa(b){a=[];for(k in b)a.push({"opcode":k,"qty":b[k]});return a}; | |
var s1 = o2oa(_s1); | |
var s2 = o2oa(_s2); | |
var s3 = o2oa(_s3); | |
</script> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment