Sei sulla pagina 1di 20

LOGIN

HOME

ABOUT

ARTICLES

DOWNLOADS

EVENTS

FEATURED

PROJECTS

RESEARCHPROJECTS

Subscribe RSS|Email

MULTIGESTURE.NET
AmultitouchandHCIresearchblog

PUBLICATIONS

Subscribe

Twitter

LinkedIn

Youtube

HomeArticlesHowtowriteanemulator(CHIP8interpreter)

Search
Search

Howtowriteanemulator(CHIP8
interpreter)
Thisguideisintendedtogiveabriefintroductiontotheworldofemulationandwillalsoteach
youhowtowriteoneyourselffromscratch.
PersonallyIhavebeenexcitedaboutemulatorssincethelate90s.AsIdidntownaconsole
backinthedays(onlyhadaC64),IwaspleasantlysurprisedwhenIlearnedthatyoucoulduse
anemulatortorunconsolegamesonthePC.IstillrememberplayingSuperMario3onthePC
usingaSNES/SuperFamicomemulatorSnes9xandafewyearslatercompletingMetalGear
SolidusingBleem!(PSXemulator).

About
I'mLaurenceMuller(M.Sc.)

,aformerFellowofthe

Scientists'DiscoveryRoomLab(SDRLab)atHarvard
University/SchoolofEngineeringandAppliedSciences
(SEAS),whereIworkedoninnovativescientificsoftware
formultitouchdevicesanddisplaywallsystems.
I'malsothefounderofEpicWindmill,asoftwarecompany
thatdevelopsappsandgamesformobiledevices.

ThesedayshoweverImmorefocussedonprovidingsupporttoemulatorprojectsofrecent
consolessuchas:PCSX2(SonyPlaystation2),Dolphinemu(NintendoGamecubeandWii)
andnullDC(SegaDreamcast).
Whilethisguideexpectsyoutohavesomebasicknowledgeofcomputersystemsandassumes
youknowaprogramlanguage,itshouldalsobeaninterestingreadforpeoplewhoare
interestedinemulationingeneral.

Twitter
RT@teh_skmpNewblogpost.
blog.nillware.com/post/148787
About3monthsagofromLaurenceMuller'sTwitter

#defineemulator
Ithinkitsimportanttofirstunderstandwhatanemulatorisandisnt.

Follow@LaurenceMuller

303followers

Anemulatorisacomputerprogramthatmimicstheinternaldesignandfunctionalityofa
computersystem(SystemA).Itallowsuserstorunsoftwaredesignedforthisspecificsystem
(SytemA)onatotallydifferentcomputersystemorarchitecture(SystemB).

Randomquotes
Friend:someonewholikesyouevenaftertheyknow

Oftenpeopleconfuseasimulatorwithanemulatorandviceversa.Justrememberthatthese

you.

wordsarentsynonyms.
Letstakealookatthefollowingexample:
Pongisa2DtennisgamewhichwasdevelopedbyAtariandranontheirownhardware.
However,thegamewasntjustavailableonAtarisystems,butalsoonrivalplatformssuchas
Amstrad,AmigaandtheC64.
SincenoteveryPonggamewaslicensedbyAtaritorunontheseplatforms,italsomeantthat
noteverygamewasrunningthecodefromAtari.Basicallywhathappenedisthatpeople
createdtheirownimplementation(clones)ofthegamePong.Inthiscasetheysimulatedthe
looksandgamebehaviorofPong.
Incaseofanemulator,wechoosenottoreimplementthegamePongforournativesystem.
Instead,werecreatetheenvironmentwithacomputerprogramwhichallowsustorunthe

HCIConferences
ACMTabletop2010(Saarbrucken,Germany)
ACMTabletop2011(Japan)
ACMTabletop2012(Cambridge,MA,USA)
CHI2009(Boston,MA,USA)
CHI2010(Atlanta,GA,USA)
CHI2011(Vancouver,BC,CA)
CHI2012(Austin,TX,USA)
IDC2009(SanJose,CA,USA)
IEEETabletop2008(Amsterdam,NL)
IEEETabletop2009(Banff,Canada)
SuperComputing2008(Austin,TX,USA)

originalmachinecodeofPong.AbenefitofthisisthatitwontjustallowustorunPong,butalso

TEI2010(Cambridge,MA,USA)

anyotherapplicationdevelopedforthatplatform.

TEI2011(Funchal,Portugal)

Multitouch
DavidWallin(whitenoise)
HarryvanderVeen(gravano)
JimiHertz
JohannesHirche(xwolf)
JoshuaBlake

WhatisaCHIP8?
TheChip8actuallyneverwasarealsystem,butmorelikeavirtualmachine(VM)developedin
the70sbyJosephWeisbecker.GameswrittenintheChip8languagecouldeasilyrunon
systemsthathadaChip8interpreter.

WhystartwithaCHIP8emulator?
WritingaChip8emulatorisprobablytheeasiestemulationprojectyoucanundertake.Dueto
smallnumberofopcodes(35intotalforChip8)andthefactthatalotofinstructionsareusedin
moreadvancedCPUs,aprojectlikethisiseducational(getabetterunderstandingofhowthe
CPUworksandhowmachinecodeisexecuted),manageable(smallnumberofopcodesto
implement)andnottootimeconsuming(projectcanbefinishedinafewdays).

JustinIreland
LynnMarentette
MathieuVirbel(Tito)
PaulDIntino(Fairlane)
RalphDas
RichardMonsonHaefel(clevermonkey)
SebastianHartman
SethSandler(cerupcat)
SharathPatali
SOCOAmsterdam
TahaBintahir
ThomasHansen
TimRoth
Touchlib

Multitouch(commercial)
AppleiPad
AppleiPhone
MERLDiamondTouch
MSSurface
PerceptivePixel

Beforeyoustart
Pickaprogramminglanguageyourefamiliarwith(C/C++orJavaarecommon).
TheexamplesbelowwilluseC/C++
Dontusethisprojectasawaytolearnhowtoprogram.
(Ifbitwiseoperationsconfuseyou,studythemfirst)
Youwillprobablyneedtouse3rdpartylibrariestohandleaudio/videooutputand
userinput(GLUT/SDL/DirectX)
OKGO!

Science
Dr.C.Shen
Dr.R.G.Belleman
HarvardSEAS
HarvardUniversitySDRLab
Prof.PeterSloot
ScientificVisualizationandVirtualRealityResearch
Group
UniversiteitvanAmsterdam

Archive

Category

August2012(1)

Android

April2012(1)

Application

February2012(2)

BlackBerry

November2011(1)

Blogroll

Whenyoustartwritinganemulator,itisimportantthatyoufindasmuchinformationaspossible

March2011(1)

Featured

aboutthesystemyouwanttoemulate.Trytofindouthowmuchmemoryandregistersareused

December2010(4)

Howto

inthesystem,whatarchitectureitisusingandseeifyoucangetholdoftechnicaldocuments

November2010(2)

Infovis

thatdescribetheinstructionset.

April2010(2)

Multitouch

CPUSpecifications

February2010(1)
InthecaseoftheChip8,IwouldrecommendtakingalookattheChip8descriptionon

December2009(1)

Wikipedia.

August2009(1)
July2009(3)

IllgiveyouabriefoverviewoftheChip8systemandsomehintsonhowtoimplementthe

February2009(1)

essentialparts:

December2008(1)
November2008(1)
September2008(2)

TheChip8has35opcodeswhicharealltwobyteslong.Tostorethecurrent

July2008(1)

opcode,weneedadatatypethatallowsustostoretwobytes.Anunsignedshort

May2008(3)

hasthelengthoftwobytesandthereforfitsourneeds:

March2008(1)
February2008(1)

unsignedshortopcode;

January2008(1)
November2007(2)

TheChip8has4Kmemoryintotal,whichwecanemulatedas:

September2007(5)
July2007(1)

unsignedcharmemory[4096];

June2007(1)
May2007(5)

CPUregisters:TheChip8has158bitgeneralpurposeregistersnamedV0,V1up
toVE.The16thregisterisusedforthecarryflag.Eightbitsisonebytesowecan
useanunsignedcharforthispurpose:
unsignedcharV[16];
ThereisanIndexregisterIandaprogramcounter(pc)whichcanhaveavalue
from 0x000 to 0xFFF
unsignedshortI;
unsignedshortpc;
Thesystemsmemorymap:
0x0000x1FFChip8interpreter(containsfontsetinemu)
0x0500x0A0Usedforthebuiltin4x5pixelfontset(0F)
0x2000xFFFProgramROMandworkRAM
Thegraphicssystem:Thechip8hasoneinstructionthatdrawsspritetothescreen.
DrawingisdoneinXORmodeandifapixelisturnedoffasaresultofdrawing,the
VFregisterisset.Thisisusedforcollisiondetection.
ThegraphicsoftheChip8areblackandwhiteandthescreenhasatotalof2048
pixels(64x32).Thiscaneasilybeimplementedusinganarraythatholdthepixel
state(1or0):
unsignedchargfx[64*32];
Interuptsandhardwareregisters.TheChip8hasnone,buttherearetwotimer
registersthatcountat60Hz.Whensetabovezerotheywillcountdowntozero.
unsignedchardelay_timer;
unsignedcharsound_timer;
Thesystemsbuzzersoundswheneverthesoundtimerreacheszero.
ItisimportanttoknowthattheChip8instructionsethasopcodesthatallowtheprogramtojump
toacertainaddressorcallasubroutine.Whilethespecificationdontmentionastack,youwill
needtoimplementoneaspartoftheinterpreteryourself.Thestackisusedtorememberthe
currentlocationbeforeajumpisperformed.Soanytimeyouperformajumporcallasubroutine,
storetheprogramcounterinthestackbeforeproceeding.Thesystemhas16levelsofstackand
inordertorememberwhichlevelofthestackisused,youneedtoimplementastackpointer
(sp).

unsignedshortstack[16];
unsignedshortsp;
Finally,theChip8hasaHEXbasedkeypad( 0x00xF ),youcanuseanarraytostorethe
currentstateofthekey.

unsignedcharkey[16];

GameLoop
Togiveyouanideaonhowtodesignyouremulator,Imadeasmallexampleofalayout.Itdoes
notteachyouhowtouseGLUTorSDLtohandlegraphicsandinputbutmerelyshowsyouhow
theflowofyouremulatorshouldbe.

April2007(3)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

#include
#include//OpenGLgraphicsandinput
#include"chip8.h"//Yourcpucoreimplementation

chip8myChip8;

intmain(intargc,char**argv)
{
//Setuprendersystemandregisterinputcallbacks
setupGraphics();
setupInput();

//InitializetheChip8systemandloadthegameintothememory
myChip8.initialize();
myChip8.loadGame("pong");

//Emulationloop
for(;;)
{
//Emulateonecycle
myChip8.emulateCycle();

//Ifthedrawflagisset,updatethescreen
if(myChip8.drawFlag)
drawGraphics();

//Storekeypressstate(PressandRelease)
myChip8.setKeys();
}

return0;
}

Line35:Inthisexampleweassumeyouwillcreateaseparateclasstohandlethe
opcodes.
Line1011:Setupthegraphics(windowsize,displaymode,etc)andinputsystem
(bindcallbacks)
Line14:Clearthememory,registersandscreen
Line15:Copytheprogramintothememory
Line21:Emulateonecycleofthesystem
Line24:Becausethesystemdoesnotdraweverycycle,weshouldsetadrawflag
whenweneedtoupdateourscreen.Onlytwoopcodesshouldsetthisflag:
0x00E0 Clearsthescreen
0xDXYN Drawsaspriteonthescreen
Line28:Ifwepressorreleaseakey,weshouldstorethisstateinthepartthat
emulatesthekeypad

Emulationcycle
Nextwewilllookintotheemulationcycle.
voidchip8::initialize()
{
//Initializeregistersandmemoryonce
}

voidchip8::emulateCycle()
{
//FetchOpcode
//DecodeOpcode
//ExecuteOpcode

//Updatetimers
}
Everycycle,themethodemulateCycleiscalledwhichemulatesonecycleoftheChip8CPU.
Duringthiscycle,theemulatorwillFetch,DecodeandExecuteoneopcode.
Fetchopcode
Duringthisstep,thesystemwillfetchoneopcodefromthememoryatthelocationspecifiedby
theprogramcounter(pc).InourChip8emulator,dataisstoredinanarrayinwhicheach
addresscontainsonebyte.Asoneopcodeis2byteslong,wewillneedtofetchtwosuccessive
bytesandmergethemtogettheactualopcode.
Todemonstratehowthisworkswewillbeusingopcode 0xA2F0 .

//Assumethefollowing:
memory[pc]==0xA2
memory[pc+1]==0xF0
Inordertomergebothbytesandstoretheminan unsignedshort (2bytesdatatype)wewill
usethebitwiseORoperation:
opcode=memory[pc]<<8|memory[pc+1];
Sowhatdidactuallyhappen?
Firstweshifted 0xA2 left8bits,whichadds8zeros.
0xA20xA2<<8=0xA200HEX
101000101010001000000000BIN
NextweusethebitwiseORoperationtomergethem:
1010001000000000|//0xA200
11110000=//0xF0(0x00F0)

1010001011110000//0xA2F0
Decodeopcode
Aswehavestoredourcurrentopcode,weneedtodecodetheopcodeandchecktheopcode
tabletoseewhatitmeans.Wewillcontinuewiththesameopcode:
0xA2F0//Assembly:mvi2F0h
Ifwetakealookattheopcodetable,ittellsusthefollowing:
ANNN:SetsItotheaddressNNN
WewillneedtosetindexregisterItothevalueofNNN(0x2F0).
Executeopcode
Nowthatweknowwhattodowiththeopcode,wecanexecutetheopcodeinouremulator.For
ourexampleinstruction 0xA2F0 itmeansthatweneedtostorethevalue 0x2F0 intoindex
registerI.Asonly12bitsarecontainingthevalueweneedtostore,weuseabitwiseAND
operator(&)togetridofthefirstfourbits(nibble):
1010001011110000&//0xA2F0(opcode)
0000111111111111=//0x0FFF

0000001011110000//0x02F0(0x2F0)
Resultingcode:
I=opcode&0x0FFF;
pc+=2;
Becauseeveryinstructionis2byteslong,weneedtoincrementtheprogramcounterbytwo
aftereveryexecutedopcode.Thisistrueunlessyoujumptoacertainaddressinthememoryor
ifyoucallasubroutine(inwhichcaseyouneedtostoretheprogramcounterinthestack).Ifthe
nextopcodeshouldbeskipped,increasetheprogramcounterbyfour.
Timers
Besidesexecutingopcodes,theChip8alsohastwotimersyouwillneedtoimplement.As
mentionedabove,bothtimers(delaytimerandsoundtimer)countdowntozeroiftheyhave
beensettoavaluelargerthanzero.Sincethesetimerscountdownat60Hz,youmightwantto
implementsomethingthatslowsdownyouremulationcycle(Execute60opcodesinone
second).

Gettingstarted
Nowthatyouknowthebasicsofemulationandhowthesystemworks,itistimetoputallpieces
togetherandstartcodingtheemulator.
Initializesystem
Beforerunningthefirstemulationcycle,youwillneedtoprepareyoursystemstate.Start
clearingthememoryandresettingtheregisterstozero.WhiletheChip8doesntreallyhavea
BIOSorfirmware,itdoeshaveabasicfontsetstoredinthememory.Thisfontsetshouldbe
loadedinmemorylocation 0x50==80 andonwards.Moredetailsabouthowthefontset

workscanbefoundattheendofthisguide.
Anotherimportantthingtorememberisthatthesystemexpectstheapplicationtobeloadedat
memorylocation 0x200 .Thismeansthatyourprogramcountershouldalsobesettothis
location.
voidchip8::initialize()
{
pc=0x200;//Programcounterstartsat0x200
opcode=0;//Resetcurrentopcode

I=0;//Resetindexregister
sp=0;//Resetstackpointer

//Cleardisplay

//Clearstack
//ClearregistersV0VF
//Clearmemory

//Loadfontset
for(inti=0;i<80;++i)
memory[i]=chip8_fontset[i];

//Resettimers
}
Loadingtheprogramintothememory
Afteryouhaveinitializedtheemulator,loadtheprogramintothememory(usefopeninbinary
mode)andstartfillingthememoryatlocation: 0x200==512 .
for(inti=0;i<bufferSize;++i)
memory[i+512]=buffer[i];
Starttheemulation
Oursystemisnowreadytoexecuteitsfirstopcode.Asmentionedabove,weshouldfetch,
decodeandexecutetheopcode.Inthisexamplewestartbyreadingthefirst4bitsofthecurrent
opcodetofindoutwhattheopcodeisandwhattheemulatorneedstodo:
voidchip8::emulateCycle()
{
//Fetchopcode
opcode=memory[pc]<<8|memory[pc+1];

//Decodeopcode
switch(opcode&0xF000)
{
//Someopcodes//

case0xA000://ANNN:SetsItotheaddressNNN
//Executeopcode
I=opcode&0x0FFF;
pc+=2;
break;

//Moreopcodes//

default:
printf("Unknownopcode:0x%X\n",opcode);
}

//Updatetimers
if(delay_timer>0)
delay_timer;

if(sound_timer>0)
{
if(sound_timer==1)
printf("BEEP!\n");
sound_timer;
}
}
Insomecaseswecannotrelysolelyonthefirstfourbitstoseewhattheopcodemeans.For
example, 0x00E0 and 0x00EE bothstartwith 0x0 .Inthiscaseweaddanadditionalswitch
andcomparethelastfourbits:
//Decodeopcode
switch(opcode&0xF000)
{
case0x0000:
switch(opcode&0x000F)
{

case0x0000://0x00E0:Clearsthescreen
//Executeopcode
break;

case0x000E://0x00EE:Returnsfromsubroutine
//Executeopcode
break;

default:
printf("Unknownopcode[0x0000]:0x%X\n",opcode);
}
break;

//moreopcodes//
}

Opcodeexamples
Letstakealookatsomemoreopcodesthatmightlookdauntingatfirst.
Example1:Opcode 0x2NNN
ThisopcodecallsthesubroutineataddressNNN.Becausewewillneedtotemporaryjumpto
addressNNN,itmeansthatweshouldstorethecurrentaddressoftheprogramcounterinthe
stack.Afterstoringthevalueoftheprogramcounterinthestack,increasethestackpointerto
preventoverwritingthecurrentstack.Nowthatwehavestoredtheprogramcounter,wecanset
ittotheaddressNNN.Remember,becausewerecallingasubroutineataspecificaddress,you
shouldnotincreasetheprogramcounterbytwo.
case0x2000:
stack[sp]=pc;
++sp;
pc=opcode&0x0FFF;
break;
Example2:Opcode 0x8XY4
ThisopcodeaddsthevalueofVYtoVX.RegisterVFissetto1whenthereisacarryandsetto0
whenthereisnt.Becausetheregistercanonlystorevaluesfrom0to255(8bitvalue),itmeans
thatifthesumofVXandVYislargerthan255,itcantbestoredintheregister(oractuallyit
startscountingfrom0again).IfthesumofVXandVYislargerthan255,weusethecarryflagto
letthesystemknowthatthetotalsumofbothvalueswasindeedlargerthan255.Dontforgetto
incrementtheprogramcounterbytwoafterexecutingtheopcode.
case0x0004:
if(V[(opcode&0x00F0)>>4]>(0xFFV[(opcode&0x0F00)>>8]))
V[0xF]=1;//carry
else
V[0xF]=0;
V[(opcode&0x0F00)>>8]+=V[(opcode&0x00F0)>>4];
pc+=2;
break;
Example3:Opcode 0xFX33
StorestheBinarycodeddecimalrepresentationofVXattheaddressesI,Iplus1,andIplus2
IhavetoconfessthatIcouldnttofigureouthowtoimplementthisopcode,soIusedTJAs
solution.
case0x0033:
memory[I]=V[(opcode&0x0F00)>>8]/100;
memory[I+1]=(V[(opcode&0x0F00)>>8]/10)%10;
memory[I+2]=(V[(opcode&0x0F00)>>8]%100)%10;
pc+=2;
break;

Handlinggraphicsandinput
Drawingpixels
Theopcoderesponsiblefordrawingtoourdisplayis 0xDXYN .TheWikipediadescriptiontells
usthefollowing:
Drawsaspriteatcoordinate(VX,VY)thathasawidthof8pixelsandaheightofN
pixels.Eachrowof8pixelsisreadasbitcodedstartingfrommemorylocationII
valuedoesntchangeaftertheexecutionofthisinstruction.Asdescribedabove,VF
issetto1ifanyscreenpixelsareflippedfromsettounsetwhenthespriteisdrawn,
andto0ifthatdoesnthappen.

Asthedescriptionoftheopcodeistellingus,theChip8actuallydrawsonthescreenby
drawingsprites.Itwillgiveusthelocationofwherethespriteneedstobedrawn(theopcode
tellsuswhichVregisterweneedtochecktofetchtheXandYcoordinates)andthenumberof
rows(N).Thewidthofeachspriteisfixed(8bits/1byte).Thestateofeachpixelissetbyusing
abitwiseXORoperation.Thismeansthatitwillcomparethecurrentpixelstatewiththecurrent
valueinthememory.Ifthecurrentvalueisdifferentfromthevalueinthememory,thebitvalue
willbe1.Ifbothvaluesmatch,thebitvaluewillbe0.
01000101^
11110011=

10110110
Letsassumeittheopcodewas 0xD003 .Thismeansitwantstodrawaspriteatlocation0,0
whichis3rowshigh.AtmemorylocationI,thefollowingvalueswereset:
memory[I]=0x3C;
memory[I+1]=0xC3;
memory[I+2]=0xFF;
Howdothese3bytesrepresentasprite?Takealookatthebinaryvaluesofeachbyte:
HEXBINSprite
0x3C00111100****
0xC311000011****
0xFF11111111********
Youshouldusethebinaryrepresentationtofillyourarray( gfx[] ).However,beforesettingthe
valuein gfx[] usingtheXORoperator,youwillalsoneedtocheckifanyofthepixels
changedfrom1to0.Ifthisisthecase,youshouldsettheVFregisterto1(Thisisbasicallyatest
forcollisiondetection).
Exampleoftheimplementationofopcode 0xDXYN
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

case0xD000:

{
unsignedshortx=V[(opcode&0x0F00)>>8];
unsignedshorty=V[(opcode&0x00F0)>>4];
unsignedshortheight=opcode&0x000F;
unsignedshortpixel;

V[0xF]=0;
for(intyline=0;yline<height;yline++)
{
pixel=memory[I+yline];
for(intxline=0;xline<8;xline++)
{
if((pixel&(0x80>>xline))!=0)
{
if(gfx[(x+xline+((y+yline)*64))]==1)
V[0xF]=1;
gfx[x+xline+((y+yline)*64)]^=1;
}
}
}

drawFlag=true;
pc+=2;
}
break;

Line34:Fetchthepositionandheightofthesprite
Line5:Pixelvalue
Line8:ResetregisterVF
Line9:Loopovereachrow
Line11:FetchthepixelvaluefromthememorystartingatlocationI
Line12:Loopover8bitsofonerow
Line14:Checkifthecurrentevaluatedpixelissetto1(notethat 0x80>>xline
scanthroughthebyte,onebitatthetime)
Line1617:Checkifthepixelonthedisplayissetto1.Ifitisset,weneedto
registerthecollisionbysettingtheVFregister
Line18:SetthepixelvaluebyusingXOR
Line23:Wechangedour gfx[] arrayandthusneedtoupdatethescreen.
Line24:Updatetheprogramcountertomovetothenextopcode

Input
TheChip8systemusesasimpleHEXkeypadthatallowsuserstointeractwiththesystem.For
ouremulatorthismeansweneedtoimplementamethodthatwillsetthestateofeachkeyinthe
variablethathandlesthekeystates.Everycycleyoushouldcheckthekeyinputstateandstore
itin key[] .
Itactuallydoesntmatterwhatvalueyoustore,becauseopcode 0xEX9E and 0xEXA1 only
checkifacertainkeyispressedorisntpressed.Opcode 0xFX0A onlywaitsforakeypress,
andwhenitreceivesone,itstoresthekeynameintheregisterandnotthekeystate.
case0xE000:
switch(opcode&0x00FF)
{
//EX9E:Skipsthenextinstruction
//ifthekeystoredinVXispressed
case0x009E:
if(key[V[(opcode&0x0F00)>>8]]!=0)
pc+=4;
else
pc+=2;
break;
Belowyoullfindanexampleoftheoriginalkeypadlayout.Itdoesnotreallymatterhowyou
implementthekeymapping,butIsuggestsomethingasontherightside.
KeypadKeyboard
++++++++++
|1|2|3|C||1|2|3|4|
++++++++++
|4|5|6|D||Q|W|E|R|
+++++=>+++++
|7|8|9|E||A|S|D|F|
++++++++++
|A|0|B|F||Z|X|C|V|
++++++++++

CHIP8fontset
ThisistheChip8fontset.Eachnumberorcharacteris4pixelswideand5pixelhigh.
unsignedcharchip8_fontset[80]=
{
0xF0,0x90,0x90,0x90,0xF0,//0
0x20,0x60,0x20,0x20,0x70,//1
0xF0,0x10,0xF0,0x80,0xF0,//2
0xF0,0x10,0xF0,0x10,0xF0,//3
0x90,0x90,0xF0,0x10,0x10,//4
0xF0,0x80,0xF0,0x10,0xF0,//5
0xF0,0x80,0xF0,0x90,0xF0,//6
0xF0,0x10,0x20,0x40,0x40,//7
0xF0,0x90,0xF0,0x90,0xF0,//8
0xF0,0x90,0xF0,0x10,0xF0,//9
0xF0,0x90,0xF0,0x90,0x90,//A
0xE0,0x90,0xE0,0x90,0xE0,//B
0xF0,0x80,0x80,0x80,0xF0,//C
0xE0,0x90,0x90,0x90,0xE0,//D
0xF0,0x80,0xF0,0x80,0xF0,//E
0xF0,0x80,0xF0,0x80,0x80//F
};
Itmightlookjustlikeanarrayofrandomnumbers,buttakeacloselookatthefollowing:
DECHEXBINRESULTDECHEXBINRESULT
2400xF011110000****2400xF011110000****
1440x9010010000**160x1000010000*
1440x9010010000**320x2000100000*
1440x9010010000**640x4001000000*
2400xF011110000****640x4001000000*
Lookattheleftexamplewerewearedrawingthenumber0.Asyoucanseeitseeitconsistsout
of5values.Ofeveryvalue,weusethebinaryrepresentationtodraw.Notethatonlythefirstfour
bits(nibble)areusedfordrawinganumberorcharacter.

Conclusion
Hopefullythisguideprovidedyouenoughinformationtogetyoustartedwithyourownemulator
project.Atleastyoushouldnowhaveabasicunderstandingofhowemulationworksand
perhapsabetterunderstandingofhowaCPUexecutesopcodes.
IhaveincludedmyownimplementationofaChip8interpreterbelowwhichyoucanuseasa
reference.ThezipfilecontainsabinaryforWindowsbutalsoincludesthefullsourcecodeofthe
emulator.Becausethefullsourcecodeissupplied,Irecommendonlylookingat chip8.cpp
fileasalastresorttoseehowIimplementedaparticularopcode.Thefile chip8.h and
main.cpp shouldbesafetoviewwithoutspoilingtoomuch.Actually, main.cpp mostly
containsGLUTcodewhichyoucanreuseinother(nonemulatorrelated)projectsaswell.
myChip8(7567)87.36kBLatest(Windowsbinary+Sourcecode)
EarlyversionofmyChip8from2003(containsanicedebugger)
AnAndroidportIdidin2008
Letmeknowifyoufindthisguideuseful!Ifyouhavequestionsorthinkthatessentialpartsare
missing,pleaseusethecommentsection

Credits
Specialthankstothefollowingpersons(manyonlyknownbytheirpseudonym)whohave
helpedmegreatlywithmyownemulationprojectsinthepastandpresent.
ector&F|RES(Dolphinemuteam)
Saqib,zenogais,Absolute0,Shadow,gigaherz,Florin,Goldfinger(PCSX2team)
drk||Raziel&ZeZu(nullDCteam)
Hacktarux(Mupen64)
Muad(nSX2)
pSXAuthor(pSX)
Shadowprince,Linker,Aprentice,SculleatR,ShizZy,Dave2001

Suggestions
AfteryouhavecompletedyourfirstChip8emulator,youmightwanttotryoneofthefollowing
things:
AddSuperCHIP8Opcodes
Usefunctionpointersinsteadofagiantswitchstatement
Improvegraphicsbyaddingfilters(Hqx)
Portittootherplatforms(Mobile?)orlanguages
MoveontoamorecomplexprojectforexampleemulatingaGameboy(Z80
processor)

Resources
http://en.wikipedia.org/wiki/CHIP8Systeminformation
CowgodsChip8TechnicalReferencev1.0Recommended
Chip8tutorialGoldroad.co.uk(mirror)
(S)Chip8instructionsetGoldroad.co.uk(mirror)
DavidWintersCHIP8emulationpageContainssomegames
(S)CHIP8instructionsetoverview(ErikBryntse)
Chip8emulatortopiconEmutalk
Chip8emulatortopiconNGemu

Advancedemulatorresources
ZilmarsEmubook
EmubookCPUemulationchapter
Emubookmemoryemulationchapter
ZenogaisEmulationTutorials(Offline,butavailablethroughArchive.org)
ZenogaisEmulationTutorials(mirror)
DynamicRecompiler(mirror)
ArrayofFunctionPointers(mirror)
IntroductiontoEmulationPart1(mirror)
IntroductiontoEmulationPart2(mirror)
LayingtheGroundForAnEmulator(mirror)

Bookmark&Share

Share

56Comment
Nate
Hello,
Firstoff,greatjobonthetutorial!Imreallyenjoyingtheprocessofmakingmy
firstemulator!ImaCSmajor,andIdonthavealotofengineering,lowlevel
background.ImfollowingyourguideusingtheJavaprogramminglanguage.
Imalittlebitconfusedonsomethinginthetutorialthusfar.
IntheFetchOpcodesectionofthetutorial,youuseashifttoleftof8bitstoadd
8zeroestotheendofthenumber.However,ineveryarticleonbitwise
operationsIcanfind,shiftsdidntaddmoredigitsontotheendofanumber,they
simplymovetheirposition.Ididsomeexperimentingandfoundthatshiftsdo
indeedadddigitstotheend,butImstillconfusedonwhyexactlytheshiftis
addingmoredigits.
Thanks!
05JUN2011|REPLY

LaurenceMuller
HiNate,
thanks!

GladtohearyouhaveaJavaemulatorcomingalong!
Aboutyourquestion,letmetrytoexplainwhatishappeningthere.Youwill
havetorememberthateachopcodeis2byteslongandthatweusethe
datatypeunsignedshorttostorethisvalue.Sincewestoreallourdataas
bytesinthememory,thismeansweneedtofindawaytoconverttwo
separatebytesintounsignedshorts(2byteslong)togetthefullopcode.
Thefirststepistoretrievethefirstbytefromthememoryandstoreitinan
unsignedshort(0xA2>0x00A2).The0x00partisjustholding8bitswith
thevalueofzero.Nowifwearegoingtoshiftbitsinanunsignedshort,the
totalnumberofbitswearemanagingisalways16.Youcannotaddor
removeanybits.
Whenyouareshiftinganunsignedshortonesteptotheleft,itmeansthat
eachbitgetsmovedoneplacetotheleft.Duringthisstep,the1stbitwill
beassignedwiththevalueofthe2ndbit.Theoriginalvalueofthe1stbit
howeverislost.The16thbitdoesnothaveaneighboringbitontheright
side.Thereforthisbitwillalwaysbeassignedthevaluezero.Nowifwe
shifttotherightside,theoppositehappens.The1stbitwillbeassigned
zero(noleftneighbor!)andthe16thbitwillbeassignedwiththeoriginal
valueofthe15thbit.Thevalueofthe16thbitislost.
Hopethishelpsyououtabit!
06JUN2011|REPLY

Nate
Laurence,
Thanksfortheexplanationonthat.Thatreallyhelpedoutalot.
Ihaveanotherquestionforyou.Javadoesntsupportunsigned
types,andIvealreadyencounteredafewproblemswiththat.Ive
sincechangedthedatatypeformyopcodevariabletoanint.The
onlyotherthingIcanthinkofthatmightbeaprobleminthefutureis
myI(index)register.Doesthatvalueevergetbiggerthanplusor
minus32768(or0x8000)?NOTE:Thatnumberisthemaxvaluefor
theJavashortdatatype.
Also,ImnotsurehowfamiliaryouarewithJava,butifyouhave
anothersolutioninmindthatwouldbebetterthanmine,pleaselet
meknow!Imallears.
Thanksagain,
Nate
07JUN2011|REPLY

LaurenceMuller
HeyNate,
Gladithelped:).
ActuallyIwashavingthesameissueswhenIwasportingmy
Chip8emutoAndroid(Java).ImnotsurehowIsolvedit(orif
Ievensolveditatall).
Ifoundthiswebsitethatmightbeusefulforyou:
http://www.javamex.com/java_equivalents/unsigned.shtml
10JUN2011|REPLY

CAGriffin
Imwritingsome14monthsafterthispostsoIimagineyouve
gotitsussedbynow.Butforotherswomaystumblehere:
Usechardatatypeasitstheonlyunsignedtypeandis
16bits.Howeverforprintingtosys.outetcithastobecast

asanintorshortotherwisetheunicodecharacterwillbe
printedout.
Asforthebytetype,alwaysuseabitmaskwhenassigningto
anotherlargersignedtypevariableandthiscancelsthe
compilerassigningthesignednumericvalue,ohandcast..
forexample:
charopcode=(char)((byte1&0xFF)<<8|(byte2&0xFF))
Iwasbangingmyheadforawhileaboutthisandfoundthe
answerinJavaPuzzlersbyJBloch.
12SEP2012|REPLY

LaurenceMuller
ThanksforyourfeedbackCarlos!Imsurethiswillhelp
outotherJavadevelopersaswell.
14SEP2012|

IvanOspina
HelloLaurence,ImfromColombia,Ivebeenwaitingforthistutorialalongtime,
Imveryhappytofindthis,anditsverygoodexplained,thankyouforthis.
24JUN2011|REPLY

Runo
HiFalcon^^
ManIrememberusingyourPADpluginsonvariousemulatorslongtimeago,
whenIwasakid.Thanksforthis,ImatranslatorforDolphinemulatorandnow
ImtryingtoimprovemyC++andemulationknowledgesothishelpsmealot!
Goodtoseeyouarestillthere,IreallymissyourpluginsonDolphinemu,the
onlyonesthateverhadapictureofthecontroller^^
23JUL2011|REPLY

toggi3
Supermariobros3wasforNES,notSNES.YouprobablyusedNESticle.
12OCT2011|REPLY

LaurenceMuller
WellyourecorrectthatSMB3wasavailablefortheNES,butIthinkIwas
usingSuperMarioAllstarsontheSNES!IdidusedNESticleforduckhunt
:P!
12OCT2011|REPLY

Mitza
Doineedtouseopengltodrawonscreen,orhowelseicoulddoit?
12NOV2011|REPLY

LaurenceMuller
ThisexampleusesOpenGL,butonwindowsyoucoulduseDirectDrawor
Direct3D
16NOV2011|REPLY

Daniel
Hidudelovethetutorialmycodeisnotcompleteikindaskippedpartsofthe
tutorialbecauseididntunderstand,Hereismycode
1 ImportsSystem.IO
2
3 PublicClassForm1

4
5 PrivateSubForm1_Load(ByValsenderAsSystem.Object,ByVal
6 Dimmemory(4096)AsByte
7 DimV(16)AsChar
8 DimIAsString
9 DimpcAsInteger
10 DimgfxAsBitmap=NewBitmap(My.Computer.FileSystem.SpecialDirectories.Desktop&
11 Dimdelay_timerAsChar
12 Dimsound_timerAsChar
13 Dimstack(16)AsShort
14 DimspAsShort
15 DimopcodeAsString
16 DimkeyAsChar
17 DimmemoryPositionAsShort
18
19 DimopenfiledialogAsNewOpenFileDialog
20 openfiledialog.ShowDialog()
21
22 memory=System.IO.File.ReadAllBytes(openfiledialog.FileName)
23
24 While(1)
25
26 opcode=Hex(memory(pc))&Hex(memory(pc+1))
27
28
29 Ifopcode.StartsWith("A")Then
30
31 'IndexRegisterInstruction
32
33 Forb=1Toopcode.Length1
34 I&=opcode(b)
35 Next
36
37 EndIf
38
39 Ifopcode.StartsWith("D")Then
40
41 DimxAsInteger
42 DimyAsInteger
43 DimheightAsInteger
44 DimwidthAsInteger
45
46 x=CLng("&H"&opcode(1))
47 y=CLng("&H"&opcode(2))
48
49 height=CLng("&H"&opcode(3))
50
51 Forb=0Toheight
52 gfx.SetPixel(x,y,Color.Gray)
53 PictureBox1.Image=gfx
54 Next
55
56 Fora=0To16
57 gfx.SetPixel(x+a,y,Color.Gray)
58 PictureBox1.Image=gfx
59 Next
60
61 EndIf
62 pc+=2
63 EndWhile
64
65 EndSub
66 EndClass

Thiscodewillsetpixelsandthatsitbutitdoesnotsetthemproperlyhowcanifix
this?
11DEC2011|REPLY

LaurenceMuller
HiDaniel,inyourDopcode,afewthingsaremissing.Youneedtoreset
V[F]tozeroandsetitwhenscreenpixelsareflipped.Also,yourcode
doesntseemtocopydatafromthememory?
28DEC2011|REPLY

Shariq
gfx[(x+xline+((y+yline)*64))]
Hi,couldsomeonepleaseexplaintheaboveline?The64isntexactly
obvioustome.Whydoweneeditthere?Igetthatweretryingtoaccess

ourgfxarraywhichrepresentsourscreen(2048pixels?)butthis
statementisntmakingalotofintuitivesensetome.Anyhelpwouldbe
greatlyappreciated.
Ohandthankyouforthiswonderfultutorial!
03JAN2015|REPLY

CrckrHckr
Ihavejustbeguncodingone,Ineedsomehelp,
https://rapidshare.com/files/1098129696/Chip_8.rar
14APR2012|REPLY

LaurenceMuller
Couldyouexplainwhatkindofhelpyouneed?
23APR2012|REPLY

Max
HeyLaurence.Firstoffthanksforthegreattutorial.Ihadacouplequestions.Im
notnewtoprogrammingbutIamstillabeginner(about9monthsofexperience).
IwaswonderingifyoucouldelaborateontwothingsIveneverdonebefore:1.
Howtoreadinthegamefilesusingfopenand2.Howtouseoneofthe3rdparty
librariestohandlethegraphics.Irealizethesecondoneisaskingaverybig
question,soperhapsjustalinktoagoodandrelevanttutorialwouldbenice.
Goodworkandthanksinadvance!
18APR2012|REPLY

LaurenceMuller
HeyMax,
1.Iwouldstartbyreadinghowfopenworks,youprobablywanttoopena
fileinreadandbinarymode:
http://www.cplusplus.com/reference/clibrary/cstdio/fopen/and
http://www.cprogramming.com/tutorial/cfileio.html
2.Youcoulduse3rdpartylibs,butifyouarejustgoingtodrawb/wpixels
inopenGL,youmightwanttousethecodesnippetImadeformychip8
emu:
http://www.multigesture.net/articles/howtodrawpixelstoatexture
opengl/
23APR2012|REPLY

CrckrHckr
Well,thankyouforreplying.Iwanttofirstfinishmycpucore.Iwantedsome
pixelsdrawing,Isawyourcodesnippet,butallIsawwasawhitescreen,and
laterblack.ButIthinkIhavetofinishtheemucorefirst,right?
23APR2012|REPLY

LaurenceMuller
Itsprobablybesttofirstimplementallcpuinstructionsandseeifyourcore
canrunproperly(makeitoutputallcommandstothescreenforexample
toseeifitendsupinadeadlock).Afterthatyoucanworkonthedrawing
part(0xD000instruction)whichyoucandobywritinganarraytoatexture.
23APR2012|REPLY

CrckrHckr
Thanksforyouropinion.Ifyoulookat:
http://forums.pcsx2.net/ThreadEmulatorProgrammingChip8
OPCODEhelp?page=2
thenthelastpostbymeshowsaproblem,ithasmysource
attached.Thanks.
24APR2012|REPLY

Stefonzo
Ihavebeencodingthisinjavatoandsofarhavebeenusingsignedshortsfor
theopcodes.Willitstillworkevenifitissigned?
04MAY2012|REPLY

LaurenceMuller
Itwillprobablywork,youwilljusthavetobecarefulwhenshiftingbits
left/right
05MAY2012|REPLY

RandomEmuDude
Iwouldpersonallycreatemyownclasstorepresentthenecessary
amountofbits.Usingasignedshortcouldbeperfectinalmostallcases,
butithastobeperfectinALLofthem.Imaginesomethinglikeoverflow
beingintentionalintheoriginalgame,thesignedshortgivedifferent
behavior.
10SEP2012|REPLY

Stefonzo
ThanksalotIappreciateitohandyourBeatNodeapplooksprettycoolwhenI
getsomemoneyImgoingtobuyit!
06MAY2012|REPLY

LaurenceMuller
Yourewelcome
07MAY2012|REPLY

CrckrHckr
Hey,Igetunkownopcode0xf090and0xf020,Whatshouldido?
06MAY2012|REPLY

CrckrHckr
SOrry,problemwaswithCPUcore.
07MAY2012|REPLY

LaurenceMuller
Gladyoufigureditout
07MAY2012|REPLY

CrckrHckr
Yup,IevengotSDLgraphicsandkeyboardinputworking,(I
amjust15:P)
12MAY2012|REPLY

Ryan
Thatsgreat,CrckrHckr.Dontstopherethough,see
whatotheremulatorsyoucanwrite.Perhapsthe
MasterSystem,ormaybetheNESwouldbean
interestingprojectforyoutotakeon?
04AUG2013|

Stefonzo
Ihavebegunimplementingtheopcodesandwaswonderingifthiscodelooked
alrightasIwaswonderinghowtoimplementNNandNNN:
case0x3XNN:
for(inti=0i<16i++){
if(V[i]==0x00FF){
pc=pc+4
}else{
pc=pc+2
}
}
break
Would0x00FFworkforNN?DoesNNhaveaspecificplaceitshouldbestored
at?
31MAY2012|REPLY

testabc
HelloLaurenceMuller,IhaveaquestionaboutthisSCHIP8instruction:
00FB*Scrolldisplay4pixelsright.
WhenitsaysScrolldisplay4pixelsrightdoesitmeanshiftthepixelinthat
directionbythatamountwithoutconcerningthe4pixels(nowoutofthescreen)
fromtheright,ordoesitmeantoshiftthescreenrightandthelast4pixelstothe
rightwillnowappeartotheleft?
04JUN2012|REPLY

Patrick
Greatwriteup!
IdidanearlylinebylineporttoC#thatrunstheinterpreterinaWindowsForms
app.ItarunningalittleslowbutIhaventlookedintoanyoptimizationandI
believethatthemultitudeoftypecastingImdoingontick.
Itwasgreatfun,thanksfortheinspirationandtheheavylifting.
http://www.dreambuildrepeat.com/Chip8/Chip8.zip
24JUN2012|REPLY

Turbohao
ThanksforportingittoC#,ivetrieditoutanditworksgreat.
iwilllearnlotsfromit.
02NOV2012|REPLY

Mario
Yousays:
Whilethisguideexpectsyoutohavesomebasicknowledgeofcomputer
systemsandassumesyouknowaprogramlanguage,itshouldalsobean
interestingreadforpeoplewhoareinterestedinemulationingeneral.
WhatdoyoumeanbyComputerSystems?
Canyourecommendanybooks?
24JUN2012|REPLY

JamesBlandford
Heythere,thanksfortheawesometutorial!
AfterimplementingalloftheopcodesinC++(thattookawhile!),itworksfine!
Optimizeditabitsoitrunsatfullspeednow,andinsteadofsettingtheredraw
flagonthespritedrawopcode,Imovedittothe0x1NNNreturnopcodeinstead.
Itdoesntblinkanymore,obviouslymygfxcodewasntuptoscratch,butit
worksfine:createdmyownlittleassemblygameandranit,playedbreakout,
blinky.
NowitstimetomoveontoNESemulation!
Thanks,
James.
14AUG2012|REPLY

LaurenceMuller
HiJames,thanksforthefeedback!
Gladthisguidecouldhelpyouonyouremulationjourney.Goodluckon
yourNESemulator!
14AUG2012|REPLY

RandomEmuDude
HiJames,thanksforthispost,itiselaboratelywrittenandhelpsnewbiesand
experienceddevelopersjuststartingwithemulationalike!
OnequestionIhaveisinregardstoC++templatesandmetaprogramming.I
haveheardthatopcodescanbegeneralizedwithtemplatesandthatitisavery
elegantsolution,butsomethingthatIwouldimaginerequiresagoodamountof
previousexposuretometaprogrammingandtemplates.Ipersonallyhavea
decentamountofC++developmentundermybelt,buttheoneareaofC++I
haventusedmuchistemplates.Wouldyoupleaserecommendawayto
accomplishthisviapointingmeintherightdirectionorshowingacodesample
thatwillhelpmegetstarted?
Thanksagain!
10SEP2012|REPLY

CarlosGriffin
IjustwantedtosharewithyouthesolutiontotheBCDassignmentforopcode
FX33.Ifonedoesntknowhowtousethemodulusoperatororifforinstanceit
simplydidntexist.
Simplearithmeticbasically.Imsubstitutingthevariablenamesformemory[i]etc.
forthenames:hunds,tens,ones.
hunds=VX/100
tens=(VX(hunds*100))/10
ones=(VX(hunds*100+tens*10))
IdoconcedethatitsnotquiteaselegantasTJAssolution.
Anyway,RegardsandHappyCoding
14SEP2012|REPLY

cyboman
Hi.
Thanksforthetutorial.Itisveryinformative.
Imslightlyconfusedabouttheskipif(not)equalinstructions.
Oneofthelinksthatyougaveonthispage,CowgodsChip8Technical
Referencev1.0,http://devernay.free.fr/hacks/chip8/C8TECH10.HTM#3xkksays
thefollowingaboutthetheskipifequalinstruction:
3xkkSEVx,byte
SkipnextinstructionifVx=kk.
TheinterpretercomparesregisterVxtokk,andiftheyareequal,incrementsthe
programcounterby2.
ThequestionthatIhaveisshouldntitincrementtheprogramcounterby4
insteadofby2sinceopcodesare2bytesandeachprogramcountervalue
correspondstoansinglebyte.IfIincrementtheprogramcounterby2,thenIwill
simplyexecutethenextinstruction,butIfIincrementitby4thenIwillskipthe
nextinstructionandexecutetheonethatisneeded.
Anyhelpisappreciated.
24OCT2012|REPLY

Smoke
Thanksforthetutorial,itconfirmedthatIalreadyhadadecentideaofhowitall
works.
ImthinkImgoingtogiveaC#implementationawhirl,shouldbefun.
Anyways,Ialsowantedtoletyouknowthatyourcompiledexampleisntworking
correctlyonWin7x64,itdoesrun,but,thegamesareallmessedup,unlessof
coursethatswhattheyresupposedtobelike?

Inpong,theboard\paddles\etc,aredrawnfine,but,youseethecpuplayingat
lightingspeeds,itlookslikeseveralballsaremovingaround,oroneismoving
reallyfast.
Tetriswasjustabigblobofpixels,likeanImadeofpixels,withsomejittery
nonsensehappeningatthetopofthetowerofpixels..
Idontknow,anyways,justwantedtoletyouknowtherewereissues.
Anyways,thanksagain.
19JAN2013|REPLY

Otto
Thanksforthenicepost.
ButItestedthebinaryyoumadeavailableanditsextremelyfast.Allgamesstart
andend(Idie)inlessthanasecond.ItsWinXP32bitsandtheCPUisacorei5.
18JUN2013|REPLY

Help
IamtryingtowriteanemulatorforChip8inJavausingtheLWJGL.HowwouldI
opentheROM?ThatisreallytheonlythingIneedhelpfor.Thanks
31JUL2013|REPLY

Mostafa
Hilaurence..
ThankyouforthisEXCELLENTtutorial..Ihopeyouarestillalive.
29SEP2013|REPLY

Coornio
IhavealsomademyownChip8/Superchipemulator,inCubescript.Itcanonly
berunwithinthegameTesseractthough
InameditCubeChipforobviousreasons,youcancatchthevideohere:
https://www.youtube.com/watch?v=O9Opuf8GHPQ
Yourarticleisaniceintroduction,butinrealitysomepartsaremisleading.If
yourestillmaintainingthisarticlewithupdatesitwouldbenicertotalkoutofthe
commentsection
16JAN2015|REPLY

EmulateurChip8|itMiscBlog
PremierpasdanslaconceptiondunmulateurChip8|
():CHIP8|
Inprogress:CHIP8emulator|Projectlog
Chip8Linuxport|Projectlog
WritingaChip8Emulator(Part1)CraigThomas
CHIP8EmulatorLyndonArmitage
CHIP8Javascript|alexkudryashkin
Chip8EmulatorinChilliSource|ProcedurallyChallenged

Leaveareply

Submit

Tags

RecentPosts

adobeairAndroid

applicationchat
conferencediyemulation
facebookflashgames google

earthgsochackingharvardhci

infovisIRCkinectlatency

howto

mmamultitouch

RecentComments

About

NodeBeatfeaturedonthe

AKouZ1onMyChip8emulator

Sitecontentcopyright20072013

BlackBerryDevblog

LaurenceMulleronMyChip8

LaurenceMuller.Allrightsreserved.

PlayBookaddon(ofxQNX)

emulator

RewritingandportingfIRC

AKouZ1onMyChip8emulator

Thewebsiteusagestatisticsfor

EpicWindmill

LaurenceMulleronHowtosetup

multigesture.netaretrackedby

NodeBeat,openFrameworksand

openFrameworksforAndroidon

GoogleAnalytics.

Android

Windows
LaurenceMulleronBootinga

museumnasanuigroupprojects

MacbookPro(2009)inAHCI

showcasesparkonsurface

modeonWin7

technology

computingtabletop

thesistouchlibtouchtracer

tutorialtvuva

2016Multigesture.netisproudlypoweredbyWordPress
Standard|Mobile

Aqualityproductfrom

Potrebbero piacerti anche