Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
HOME
ABOUT
ARTICLES
DOWNLOADS
EVENTS
FEATURED
PROJECTS
RESEARCHPROJECTS
Subscribe RSS|Email
MULTIGESTURE.NET
AmultitouchandHCIresearchblog
PUBLICATIONS
Subscribe
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