Luig Posted October 8, 2010 Share Posted October 8, 2010 Alright I attempted to port a chip8 emulator in vb6 to autoit. The result is AutoChip. Although it isn't fully functional its a start. It seems to emulate sound correctly but something went wrong in the video. The result varies with different roms. Haven't implemented input yet. My hope is that it can be written in pure autoit if not I will have to code a lib for it in Delphi since I am not fluent in C. Chip8 UDF: expandcollapse popup#cs ---------------------------------------------------------------------------- AutoIt Version: 3.3.6.1 Author: Luig Script Function: CHIP8 Emulator Internal Functions. #ce ---------------------------------------------------------------------------- #include-once #include <GuiConstantsEx.au3> #include <GDIPlus.au3> #include <EditConstants.au3> #include <WindowsConstants.au3> Dim $ram[8193] Dim $stack[257] Dim $v[257] Dim $keydef[17] Global $opcode1, $opcode2, $opcode3, $opcode4, $sp, $key_up, $key_down Global $delaytimer, $soundtimer, $x, $y, $i, $j, $dbg, $Pause, $pc, $Index Global $key_choice $keydef[1] = 103 $keydef[2] = 104 $keydef[3] = 105 $keydef[4] = 100 $keydef[5] = 101 $keydef[6] = 102 $keydef[7] = 97 $keydef[8] = 98 $keydef[9] = 99 $keydef[10] = 96 $keydef[11] = 111 $keydef[12] = 106 $keydef[13] = 107 $keydef[14] = 13 $keydef[15] = 103 $keydef[16] = 110 $dbg = True If $dbg Then $Debug = GUICreate("Debug", 387, 211, 192, 124) $Edit1 = GUICtrlCreateEdit("", 0, 0, 385, 209) GUISetState(@SW_SHOW) EndIf _GDIPlus_Startup() Global $hScreen Global $Black = _GDIPlus_PenCreate(0xFF00FF00) Global $White = _GDIPlus_PenCreate(0xFFFFFFFF) Func OpenRom($File) $a = 1 For $i = 1 to StringLen($File) $ram[0x200 - 1 + $i] = '0x' & StringMid($File, $a, 2) $a += 2 Next Restart_CPU() EndFunc Func Restart_CPU() $pc = 0x200 $ram[0x1000] = 96 $ram[0x1001] = 144 $ram[0x1002] = 144 $ram[0x1003] = 144 $ram[0x1004] = 96 $ram[0x1005] = 96 $ram[0x1006] = 224 $ram[0x1007] = 96 $ram[0x1008] = 96 $ram[0x1009] = 240 $ram[0x100A] = 96 $ram[0x100B] = 144 $ram[0x100C] = 32 $ram[0x100D] = 64 $ram[0x100E] = 240 $ram[0x100F] = 224 $ram[0x1010] = 16 $ram[0x1011] = 96 $ram[0x1012] = 16 $ram[0x1013] = 224 $ram[0x1014] = 160 $ram[0x1015] = 160 $ram[0x1016] = 240 $ram[0x1017] = 32 $ram[0x1018] = 32 $ram[0x1019] = 240 $ram[0x101A] = 128 $ram[0x101B] = 240 $ram[0x101C] = 16 $ram[0x101D] = 240 $ram[0x101E] = 240 $ram[0x101F] = 128 $ram[0x1020] = 240 $ram[0x1021] = 144 $ram[0x1022] = 240 $ram[0x1023] = 240 $ram[0x1024] = 16 $ram[0x1025] = 32 $ram[0x1026] = 64 $ram[0x1027] = 128 $ram[0x1028] = 96 $ram[0x1029] = 144 $ram[0x102A] = 96 $ram[0x102B] = 144 $ram[0x102C] = 96 $ram[0x102D] = 240 $ram[0x102E] = 144 $ram[0x102F] = 240 $ram[0x1030] = 16 $ram[0x1031] = 240 $ram[0x1032] = 96 $ram[0x1033] = 144 $ram[0x1034] = 240 $ram[0x1035] = 144 $ram[0x1036] = 144 $ram[0x1037] = 224 $ram[0x1038] = 144 $ram[0x1039] = 224 $ram[0x103A] = 144 $ram[0x103B] = 224 $ram[0x103C] = 112 $ram[0x103D] = 128 $ram[0x103E] = 128 $ram[0x103F] = 128 $ram[0x1040] = 112 $ram[0x1041] = 224 $ram[0x1042] = 144 $ram[0x1043] = 144 $ram[0x1044] = 144 $ram[0x1045] = 224 $ram[0x1046] = 240 $ram[0x1047] = 128 $ram[0x1048] = 224 $ram[0x1049] = 128 $ram[0x104A] = 240 $ram[0x104B] = 240 $ram[0x104C] = 128 $ram[0x104D] = 224 $ram[0x104E] = 128 $ram[0x104F] = 128 Emulate_CPU() EndFunc Func Emulate_CPU() Sleep(10) If $delaytimer > 1 Then $delaytimer -= 1 If $Pause = False Then Interpret() EndFunc Func getopcode() $opcode1 = BitAND($ram[$pc], 0xF0) $opcode1 /= 2 $opcode1 /= 2 $opcode1 /= 2 $opcode1 /= 2 $opcode2 = BitAND($ram[$pc], 0xF) $opcode3 = BitAND($ram[$pc + 1], 0xF0) $opcode3 /= 2 $opcode3 /= 2 $opcode3 /= 2 $opcode3 /= 2 $opcode4 = BitAND($ram[$pc + 1], 0xF) $pc += 2 EndFunc Func Timer() If $delaytimer > 0 Then $delaytimer = $delaytimer - 1 If $soundtimer > 0 Then $soundtimer = $soundtimer - 1 Beep(500, $soundtimer * 10) $soundtimer = 0 EndIf EndFunc Func Interpret() getopcode() If $dbg Then Print(($pc - 2) & ': ' & $opcode1 & ' ' & $opcode2 & ' ' & $opcode3 & ' ' & $opcode4) Switch $opcode1 Case 0x00 Switch $opcode3 Case 0x0E Switch $opcode4 Case 0x00 If $dbg Then Print('ClearScreen') ClearScreen() Case 0x0E If $dbg Then Print('ReturnFromSub') ReturnFromSub() EndSwitch EndSwitch Case 0x01 If $dbg Then Print('JumpToAddress') JumpToAddress() Case 0x02 If $dbg Then Print('JumpToSub') JumpToSub() Case 0x03 If $dbg Then Print('SkipIfRegEqual') SkipIfRegEqual() Case 0x04 If $dbg Then Print('SkipIfRegNotEqual') SkipIfRegNotEqual() Case 0x05 If $dbg Then Print('SkipIfRegEqualReg') SkipIfRegEqualReg() Case 0x06 If $dbg Then Print('LoadRegWithConstant') LoadRegWithConstant() Case 0x07 If $dbg Then Print('AddConstantToReg') AddConstantToReg() Case 0x08 Switch $opcode4 Case 0x00 If $dbg Then Print('LoadRegWithReg') LoadRegWithReg() Case 0x01 If $dbg Then Print('OrRegWithReg') OrRegWithReg() Case 0x02 If $dbg Then Print('AndRegWithReg') AndRegWithReg() Case 0x03 If $dbg Then Print('XorRegWithReg') XorRegWithReg() Case 0x04 If $dbg Then Print('AddRegToReg') AddRegToReg() Case 0x05 If $dbg Then Print('SubRegFromReg') SubRegFromReg() Case 0x06 If $dbg Then Print('ShiftRegRight') ShiftRegRight() Case 0x07 If $dbg Then Print('RSubRegFromReg') RSubRegFromReg() Case 0x0E If $dbg Then Print('ShiftRegLeft') ShiftRegLeft() EndSwitch Case 0x09 If $dbg Then Print('SkipIfRegNotEqualReg') SkipIfRegNotEqualReg() Case 0x0A If $dbg Then Print('LoadIndexWithConstant') LoadIndexWithConstant() Case 0x0B If $dbg Then Print('JumpToAddressPlusReg0') JumpToAddressPlusReg0() Case 0x0C If $dbg Then Print('CreateRandomNumber') CreateRandomNumber() Case 0x0D If $dbg Then Print('DrawSprite') DrawSprite() Case 0x0E Switch $opcode3 Case 0x09 If $dbg Then Print('SkipIfKeyPressed') SkipIfKeyPressed() Case 0x0A If $dbg Then Print('SkipIfKeyNotPressed') SkipIfKeyNotPressed() EndSwitch Case 0x0F Switch $opcode3 Case 0x00 Switch $opcode4 Case 0x07 If $dbg Then Print('GetDelayTimerIntoReg') GetDelayTimerIntoReg() Case 0x0A If $dbg Then Print('WaitForKeyPress') WaitForKeyPress() EndSwitch Case 0x01 Switch $opcode4 Case 0x05 If $dbg Then Print('SetDelayTimer') SetDelayTimer() Case 0x08 If $dbg Then Print('SetSoundTimer') SetSoundTimer() Case 0x0E If $dbg Then Print('AddRegToIndex') AddRegToIndex() EndSwitch Case 0x02 If $dbg Then Print('PointIndexToFont') PointIndexToFont() Case 0x03 If $dbg Then Print('StoreBCD') StoreBCD() Case 0x05 If $dbg Then Print('StoreRegsAtIndex') StoreRegsAtIndex() Case 0x06 If $dbg Then Print('LoadRegsFromIndex') LoadRegsFromIndex() EndSwitch EndSwitch EndFunc Func ClearScreen() _GDIPlus_GraphicsClear($hScreen, 0x00FFFFFF) EndFunc Func ReturnFromSub() $sp -= 1 $pc = $stack[$sp] EndFunc Func JumpToAddress() For $a = 1 To 8 $opcode2 *= 2 Next For $a = 1 To 4 $opcode3 *= 2 Next $pc = $opcode2 + $opcode3 + $opcode4 EndFunc Func JumpToSub() $stack[$sp] = $pc $sp += 1 For $a = 1 To 8 $opcode2 *= 2 Next For $a = 1 To 4 $opcode3 *= 2 Next $pc = $opcode2 + $opcode3 + $opcode4 EndFunc Func SkipIfRegEqual() For $a = 1 To 4 $opcode3 *= 2 Next If $v[$opcode2] = ($opcode3 + $opcode4) Then $pc +=2 EndFunc Func SkipIfRegNotEqual() For $a = 1 To 4 $opcode3 *= 2 Next If $v[$opcode2] <> ($opcode3 + $opcode4) Then $pc += 2 EndFunc Func SkipIfRegEqualReg() If $v[$opcode2] = $v[$opcode3] Then $pc += 2 EndFunc Func SkipIfRegNotEqualReg() If $v[$opcode2] <> $v[$opcode3] Then $pc += 2 EndFunc Func LoadRegWithConstant() For $a = 1 To 4 $opcode3 *= 2 Next $v[$opcode2] = ($opcode3 + $opcode4) EndFunc Func AddConstantToReg() For $a = 1 To 4 $opcode3 *= 2 Next $x = $v[$opcode2] + ($opcode3 + $opcode4) If $x > 255 Then $x -= 256 $v[$opcode2] = $x EndFunc Func LoadRegWithReg() $v[$opcode2] = $v[$opcode3] EndFunc Func OrRegWithReg() $v[$opcode2] = BitOR($v[$opcode2], $v[$opcode3]) EndFunc Func AndRegWithReg() $v[$opcode2] = BitAND($v[$opcode2], $v[$opcode3]) EndFunc Func XorRegWithReg() $v[$opcode2] = BitXOR($v[$opcode2], $v[$opcode3]) EndFunc Func AddRegToReg() Local $x If $v[$opcode2] >= $v[$opcode3] Then $v[0x0F] = 1 Else $v[0x0F] = 0 EndIf $x = $v[$opcode2] $x -= $v[$opcode3] If $x < 0 Then $x += 256 $v[$opcode2] = $x EndFunc Func SubRegFromReg() Local $x If $v[$opcode2] >= $v[$opcode3] Then $v[0x0F] = 1 Else $v[0x0F] = 0 EndIf $x = $v[$opcode2] $x = $x - $v[$opcode3] If $x < 0 Then $x = $x + 256 $v[$opcode2] = $x EndFunc Func ShiftRegRight() If BitAND($v[$opcode2], 1) Then $v[0x0F] = 1 Else $v[0x0F] = 0 EndIf $v[$opcode2] /= 2 EndFunc Func RSubRegFromReg() Local $x If $v[$opcode2] >= $v[$opcode3] Then $v[0x0F] = 1 Else $v[0x0F] = 0 EndIf $x = $v[$opcode3] $x -= $v[$opcode2] If $x < 0 Then $x += 256 $v[$opcode2] = $x EndFunc Func ShiftRegLeft() If BitAND($v[0x0F], 128) Then $v[0x0F] = 1 Else $v[0x0F] = 0 EndIf $x = $v[$opcode2] * 2 If $x > 255 Then $x -= 256 $v[$opcode2] = $x EndFunc Func LoadIndexWithConstant() For $a = 1 To 8 $opcode2 *= 2 Next For $a = 1 To 4 $opcode3 *= 2 Next $Index = $opcode2 + $opcode3 + $opcode4 EndFunc Func JumpToAddressPlusReg0() For $a = 1 To 8 $opcode2 *= 2 Next For $a = 1 To 4 $opcode3 *= 2 Next $pc = $v[0] + $opcode2 + $opcode3 + $opcode4 EndFunc Func CreateRandomNumber() For $a = 1 To 4 $opcode3 *= 2 Next $v[$opcode2] = BitAND(Int(Random() * 256), ($opcode3 + $opcode4)) EndFunc Func DrawSprite() $v[0x0F] = 0 For $j = 0 To $opcode4 - 1 $datax = $ram[$Index + $j] $i = 0 $x = $v[$opcode2] * 4 $y = $v[$opcode4] * 4 If $datax >= 128 Then drawscreen() $datax -= 128 EndIf $i += 1 If $datax >= 64 Then drawscreen() $datax -= 64 EndIf $i += 1 If $datax >= 32 Then drawscreen() $datax -= 32 EndIf $i += 1 If $datax >= 16 Then drawscreen() $datax -= 16 EndIf $i += 1 If $datax >= 8 Then drawscreen() $datax -= 8 EndIf $i += 1 If $datax >= 4 Then drawscreen() $datax -= 4 EndIf $i += 1 If $datax >= 2 Then drawscreen() $datax -= 2 EndIf $i += 1 If $datax >= 1 Then drawscreen() $datax -= 1 EndIf Next EndFunc Func drawscreen() Local $pointx, $pointy, $height, $width $pointx = 1 + $x + ($i * 4) $pointy = $y + ($j * 4) $width = (1 + $x + ($i * 4) + 3) - $pointx $height = ($y + ($j * 4) + 3) - $pointy If _PixelGetColor_GetPixel($hScreen, 1 + $x + ($i * 4), $y + ($j * 4)) = 0x00FF00 Then _GDIPlus_GraphicsDrawRect($hScreen, $pointx, $pointy, $width, $height, $White) ;_GDIPlus_GraphicsDrawLine($hScreen, 1 + $x + ($i * 4), $y + ($j * 4), 1 + $x + ($i * 4) + 3, $y + ($j * 4) + 3, $White) Else _GDIPlus_GraphicsDrawRect($hScreen, $pointx, $pointy, $width, $height, $Black) ;_GDIPlus_GraphicsDrawLine($hScreen, 1 + $x + ($i * 4), $y + ($j * 4), 1 + $x + ($i * 4) + 3, $y + ($j * 4) + 3, $Black) EndIf EndFunc Func SkipIfKeyPressed() If $key_down = $v[$opcode2] Then $pc += 2 EndFunc Func SkipIfKeyNotPressed() If $key_down <> $v[$opcode2] Then $pc += 2 EndFunc Func WaitForKeyPress() $key_down = 0 While $key_down = 0 Sleep(1) WEnd $v[$opcode2] = $key_down EndFunc Func SetDelayTimer() $delaytimer = $v[$opcode2] EndFunc Func GetDelayTimerIntoReg() $v[$opcode2] = $delaytimer EndFunc Func SetSoundTimer() $soundtimer = $v[$opcode2] EndFunc Func AddRegToIndex() $Index += $v[$opcode2] EndFunc Func PointIndexToFont() $Index = 0x1000 + ($v[$opcode2] * 0x05) EndFunc Func StoreBCD() $num = $v[$opcode2] For $i = 3 To 1 Step -1 $ram[$Index + ($i - 2)] = Mod($num, 10) $num /= 10 Next EndFunc Func StoreRegsAtIndex() For $i = 0 To $opcode2 $ram[$index + $i] = $v[$i] Next EndFunc Func LoadRegsFromIndex() For $i = 0 To $opcode2 $v[$i] = $ram[$Index + $i] Next EndFunc Func Print($String) GUICtrlSetData($Edit1, GUICtrlRead($Edit1) & @CRLF & $String) EndFunc Func _PixelGetColor_GetPixel($iPixelGetColor_MemoryContext,$iX,$iY, $hDll = "gdi32.dll") $iColor = DllCall($hDll,"int","GetPixel","int",$iPixelGetColor_MemoryContext,"int",$iX,"int",$iY) If $iColor[0] = -1 then Return SetError(1,0,-1) $sColor = Hex($iColor[0],6) Return StringRight($sColor,2) & StringMid($sColor,3,2) & StringLeft($sColor,2) EndFunc Emulator: expandcollapse popup#cs ---------------------------------------------------------------------------- AutoIt Version: 3.3.6.1 Author: Luig Script Function: GUI of Emulator. #ce ---------------------------------------------------------------------------- #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include 'CHIP8v2.au3' $Form1 = GUICreate("AutoChip v 1.0", 270, 134, 374, 138) GUISetState(@SW_SHOW) $hScreen = _GDIPlus_GraphicsCreateFromHWND($Form1) ClearScreen() $File = FileOpen(@ScriptDir & '\Pong (19xx)(-)(Chip-8).ch8', 16) $Raw = FileRead($File) FileClose($File) OpenRom(StringTrimLeft($Raw, 2)) ;AdlibRegister('Timer', 17) While 1 Timer() Emulate_CPU() $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit EndSwitch WEnd You can get the VB Source here : http://www.zophar.net/chip8/vb-chip-8.html oHenry 1 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now