Z3 - Emulator

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

DAK

Betreff: Z3 - Emulator

BeitragMi, Sep 23, 2009 0:43
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragMi, Sep 23, 2009 11:00
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragMi, Sep 23, 2009 14:05
Antworten mit Zitat
Benutzer-Profile anzeigen
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

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group