
FreeBASIC's Official Forums
|
| View previous topic :: View next topic |
| Author |
Message |
|
|
Posted: May 16, 2008 10:34 Post subject: Port of a CHIP8 Emulator to FB :D |
|
|
Some of you surely saw my post in the beginners section :p
Well, i'm pretty proud to present you this port of a CHIP 8 emulator made for Game boy advance / DS architecture.
The original code was linked with a french tutorial (if you know french and wanna learn how a basic emulator works, GO READ THIS!). You can find it here :
http://www.portabledev.com/pages/ds/tutoriels/alors-comme-cela-on-veut-faire-un-E9mulateur.php
The FB port of the emulator (a .rar with .bas, .exe, and a ROM to test) :
http://Narky00.free.fr/CHIP8_Emul_FB.rar
Okay, you'll say "hey ! it's damn slow !" and I'll answer "Yep". But I'm so glad I ported it, I had to post it here :)
Oh one last thing, I need to use better keys .. NUMPAD keys doesn't work here so you have to (sic..) use MAJ+NUM (4=left ,6=right)
Code :
| Code:
|
|
'' '' emulateur CHIP-8 ? '' '' '' - 4K memory (&hFFF) '' - 64*32 px res '' '' memory : interpreter -> &h000-&h1FF '' programs -> &h200-&hFFF
#include "fbGfx.bi"
Randomize Timer
'#Define DEBUG
'' Chip 8 CPU type
Type Chip8_Type As Byte reg_V(16) '' 16 registres As Short reg_PC '' registre Program Counter As Short reg_SP '' registre SP As Short reg_I '' registre I As Byte delay, Sound '' timers delay et son End Type
'' CPU Variables
Dim Shared As Chip8_Type Chip8CPU '' le CPU
Dim Shared As Byte Iperiod '' Cycles d'horloge
Dim Shared As Byte keys(16) '' buffer des 16 touches Dim Shared As Byte Display(64*32) '' buffer ecran
Dim Shared As Byte Mem(4096) '' les 4K de mémoire
Dim Shared As Short PILE(16) '' Pile de 16 emplacements
Dim Shared As Byte CPU_Exec '' CPU running or not ? (yes / no)
Dim Shared As Byte opcode_1, opcode_2,_ '' lecture des opcodes opcode_3,opcode_4
'' Read/write memory routines
#Define Read_Mem(adr) Mem(adr And 4095) #Define Write_Mem(adr,Val) Mem(adr And 4095)=Val
'' GetOpCode Sub Sub CHIP8_GetOpCode() OpCode_1 = (read_mem(CHIP8CPU.Reg_PC ) And &hF0) Shr 4 OpCode_2 = (read_mem(CHIP8CPU.Reg_PC ) And &h0F) OpCode_3 = (read_mem(CHIP8CPU.Reg_PC + 1) And &hF0) Shr 4 OpCode_4 = (read_mem(CHIP8CPU.Reg_PC + 1) And &h0F) Chip8CPU.reg_PC += 2 End Sub
'' DEBUG SUB
#Macro Say(a) #ifdef DEBUG Open Cons For Output As #157 Print #157, a Close #157 #endif #endMacro '' OPCODES INSTRUCTIONS ***********************************
Sub Op00E0_cls() Say("cls") For ulig As Integer = 0 To 32-1 For uCol As Integer = 0 To 64-1 Display(ulig * 64 + uCol) = 0 Next Next
End Sub
Sub Op00EE_rts() Chip8CPU.reg_SP+=1 Chip8CPU.reg_PC = PILE(Chip8CPU.reg_SP) Say("rts : SP="+Str(Chip8CPU.reg_SP)+" , PC="+Str(PILE(Chip8CPU.reg_SP))) End Sub
Sub Op1xxx_jump_xxx()
Chip8CPU.reg_PC = (OpCode_2 * 256) + (OpCode_3 *16) + OpCode_4 Say("jump : PC="+Str(Chip8CPU.reg_PC)) End Sub
Sub Op2xxx_jsr_xxx()
PILE(Chip8CPU.reg_SP) = Chip8CPU.reg_PC Chip8CPU.reg_SP-=1 Chip8CPU.reg_PC = (OpCode_2 * 256) + (OpCode_3 *16) + OpCode_4 Say("jsr : TOP PILE="+Str(PILE(Chip8CPU.reg_SP))+", Pc="+Str(Chip8CPU.reg_PC)) End Sub
Sub Op3rxx_sqeqvrxx()
If (Chip8CPU.reg_V(OpCode_2) = ((OpCode_3 *16) + OpCode_4)) Then Chip8CPU.reg_PC += 2 End If say("sqeqVrXX") End Sub
Sub Op4rxx_sqnevrxx()
If (Chip8CPU.reg_V(OpCode_2) <> ((OpCode_3 *16) + OpCode_4)) Then Chip8CPU.reg_PC += 2 End If say("sqneVrXX") End Sub
Sub Op5ry0_sqnevrvy()
If (Chip8CPU.reg_V(OpCode_2) = Chip8CPU.reg_V(OpCode_3)) Then Chip8CPU.reg_PC += 2 End If say("sqeqVrVy") End Sub
Sub Op6rxx_movvrxx()
Chip8CPU.reg_V(OpCode_2) = (OpCode_3 * 16) + OpCode_4 say("movVrXX : "+Str((OpCode_3 * 16) + OpCode_4)+" in reg "+Str(OpCode_2)) End Sub
Sub Op7rxx_addvrxx()
Chip8CPU.reg_V(OpCode_2) += (OpCode_3 * 16) + OpCode_4 Say("AddVrXX : reg "+Str(OpCode_2)+"+="+Str((OpCode_3 * 16) + OpCode_4)) End Sub
Sub Op8ry0_movvxvy()
Chip8CPU.reg_V(OpCode_2) = Chip8CPU.reg_V(OpCode_3) say("movVxVy : reg "+Str(Opcode_2)+" = reg "+Str(Opcode_3)) End Sub
Sub Op8ry1_orvxvy()
Chip8CPU.reg_V(OpCode_2) Or= Chip8CPU.reg_V(OpCode_3) say("orVxVy : reg "+Str(Opcode_2)+" OR= reg "+Str(Opcode_3)) End Sub
Sub Op8ry2_andvxvy()
Chip8CPU.reg_V(OpCode_2) And= Chip8CPU.reg_V(OpCode_3) say("andVxVy : reg "+Str(Opcode_2)+" AND= reg "+Str(Opcode_3)) End Sub
Sub Op8ry3_xorvxvy()
Chip8CPU.reg_V(OpCode_2) Xor= Chip8CPU.reg_V(OpCode_3) say("xorVxVy : reg "+Str(Opcode_2)+" XOR= reg "+Str(Opcode_3)) End Sub
Sub Op8ry4_addvxvy()
If(Chip8CPU.reg_V(OpCode_2) And Chip8CPU.reg_V(OpCode_3)) Then
Chip8CPU.reg_V(&hF) = 1
Else Chip8CPU.reg_V(&hF) = 0 End If Chip8CPU.reg_V(OpCode_2) += Chip8CPU.reg_V(OpCode_3) say("addVxVy : reg "+Str(Opcode_2)+" += reg "+Str(Opcode_3)) End Sub
Sub Op8ry5_subvxvy()
If(Chip8CPU.reg_V(OpCode_2) > Chip8CPU.reg_V(OpCode_3)) Then
Chip8CPU.reg_V(&hF) = 1
Else Chip8CPU.reg_V(&hF) = 0 End If Chip8CPU.reg_V(OpCode_2) -= Chip8CPU.reg_V(OpCode_3) say("subVxVy : reg "+Str(Opcode_2)+" -= reg "+Str(Opcode_3)) End Sub
Sub Op8ry6_shrvx()
If Chip8CPU.reg_V(OpCode_2) And 1 Then
Chip8CPU.reg_V(&hF) = 1
Else Chip8CPU.reg_V(&hF) = 0 End If
Chip8CPU.reg_V(OpCode_2) Shr= 1 say("shrVx : reg "+Str(Opcode_2)+" SHR= 1") End Sub
Sub Op8ry7_rsbvxvy()
If(Chip8CPU.reg_V(OpCode_3) > Chip8CPU.reg_V(OpCode_2)) Then Chip8CPU.reg_V(&hF) = 1
Else Chip8CPU.reg_V(&hF) = 0 End If Chip8CPU.reg_V(OpCode_2) -= Chip8CPU.reg_V(OpCode_3) - Chip8CPU.reg_V(OpCode_2) say("rsbVxVy : reg "+Str(Opcode_2)+" -= reg "+Str(Opcode_3)+" - reg "+Str(Opcode_2)) End Sub
Sub Op8r0E_shlvx()
If (Chip8CPU.reg_V(OpCode_2) And 128) Then Chip8CPU.reg_V(&hF) = 1
Else Chip8CPU.reg_V(&hF) = 0 End If Chip8CPU.reg_V(OpCode_2) Shl= 1 say("shlVx : reg "+Str(Opcode_2)+" SHL= 1") End Sub
Sub Op9ry0_sknevxvy()
If (Chip8CPU.reg_V(OpCode_2) <> Chip8CPU.reg_V(OpCode_3)) Then Chip8CPU.reg_PC += 2 End If say("skneVxVy") End Sub
Sub OpAxxx_mvixxx()
Chip8CPU.reg_I = (OpCode_2 * 256) + (OpCode_3 *16) + OpCode_4 say("mviXXX : reg_I = "+Str((OpCode_2 * 256) + (OpCode_3 *16) + OpCode_4)) End Sub
Sub OpBxxx_jmixxx()
Chip8CPU.reg_PC = Chip8CPU.reg_V(0) + (OpCode_2 * 256) + (OpCode_3 * 16) + OpCode_4 Say("jmiXXX : reg_PC = "+Str(Chip8CPU.reg_V(0) + (OpCode_2 * 256) + (OpCode_3 * 16) + OpCode_4)) End Sub
Sub OpCrxx_randvrxx()
'Chip8CPU.reg_V(OpCode_2) = rand() & ((OpCode_3 *16) + OpCode_4); Chip8CPU.reg_V(OpCode_2) = Int(Rnd() * ((OpCode_3 *16) + OpCode_4)) Say("randVrXX : "+Str(Chip8CPU.reg_V(OpCode_2))) End Sub
Sub OpDry0_spritevxvys() Say("SpriteVxVyS") Dim As Byte gfxVal, xVal, yVal
'// Pas de collision pour l'instant Chip8CPU.reg_V(&hF) = 0 For ulig As Integer = 0 To OpCode_4-1 gfxVal = read_mem(Chip8CPU.reg_I + ulig) ' // Recup des 8 pixels de la ligne yVal = (Chip8CPU.reg_V(OpCode_3) + ulig) ' // Recup la coordonnee Y d'affichage (opcode3 + 1..15
For uCol As Integer = 0 To 8-1 xVal = (Chip8CPU.reg_V(OpCode_2) + uCol) '// Recup la coordonnee X d'affichage (opcode2 + 1..8) If ((gfxVal And (&h80 Shr uCol)) <> 0) Then '// Si le pixel est de couleur (donc <>0) If (Display(((yVal Mod 32) * 64) + (xVal Mod 64)) = 1) Then '// Si il y a dejà un pixel a cet endroit Chip8CPU.reg_V(&hF) = 1 '// Stocke la collision de pixel End If Display(((yVal Mod 32) * 64) + (xVal Mod 64)) Xor= 1 ' // Allume ou eteind le pixel en conséquence If Display(((yVal Mod 32) * 64) + (xVal Mod 64)) = 1 Then Say(" Sprite Coord : ("+Str(xVal)+","+Str(yVal)+")") End If End If Next Next End Sub
Sub OpEk9E_skprk()
If (Keys(Chip8CPU.reg_V(OpCode_2)) = 1) Then '' // Si touche enfoncee Chip8CPU.reg_PC += 2 End If Say("skprk") End Sub
Sub OpEkA1_skupk() If (Keys(Chip8CPU.reg_V(OpCode_2)) = 0) Then ' // Si touche relachee Chip8CPU.reg_PC += 2 ' // On saute l'instruction suivante End If Say("skupk") End Sub
Sub Opfr07_gdelayvr()
Chip8CPU.reg_V(OpCode_2) = Chip8CPU.delay Say("gdelayVr : reg_V("+Str(opcode_2)+") = "+Str(Chip8CPU.delay)) End Sub
Sub Opfr0A_keyvr()
Dim As Integer KeyPressed = 0
For uBc As Integer = 0 To 16-1 ' // Regarde si une des 16 touches est pressée If (Keys(uBc) = 1) Then Chip8CPU.reg_V(OpCode_2) = uBc ' // Si Oui, Vx = Touche KeyPressed = 1 End If Next If keypressed Then Say("keyVr : KeyCode = "+Str(Chip8CPU.reg_V(OpCode_2))) Else Say("keyVr : noKey") End If If (KeyPressed = 0) Then Chip8CPU.reg_PC -= 2 '// Si Non, on reste sur la même instruction End If
End Sub
Sub Opfr15_sdelayvr()
Chip8CPU.delay = Chip8CPU.reg_V(OpCode_2) Say("sdelayVr : delay = "+Str(Chip8CPU.delay)) End Sub
Sub Opfr18_ssoundvr()
Chip8CPU.sound = Chip8CPU.reg_V(OpCode_2) Say("ssoundVr : sound = "+Str(Chip8CPU.sound)) End Sub
Sub Opfr1E_adivr()
Chip8CPU.reg_I += Chip8CPU.reg_V(OpCode_2) Say("adiVr : reg_I += "+Str(Chip8CPU.reg_V(OpCode_2))) End Sub
Sub Opfr29_fontvr()
Chip8CPU.reg_I = &h0000+(Chip8CPU.reg_V(OpCode_2) * &h5) '// I = Carac num VX say("fontVr : reg_I = "+Str(&h0000+(Chip8CPU.reg_V(OpCode_2) * &h5))) End Sub
Sub Opfr33_bcdvr()
Dim As Byte uNbre = Chip8CPU.reg_V(OpCode_2)
For uBc As Byte = 3 To 1 Step -1 write_mem(Chip8CPU.reg_I + (uBc - 1),uNbre Mod 10)
uNbre /= 10 Next Say("bcdVr : mem writing") End Sub
Sub Opfr55_strv0vr()
For uBc As Byte = 0 To OpCode_2 write_mem(Chip8CPU.reg_I + uBc, Chip8CPU.reg_V(uBc)) Next Say("strV0Vr : mem writing") End Sub
Sub Opfr65_ldrv0vr()
For uBc As Byte = 0 To OpCode_2 Chip8CPU.reg_V(uBc) = read_mem(Chip8CPU.reg_I + uBc) Next Say("ldrV0Vr : mem writing") End Sub
'' ********************************************** '' ***** ********* '' ****** Chip8 Execution Sub ************ '' **** ******* '' **********************************************
Sub Chip8Execute() '' Pour une periode d'execution For uBc As Integer = 0 To Iperiod-1
' recupere l'opcode CHIP8_GetOpcode() ' Interprete l'opcode Select Case (OpCode_1) Case &h0 Select Case(OpCode_3) Case &hE Select Case (OpCode_4) Case &h0 : Op00E0_cls() : Exit For Case &hE : Op00EE_rts() : Exit For End Select Exit For End Select Exit For Case &h1: Op1xxx_jump_xxx() : Exit For Case &h2: Op2xxx_jsr_xxx() : Exit For Case &h3: Op3rxx_sqeqvrxx() : Exit For Case &h4: Op4rxx_sqnevrxx() : Exit For Case &h5: Op5ry0_sqnevrvy() : Exit For Case &h6: Op6rxx_movvrxx() : Exit For Case &h7: Op7rxx_addvrxx() : Exit For Case &h8 Select Case (OpCode_4) Case &h0: Op8ry0_movvxvy() : Exit For Case &h1: Op8ry1_orvxvy() : Exit For Case &h2: Op8ry2_andvxvy() : Exit For Case &h3: Op8ry3_xorvxvy() : Exit For Case &h4: Op8ry4_addvxvy() : Exit For Case &h5: Op8ry5_subvxvy() : Exit For Case &h6: Op8ry6_shrvx() : Exit For Case &h7: Op8ry7_rsbvxvy() : Exit For Case &hE: Op8r0E_shlvx() : Exit For End Select Exit For Case &h9: Op9ry0_sknevxvy() : Exit For Case &hA: OpAxxx_mvixxx() : Exit For Case &hB: OpBxxx_jmixxx() : Exit For Case &hC: OpCrxx_randvrxx() : Exit For Case &hD: OpDry0_spritevxvys() : Exit For Case &hE Select Case(OpCode_3) Case &h9: OpEk9E_skprk() : Exit For Case &hA: OpEkA1_skupk() : Exit For End Select Exit For Case &hF Select Case (OpCode_3) Case &h0 Select Case(OpCode_4) Case &h7: Opfr07_gdelayvr() : Exit For Case &hA: Opfr0A_keyvr() : Exit For End Select Exit For Case &h1 Select Case(OpCode_4) Case &h5: Opfr15_sdelayvr() : Exit For Case &h8: Opfr18_ssoundvr() : Exit For Case &hE: Opfr1E_adivr() : Exit For End Select Exit For Case &h2: Opfr29_fontvr() : Exit For Case &h3: Opfr33_bcdvr() : Exit For Case &h5: Opfr55_strv0vr() : Exit For Case &h6: Opfr65_ldrv0vr() : Exit For End Select Exit For Case Else
Exit For End Select
Next ' // Met a jour les timers If (Chip8CPU.delay)>0 Then Chip8CPU.delay-=1 If (Chip8CPU.sound)>0 Then Chip8CPU.sound-=1 End If End Sub
'' ******************** Load ROM Sub *************************** Sub LoadRom(szName As String)
Dim As Integer fd = Freefile
If Open(szName For Binary As #fd) = 0 Then Get #fd, 1, MEM(&h200), (&h1000 - &h200) Close #fd End If
End Sub
'' ***************** GFX SUBS **************** Sub Chip8InitFont()
MEM(&h0000) = 96' //.11..... MEM(&h0001) = 144' //1..1.... MEM(&h0002) = 144' //1..1.... MEM(&h0003) = 144' //1..1.... MEM(&h0004) = 96' //.11.....
MEM(&h0005) = 96' //.11..... MEM(&h0006) = 224' //111..... MEM(&h0007) = 96' //.11..... MEM(&h0008) = 96' //.11..... MEM(&h0009) = 240' //1111....
MEM(&h000A) = 96' //.11..... MEM(&h000B) = 144' //1..1.... MEM(&h000C) = 32' //..1..... MEM(&h000D) = 64' //.1...... MEM(&h000E) = 240' //1111.... MEM(&h000F) = 224' //111..... MEM(&h0010) = 16' //...1.... MEM(&h0011) = 96' //.11..... MEM(&h0012) = 16' //...1.... MEM(&h0013) = 224' //111.....
MEM(&h0014) = 160' //1.1..... MEM(&h0015) = 160' //1.1..... MEM(&h0016) = 240' //1111.... MEM(&h0017) = 32' //..1..... MEM(&h0018) = 32' //..1.....
MEM(&h0019) = 240' //1111.... MEM(&h001A) = 128' //1....... MEM(&h001B) = 240' //1111.... MEM(&h001C) = 16' //...1.... MEM(&h001D) = 240' //1111.... MEM(&h001E) = 240' //1111.... MEM(&h001F) = 128' //1....... MEM(&h0020) = 240' //1111.... MEM(&h0021) = 144' //1..1.... MEM(&h0022) = 240' //1111....
MEM(&h0023) = 240' //1111.... MEM(&h0024) = 16' //...1.... MEM(&h0025) = 32' //..1..... MEM(&h0026) = 64' //.1...... MEM(&h0027) = 128' //1.......
MEM(&h0028) = 96' //.11..... MEM(&h0029) = 144' //1..1.... MEM(&h002A) = 96' //.11..... MEM(&h002B) = 144' //1..1.... MEM(&h002C) = 96' //.11.....
MEM(&h002D) = 240' //1111.... MEM(&h002E) = 144' //1..1.... MEM(&h002F) = 240' //1111.... MEM(&h0030) = 16' //...1.... MEM(&h0031) = 240' //1111....
MEM(&h0032) = 96' //.11..... MEM(&h0033) = 144' //1..1.... MEM(&h0034) = 240' //1111.... MEM(&h0035) = 144' //1..1.... MEM(&h0036) = 144' //1..1....
MEM(&h0037) = 224' //111..... MEM(&h0038) = 144' //1..1.... MEM(&h0039) = 224' //111..... MEM(&h003A) = 144' //1..1.... MEM(&h003B) = 224' //111.....
MEM(&h003C) = 112' //.111.... MEM(&h003D) = 128' //1....... MEM(&h003E) = 128' //1....... MEM(&h003F) = 128' //1....... MEM(&h0040) = 112' //.111....
MEM(&h0041) = 224' //111..... MEM(&h0042) = 144' //1..1.... MEM(&h0043) = 144' //1..1.... MEM(&h0044) = 144' //1..1.... MEM(&h0045) = 224' //111.....
MEM(&h0046) = 240' //1111.... MEM(&h0047) = 128' //1....... MEM(&h0048) = 224' //111..... MEM(&h0049) = 128' //1....... MEM(&h004A) = 240' //1111....
MEM(&h004B) = 240' //1111.... MEM(&h004C) = 128' //1....... MEM(&h004D) = 224' //111..... MEM(&h004E) = 128' //1....... MEM(&h004F) = 128' //1.......
End Sub
'' Reset / Start Sub Sub CHIP8_Reset() CHIP8CPU.reg_SP = &hF CHIP8CPU.reg_PC = &h200 Chip8InitFont Iperiod = 15 CPU_Exec = 1 End Sub
'' CheckKeys Sub **********************
Sub CheckKeys() '// Toutes les touches sont à l'état "non enfoncée" For uBc As Integer = 0 To 16 : Keys(uBc) = 0 : Next '// Regarde si une touche de la DS est enfoncée If multikey(fb.SC_2) Then Keys(2) = 1 If multikey(fb.SC_8) Then Keys(8) = 1 If multikey(fb.SC_4) Then Keys(4) = 1 If multikey(fb.SC_6) Then Keys(6) = 1 If multikey(fb.SC_5) Then Keys(5) = 1 If multikey(fb.SC_0) Then keys(0) = 1 If multikey(fb.SC_7) Then keys(7) = 1 If multikey(fb.SC_9) Then keys(9) = 1 If multikey(fb.SC_1) Then keys(1) = 1 If multikey(fb.SC_3) Then keys(3) = 1
End Sub
''' UPDATE SCREEN SUB !! *************************************
Sub UpdateScreen()
Dim As Integer uPixel Dim As Uinteger uColor For ulig As Integer=0 To 32-1 For uCol As Integer=0 To 64-1 uPixel = Display(uCol+ulig*64) ' // Recuperation du pixel If (uPixel = 1) Then ' // Prend blanc ou noir suivant sa valeur uColor = RGB(255,255,255) Else uColor = RGB(0,0,0) End If
Line(ucol*4,ulig*4)-(ucol*4+4,ulig*4+4),uColor,bf Next Next End Sub
'' ************************************************************ '' ************************************************************ '' **************** \ MAIN / ******************** '' ************************************************************ '' ************************************************************
Sub main() Screenres 256,128,16,2 Windowtitle "Chip 8 Emulator" LoadRom "BRIX" CHIP8_Reset()
Do While (CPU_Exec) screenlock Chip8Execute () CheckKeys UpdateScreen Screenunlock:Sleep 1,1 Loop
End Sub
main |
(I have a lot of warnings : "Overflow in constant conversion", problem with datatypes ?) |
| |
|
| Back to top |
|
 |
|
|
Posted: May 20, 2008 3:55 Post subject: |
|
|
Cool, great work on this project!
This is one of my great aspirations to do something like this. Great find on the article. My french is very basic, but I'll see what I can read through. |
| |
|
| Back to top |
|
 |
|
|
|
| Back to top |
|
 |
|
|
|
| Back to top |
|
 |
|
|
Posted: May 20, 2008 14:24 Post subject: |
|
|
Yeah I remember this post Joshy :p I was literally astounded !!
Thanks ! |
| |
|
| Back to top |
|
 |
|
|
|
| Back to top |
|
 |
|
|
Posted: May 20, 2008 21:24 Post subject: |
|
|
| Quote: | | yours is the third in fb ;-) |
I'm ok with it :P |
| |
|
| Back to top |
|
 |
|
|
Posted: May 21, 2008 1:14 Post subject: |
|
|
I just popped in to brag about my z80/spectrum emulator :P
Great work, I love a good emulator. |
| |
|
| Back to top |
|
 |
|
|
Posted: May 21, 2008 8:13 Post subject: |
|
|
| Quote: | | I just popped in to brag about my z80/spectrum emulator :P |
In FB ?! I searched in the forum but didn't find it !
| Quote: | | Great work, I love a good emulator. |
Thanks :) |
| |
|
| Back to top |
|
 |
|
|
Posted: May 21, 2008 11:49 Post subject: HOLY CRAP |
|
|
| HOLY CRAP! this could help me immensly working on my GB Emulator :O this is awesome man |
| |
|
| Back to top |
|
 |
|
|
Posted: May 22, 2008 17:02 Post subject: |
|
|
Hey thanks :p
I'm glad it'll be useful for someone :) |
| |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|