Z3 - Emulator
Übersicht

![]() |
DAKBetreff: Z3 - Emulator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Leute, mir war langweilig und darum hab ich mal was gemacht, was ich schon lange machen wollte:
ich hab einen emulator für einen historischen computer... der einfachheithalber hab ich gleich mal den ersten funktionsfähigen digitalrechner der welt dafür misbraucht. falls es iwen intressiert (was ich nicht soo unbedingt erwarte): das hier ist ein Zuse Z3 - Emulator: Code: [AUSKLAPPEN] SuperStrict Framework brl.standardio Import brl.retro Import brl.polledinput Import brl.filesystem Import dak.stringstream Const USEREALTIME:Byte=1 Const USEDEBUG:Byte=1 Type TZ3 Field RAM:Float[63] Field Register:Float[2] Field Program:Byte[] Field ProgramCounter:Short Field ProgramMax:Short Field Read:Byte=0 Function Create:TZ3(code:String) Local tmp:TZ3 = New TZ3 tmp.CompileProgram(code) Return tmp End Function Method LoadCodeFile:TZ3(URL:String) Local stream:TStream = OpenStream(URL) Local code:String While Not Eof(stream) code:+ReadLine(stream)+"~n" Wend Return Create(code) End Method Method LoadBinaryFile:TZ3(URL:String) Local tmp:TZ3 = New TZ3 Program = New Byte[FileSize(URL)] Local stream:TStream = OpenStream(URL) Local ct:Short While Not Eof(stream) Program[ct] = ReadByte(stream) ct:+1 Wend Return tmp End Method Method Run:Byte() Local ln:Byte = Program[ProgramCounter] ProgramCounter:+1 If ProgramCounter=ProgramMax Then Return 0 If ln=96 Then 'Add La If USEDEBUG Then Print "La" Delay 188*3*USEREALTIME Register[0]:+Register[1] Register[1]=0 ElseIf ln=80 Then 'Div Li If USEDEBUG Then Print "Li" Delay 188*18*USEREALTIME Register[0]:/Register[1] Register[1]=0 ElseIf ln=112 Then 'Input Lu If USEDEBUG Then Print "Lu" Local inp:String =Trim(Input("<<")) Register[0]=Float(inp) Delay 188*25*USEREALTIME ElseIf ln=72 Then 'Mul Lm If USEDEBUG Then Print "Lm" Delay 188*16*USEREALTIME Register[0]:*Register[1] Register[1]=0 ElseIf ln=104 Then 'Sub Ls If USEDEBUG Then Print "Ls" Delay 188*4.5*USEREALTIME Register[0]:-Register[1] Register[1]=0 ElseIf ln=88 Then 'Sqr Lw If USEDEBUG Then Print "Lw" Delay 188*20*USEREALTIME Register[0]=Sqr(Register[0]) Register[1]=0 ElseIf ln=120 Then 'Out Ld If USEDEBUG Then Print "Ld" Delay 188*25*USEREALTIME Print(">>"+Register[0]) ElseIf ln=65 Then 'SPc Sc If USEDEBUG Then Print "Sc" Delay 188*USEREALTIME ProgramCounter=Short(Register[0]) Register[1]=0 ElseIf Left(bin2(ln),2)="10" Then 'Save Ps If USEDEBUG Then Print "Ps" Delay 188*USEREALTIME Ram[Byte(Mid(bin2(ln),3))] = Register[0] ElseIf Left(bin2(ln),2)="11" Then 'Read Pr If USEDEBUG Then Print "Pr" Delay 188*.5*USEREALTIME Register[Read] = Ram[Byte(Mid(bin2(ln),3))] If Read=0 Then Read=1 EndIf Return 1 End Method Method CompileProgram:String(code:String) Local stream:TStringStream = CreateStringStream(code,"~n") Local i:Int = 0 While Not Eos(stream) stream.ReadLine() i:+1 Wend ProgramMax=i SetStringPos(stream,0) Program = New Byte[i] For Local v:Int=0 To i Local ln:String = Lower(Trim(stream.ReadLine())) If ln = "la" Then Program[v] = Byte("%01100000") ElseIf ln = "li" Then Program[v] = Byte("%01010000") ElseIf ln = "lu" Then Program[v] = Byte("%01110000") ElseIf ln = "lm" Then Program[v] = Byte("%01001000") ElseIf ln = "ls" Then Program[v] = Byte("%01101000") ElseIf ln = "lw" Then Program[v] = Byte("%01011000") ElseIf ln = "ld" Then Program[v] = Byte("%01111000") ElseIf ln = "sc" Then Program[v] = Byte("%01000001") ElseIf Left(ln,2) = "ps" Then Program[v] = Byte("%10"+Bin2(Int(Trim(Mid(ln,4))))) ElseIf Left(ln,2) = "pr" Then Program[v] = Byte("%11"+Bin2(Int(Trim(Mid(ln,4))))) EndIf Next End Method End Type Function Bin2:String(val:Int) Local out:String = Bin(val) Local l:Byte = Len(out) For Local i:Byte=0 To l If Left(out,1) = 0 Then out=Mid(out,2) Next Return out End Function Local code:String = "Lu~nPs 0~nPr 0~nPr 0~nLm~nLd~nPs 0~nPr 0~nLs~nSc" Local Z3:TZ3 = TZ3.Create(code) While 1 If Z3.Run()=0 Then End Wend Das ganze kann Z3-Assembler- und Z3-Binary-Dateien oder auch direkte Z3-Assembler-Codes verarbeiten. Mit dabei ist gleich ein Programm, dass das Quadrat der eingegebenen Zahl ausgibt. Die Assemblerbefehle inklusive Opcodes: Code: [AUSKLAPPEN] 01.100000 La R1=R1+R2, R2=0
01.010000 Li R1=R1/R2, R2=0 01.110000 Lu R1 <- Bin(Input) 01.001000 Lm R1=R1*R2, R2=0 01.101000 Ls R1=R1-R2, R2=0 01.011000 Lw R1=Sqr(R1), R2=0 01.111000 Ld Print Dec(R1) 01.000001 Sc ProgrammCounter=R1 <- Diesen hier hab ich mir nicht verkneifen können selbst hinzu zu fügen. war in der Original-Z3 nicht enthalten. 10.zzzzzz Ps z RAM[z]=R1 11.zzzzzz Pr z R1\R2=RAM[z] Edit: um das feeling aufkommen zu lassen, dass es wohl gehabt hat, an dem ding zu coden, hab ich noch eine option eingebaut. wenn man USEREALTIME auf 1 setzt, dann arbeitet der emulator genauso schnell wie das originalteil. (also seeehr langsam ^^ 5.3 Hz) und damit dabei das zuschauen nicht allzu langweilig wird hab ich noch eine option eingebaut: USEDEBUG gibt aus, was der emulator gerade macht. natürlich nicht in klartext sondern in assembler. |
||
Gewinner der 6. und der 68. BlitzCodeCompo |
![]() |
Firstdeathmaker |
![]() Antworten mit Zitat ![]() |
---|---|---|
Schon ziemlich cool...
nur irgendwie verstehe ich das mit deinem Program nicht: Wenn ich das Program starte, bekomme ich: Zitat: Ps
Pr Pr Lm Ld >>0.000000000 Ps Pr Ls Sc Ps Pr Pr Lm Ld >>0.000000000 Ps Pr Ls Sc Ps Pr Pr Lm Ld >>0.000000000 Ps Pr Ls Aber der Programmcode welchen du ihm gibst, sieht doch folgendermaßen aus: Zitat: Lu Ps 0 Pr 0 Pr 0 Lm Ld Ps 0 Pr 0 Ls Sc Demnach müsste doch ersteinmal ein Input kommen, oder? Genau das seh ich aber nicht. Weiter Untersuchungen ergeben, dass es schon beim kompilieren nicht mit übersetzt wird. Vielleicht ist das benötigte dak.stringstream defekt? Ist die hier im Module-Forum gepostete Version up-to-date? Ach ja, die HP in deiner Sig ist nicht erreichbar. |
||
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon Gewinner des BCC #57 User posted image |
![]() |
DAK |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hmm... war die StringStream-Version, die ich verwend inzwischen eine andere, als die dies hier im forum gibt.. egal. ich hab das ganze mal schnell umgeschrieben, dass dak.stringstream nicht mehr verwendet wird.
Code: [AUSKLAPPEN] SuperStrict Framework brl.standardio Import brl.retro Import brl.polledinput Import brl.filesystem Const USEREALTIME:Byte=1 Const USEDEBUG:Byte=1 Type TZ3 Field RAM:Float[64] Field Register:Float[2] Field Program:Byte[] Field ProgramCounter:Short Field ProgramMax:Short Field Read:Byte=0 Field InpHelp:Byte=1 Function Create:TZ3(code:String) Local tmp:TZ3 = New TZ3 tmp.CompileProgram(code) Return tmp End Function Method LoadCodeFile:TZ3(URL:String) Local stream:TStream = OpenStream(URL) Local code:String While Not Eof(stream) code:+ReadLine(stream)+"~n" Wend Return Create(code) End Method Method LoadBinaryFile:TZ3(URL:String) Local tmp:TZ3 = New TZ3 Program = New Byte[FileSize(URL)] Local stream:TStream = OpenStream(URL) Local ct:Short While Not Eof(stream) Program[ct] = ReadByte(stream) ct:+1 Wend Return tmp End Method Method InputRAM:Byte() If InpHelp Then Print "INPUT~n(Zelle:Wert) 'END' um die Eingabe zu beenden";InpHelp=0 Local in:String = Input("<-") If Lower(Trim(in)) = "end" Then Print "INPUT ENDED~n";Return 0 in = Replace(in," ","") Local pos:Byte = Instr(in,":") RAM[Int(Left(in,pos-1))] = Float(Mid(in,pos+1)) Return 1 End Method Method Run:Byte() If ProgramCounter=ProgramMax Then Return 0 Local ln:Byte = Program[ProgramCounter] ProgramCounter:+1 If ln=96 Then 'Add La If USEDEBUG Then Print "La" Delay 188*3*USEREALTIME Register[0]:+Register[1] Register[1]=0 ElseIf ln=80 Then 'Div Li If USEDEBUG Then Print "Li" Delay 188*18*USEREALTIME Register[0]:/Register[1] Register[1]=0 ElseIf ln=112 Then 'Input Lu If USEDEBUG Then Print "Lu" Local inp:String =Trim(Input("<<")) Register[0]=Float(inp) Delay 188*25*USEREALTIME ElseIf ln=72 Then 'Mul Lm If USEDEBUG Then Print "Lm" Delay 188*16*USEREALTIME Register[0]:*Register[1] Register[1]=0 ElseIf ln=104 Then 'Sub Ls If USEDEBUG Then Print "Ls" Delay 188*4.5*USEREALTIME Register[0]:-Register[1] Register[1]=0 ElseIf ln=88 Then 'Sqr Lw If USEDEBUG Then Print "Lw" Delay 188*20*USEREALTIME Register[0]=Sqr(Register[0]) Register[1]=0 ElseIf ln=120 Then 'Out Ld If USEDEBUG Then Print "Ld" Delay 188*25*USEREALTIME Print(">>"+Register[0]) ElseIf ln=65 Then 'SPc Sc If USEDEBUG Then Print "Sc" Delay 188*USEREALTIME ProgramCounter=Short(Register[0]) Register[1]=0 ElseIf Left(bin2(ln),2)="10" Then 'Save Ps If USEDEBUG Then Print "Ps "+Int("%"+Right(bin2(ln),6)) Delay 188*USEREALTIME Ram[Byte("%"+Right(Bin(ln),6))] = Register[0] ElseIf Left(bin2(ln),2)="11" Then 'Read Pr If USEDEBUG Then Print "Pr "+Int("%"+Right(bin2(ln),6)) Delay 188*.5*USEREALTIME Register[Read] = Ram[Byte("%"+Right(Bin(ln),6))] If Read=0 Then Read=1 EndIf Return 1 End Method Method CompileProgram:String(code:String) Local codesplit:String[] = code.split("~n") ProgramMax=codesplit.length Program = New Byte[codesplit.length] If USEDEBUG Then Print "COMPILING" For Local i:Int=0 To codesplit.length-1 Local ln:String = Lower(Trim(codesplit[i])) If ln = "la" Then Program[i] = Byte("%01100000") ElseIf ln = "li" Then Program[i] = Byte("%01010000") ElseIf ln = "lu" Then Program[i] = Byte("%01110000") ElseIf ln = "lm" Then Program[i] = Byte("%01001000") ElseIf ln = "ls" Then Program[i] = Byte("%01101000") ElseIf ln = "lw" Then Program[i] = Byte("%01011000") ElseIf ln = "ld" Then Program[i] = Byte("%01111000") ElseIf ln = "sc" Then Program[i] = Byte("%01000001") ElseIf Left(ln,2) = "ps" Then Program[i] = Byte("%10"+Right(Bin(Int(Trim(Mid(ln,4)))),6)) ElseIf Left(ln,2) = "pr" Then Program[i] = Byte("%11"+Right(Bin(Int(Trim(Mid(ln,4)))),6)) EndIf If USEDEBUG Then Print Lower(Trim(codesplit[i]))+" "+Program[i] Next If USEDEBUG Then Print "COMPILING ENDED~n" End Method End Type Function Bin2:String(val:Int) Local out:String = Bin(val) Local l:Byte = Len(out) For Local i:Byte=0 To l If Left(out,1) = 0 Then out=Mid(out,2) Next Return out End Function Local code:String = "Lu~nPs 0~nPr 0~nPr 0~nLm~nLd~nPs 0~nPr 0~nLs~nSc" Local Z3:TZ3 = TZ3.Create(code) While Z3.InputRAM() Wend While Z3.Run() Wend End Desweiteren wird der kompilierte code angezeigt, wenn debug aktiviert ist. bei den befehlen Ps und Pr wird im Debugmode jetzt auch die verwendete Speicherzelle angezeigt. und noch eine weiter funktion der Z3 hab ich eingebaut: man kann, bevor man das programm laufen lässt, die speicherzellen füllen. hier noch ein paar kleine Programme: Code: [AUSKLAPPEN] Lu
Ps 5 Pr 4 Lm Pr 3 La Pr 5 Lm Pr 2 La Pr 5 Lm Pr 1 La Ld Lu~nPs 5~nPr 4~nPr 5~nLm~nPr 3~nLa~nPr 5~nLm~nPr 2~nLa~nPr 5~nLm~nPr 1~nLa~nLd Dieses hier rechnet den Term (((a1+a2)*x+a3)*x+a4)*x aus, wobei a1-4 von anfang im RAM vorhanden sein muss und x eingegeben wird. Code: [AUSKLAPPEN] Lu
Ps 1 Lu Ps 2 Lu Ps 3 Lu Ps 4 Lu Ps 5 Pr 1 Pr 2 La Pr 5 Lm Pr 3 La Pr 5 Lm Pr 4 La Pr 5 Lm Ld Lu~nPs 1~nLu~nPs 2~nLu~nPs 3~nLu~nPs 4~nLu~nPs 5~nPr 1~nPr 2~nLa~nPr 5~nLm~nPr 3~nLa~nPr 5~nLm~nPr 4~nLa~nPr 5~nLm~nLd macht das gleiche, nur dass a1-4 + x im laufenden Programm eingegeben werden müssen. |
||
Gewinner der 6. und der 68. BlitzCodeCompo |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group