Upload
norbertkehrer
View
284
Download
3
Tags:
Embed Size (px)
Citation preview
Translating Classic Arcade Gamesto JavaScript
Norbert Kehrer
vienna.js Meetup, June 24, 2015
Automatic Program Translation Is Exciting Objective: exact conversion of the original
The traditional way: emulators
Interesting alternative: static binary translation (static recompilation)
Examples: Asteroids (1979), Astro Fighter (1980), Centipede (1981)
Translating 6502 to JavaScript
Emulation vs. Recompilation of „Asteroids“
The Source: the 6502 The Target: JavaScript „Naive“ Translation Patterns Code Optimization and the Exciting
Journey into Compiler Theory
The Asteroids Arcade Machine is Based on the 6502 Processor
Program ROM6800–7fff
Work RAM0000–02ff
Vector ROM5000–57ff
Vector RAM4000–47ff
6502 DVG
Game Logic Video Hardware
Traditional Emulation of the Hardware ...
Program ROM6800–7fff
Work RAM0000–02ff
Vector ROM5000–57ff
Vector RAM4000–47ff
6502 DVG
Emulator inJavaScript
... or Translating the Game Program to JavaScript, …
Program ROM6800–7fff
Work RAM0000–02ff
Vector ROM5000–57ff
Vector RAM4000–47ff
6502 DVG
JavaScript
Emulator inJavaScript
… and by that Create a Stand-Alone Application
Program ROM6800–7fff
Work RAM0000–02ff
Vector ROM5000–57ff
Vector RAM4000–47ff
6502 DVG
JavaScript
Emulator inJavaScript
Translating 6502 to JavaScript
Emulation vs. Recompilation of „Asteroids“
The Source: the 6502 The Target: JavaScript „Naive“ Translation Patterns Code Optimization and the Exciting
Journey into Compiler Theory
The 6502 was a Popular Microprocessor in the 1980s
The 6502 Is Simple and Has Only a Few Registers
Accumulator (A)
X Register (X)
Y Register (Y)
Program Counter (PC)
Flags: NV-BDIZC
00000001 Stack Pointer (S)
0000-00ff: Zero Page
0100-01ff: Stack
0200-ffff: Program
Registers Memory
The 6502 Instructions Can Have Three Formats
Op Code
Op CodePara-meter
Op CodeAddress
LowAddress
High
$a9 $03 … lda #3
$8d $07 $19 … sta $1907
$0a … asl
Some Instruction Examples
lda #1 Load accu with 1 sta 1000 Store accu in 1000 inx Add 1 to X adc #7 Add 7 to the accu jmp 3000 Jump to 3000 beq 2000 Conditional branch,
if Z (zero) flag is set
Translating 6502 to JavaScript
Emulation vs. Recompilation of „Asteroids“
The Source: the 6502 The Target: JavaScript „Naive“ Translation Patterns Code Optimization and the Exciting
Journey into Compiler Theory
JavaScript is the Target
Variables and arrays Assignments and arithmetics if (cond) { stmt1 } else { stmt2 }; switch (var) {
case a: stmt1; break;case b: stmt2; break;case c: stmt3; break;…
};
Translating 6502 to JavaScript
Emulation vs. Recompilation of „Asteroids“
The Source: the 6502 The Target: JavaScript „Naive“ Translation Patterns Code Optimization and the Exciting
Journey into Compiler Theory
First, Write a Disassembler …
…6834: A2 44 ldx #$446836: A9 02 lda #$026838: 85 02 sta $02683A: 86 03 stx $03…
…A2 44A9 0285 0286 03…
Program ROM(from Asteroids)
Disassembler listing
Then, Make a Code Generator Out of It
…… ldx #$44 x=44;… lda #$02 a=2;… sta $02 mem[2]=a;… stx $03 mem[3]=x;…
…A2 44A9 0285 0286 03…
Program ROM(from Asteroids)
JavaScript code instead of disassembler listing
6502 Registers and Memory Become Variables and ArraysAccumulator
X register
Y register
C flag
N flag
…
Memory
var a;
var x;
var y;
var c;
var n;
var mem = new Array(65536);
„Normal“ Instructions Are Easy to Translatelda 1000
sta 1001
inc 1000
ldx #10
sta 2000,x
inx
a = mem[1000];
mem[1001] = a;
mem[1000] =
(mem[1000]+1)&0xff;
x = 10;
mem[2000+x] = a;
x = (x+1) & 0xff;
„GOTO Considered Harmful“ Considered Harmful…
1000: ldx #0 ; x = 0
1002: inx ; x = x + 1
1003: stx $d020 ; x screen color
1006: jmp 1002 ; go to 1002
…
But, JavaScript has no (real) GOTO !
An Old „Fortran to C“ Trick
pc = 1000;while (true) {
switch (pc) {
case 1000: x = 0; //ldx
case 1002: x = (x+1) & 0xff; //inx case 1003: mem[0xd020] = x; //stx
case 1006: pc = 1002; break; //jmp
…
};};
Case Labels Are Only Needed For Jump Targetspc = 1000;while (true) {
switch (pc) {
case 1000: x = 0; //ldx
case 1002: x = (x+1) & 0xff; //inx case 1003: mem[0xd020] = x; //stx
case 1006: pc = 1002; break; //jmp
…
};};
Conditional Branches Become“If” Statements
…
if (z === 1) { // beq 3000
pc = 3000;
break;
};
…
case 3000:…
Dr. Sheldon Cooper‘s „Fun with Flags“ Many 6502 instructions set flags as their
side effect Example:
lda 1000 if zero Z=1 else Z=0
if neg. N=1 else N=0
beq 4711
…
Instructions Need Additional Flag Calculation Code
lda 1000
lda 1000
a = mem[1000];
a = mem[1000];
if (a==0) z=1; else z=0;
if (a<0) n=1; else n=0;
Resulting programs are correct but big
Translating 6502 to JavaScript
Emulation vs. Recompilation of „Asteroids“
The Source: the 6502 The Target: JavaScript „Naive“ Translation Patterns Code Optimization and the Exciting
Journey into Compiler Theory
Flag Calculations Are Often Redundant …
lda 1000 a = mem[1000];
if (a==0) z=1; else z=0;
if (a<0) n=1; else n=0;
ldx 1200 x = mem[1200];
if (x==0) z=1; else z=0;
if (x<0) n=1; else n=0;
beq 4711 if (z==1) …
Flag Calculations Are Often Redundant …
lda 1000 a = mem[1000];
if (a==0) z=1; else z=0;
if (a<0) n=1; else n=0;
ldx 1200 x = mem[1200];
if (x==0) z=1; else z=0;
if (x<0) n=1; else n=0;
beq 4711 if (z==1) …
?:
yes:
… But Not Always
lda 1000 a = mem[1000];
if (a==0) z=1; else z=0;
if (a<0) n=1; else n=0;
ldx 1200 x = mem[1200];
if (x==0) z=1; else z=0;
if (x<0) n=1; else n=0;
beq 4711 if (z==1) …
Redundant Code Elimination Is Difficult and Interesting „Liveness analysis“ problem Solution with fixpoint iteration, or more elegantly
with Datalog programs Many exciting further directions:
More optimizations (combinations, high-level structure detection,…)
LLVMasm.jsDatalog, Logic Programming, …
Summary: From Asteroids to Liveness Analysis Browser-playable „Asteroids“ as an
example 6502 Processor Translating 6502 code to JavaScript Optimizing: Redundant Code Elimination
Thank you!
http://members.aon.at/nkehrer/