| |
|
|
- Seite 1 - |
|
HofK | Auf einen heißen Tipp von IF hin, habe ich mir mal three.js [...] angeschaut. Da [...] (ganz unten) die ersten Resultate. |
|
|
| |
|
|
| |
|
- Seite 39 - |
|
|
| Statt 0{px|vh|...} kann man einfach 0 schreiben (ohne Einheit) - (bei "Tippfaulheit" kann man es aber auch stehen lassen).
wg. Reihenfolge(n):
Auch bei CSS ist die Reihenfolge wichtig, spätere Deklarationen überschreiben Vorherige: Wenn Du also Stile erst für den Body festlegst und danach Stile für * (="alles"), dann würden die in * definierten Werte die zuvor in body Definierten überschreiben.
Beim Slider kann ich auch noch eine 100%-Width-Angabe erkennen - aber hier wird scheinbar das Background-Image skaliert - dafür gibt es wiederum die background-size -Eigenschaft - in meinen ersten Tests dies dort aber wohl noch nicht die Lösung zu sein scheint. |
|
|
| |
|
|
|
HofK | Ich hatte mich bisher immer mit der "Erkenntnis" begnügt, dass body an der Basis steht. Ist doch komplizierter, eine Suche ergab entsprechende Anfagen bei Experten auf stackoverflow.com.
Die Funktion der selbst gezimmerten Auswahlboxen ist auch nicht ganz trivial.
Aber es funktioniert wie gedacht. Allerdings eignet sich meine Lösung nur für eine kleine Anzahl solcher Boxen auf der Seite. Ich benötige nur 3 Stück.
Bei den Mnemonics ist die Auswahl mit Eintrag in das Eingabefeld bereits realisiert.
( /dev Seite ) |
|
|
| |
|
|
|
HofK | Die Zuordnung der 8 Bit Maschinenbefehle zu den Assembler-Mnemonics und den Operanden ist eine recht umfangreiche XProfan Prozedur.
proc assembler_to_binary_code ' Assembler --> Binärcode
Ich habe sie zwar einfach in mein Javascript kopieren können, aber dann geht die Arbeit erst richtig los.
Bei der Entwicklung der "höheren" Programmiersprachen in den letzten mehr als 60 Jahren, sind die Autoren nicht sehr einheitlich vorgegangen. Zwar ist das Vokabular ( bzw. die Abkürzungen ) in der Regel der englischen Sprache entnommen, aber für eine Sache werden trotzdem verschiedene Bezeichner benutzt. Und dann die unterschiedlichen Trennzeichen und Klammerungen. Da kann man leicht den Überblick verlieren.
Aus select mn$ ... endselect wird switch( mn$ ) { ... }
und die Fälle ändern sich von z.B. caseof "NOP" zu case "NOP":
Macht man aus caseof per Ersetzung case, fehlt noch der Doppelpunkt und man bemerkt hinterher, dass da schon ein case in XProfan war!
case mn$="JIN" : oc$ = "000"+"0"+"10"+"01"
Hätte man vorher zu einem if( mn$ === "JIN" ) oc$ = "000"+"0"+"10"+"01"; machen sollen.
Mit etwas Geduld ist es aber geschafft!
Ein weiteres Problem ist das unterschiedliche Ereignismodell.
In XProfan habe ich mit einer verschachtelten Ereignisabfrage gearbeitet.
repeat' >>>>>> Ereignisschleife Halt/Weiter/Einzelschritt und MGA-Display >>>>>>>
'------- (äussere Ereignisschleife)
waitinput
'-------
...
repeat' innere Ereignisschleife
'........
waitinput' EREIGNISABFRAGE für mögliche Aktionen: X STOP Programm / weiter ausführen / einen Befehl weiter
'........
...
Im Browser benutzt man Ereignis-Lauscher in der Form
mn.addEventListener( 'input', onMnInput );
für jedes Element und jedes Ereignis und ordnet dem eine Funktion zu.
Das wirft den ganzen Algorithmus in seiner Struktur über den Haufen. Man muss es gänzlich neu strukturieren.
Auf /dev [...] funktioniert jetzt erst einmal der Eintrag des 8 Bit Binärcodes in das Feld Op Code links neben Mnemonic.
Beim Test darauf achten, dass nur gültige Befehle zu einem sinnvollen Ergebnis führen, unsinnige Kombinationen ergeben immer den NOP Befehl 00000000. |
|
|
| |
|
|
|
HofK | Der Anfang für die Verbindung von 2D HTML/CSS GUI und 3D three.js RAM ist gemacht. Die binären Operationscodes werden in den RAM übertragen.
Allerdings ist die Sache noch nicht vollständig. Die Funktion restore_instruction( ); muss noch realisiert werden und die Adresse wird noch dezimal angezeigt. Auch gibt es Abweichungen wegen des Ereignismodells.
function animate() {
// t += 0.005;
requestAnimationFrame( animate );
for ( let i = 0; i < 8 ; i ++ ) {
if ( oc$[i] ==='0' ) {
visibilityRAM( iMeshRamDig0, coderow, i, visible );
visibilityRAM( iMeshRamDig1, coderow, i, hidden );
} else {// === '1'
visibilityRAM( iMeshRamDig0, coderow, i, hidden );
visibilityRAM( iMeshRamDig1, coderow, i, visible );
}
Aktuell bei /dev
----- |
|
|
| |
|
|
|
p.specht
| Tolles Lehrmittel! Bedeutet restore_instruction(), dass dein Programm sogar disassemblieren kann? Frohe Festtage, Klaus! |
|
|
| XProfan 11Computer: Gerät, daß es in Mikrosekunden erlaubt, 50.000 Fehler zu machen, zB 'daß' statt 'das'... | 23.12.2020 ▲ |
|
|
|
|
HofK | Wenn man mit Hilfe der Buttons
im RAM vor und zurück geht, muss der Befehl (ebenso die Konstante) aus dem RAM wieder in der Programmieroberfläche rekonstruiert werden. Ansonsten wird der RAM Inhalt an der neuen Stelle mit den in der Oberfläche stehenden Werten überschrieben. Das ist gegenwärtig noch der Stand. Bald nicht mehr!
Der Code von XProfan muss angepasst übernommen werden.
'{--- Hilfsprozeduren Assembler ------
proc restore_instruction' Befehl (Eingabe) mit Kommentar wiederherstellen
settext mn% , left$( gettext$(RAM%, coderow%,3) , 3)' Mnemonic setzen
settext op1%, mid$( gettext$(RAM%, coderow%,3) , 5, 4)' Op 1 setzen
settext op2%, mid$( gettext$(RAM%, coderow%,3) ,10, 4)' Op 2 setzen
settext opcomm%, trim$(mid$(comment$[coderow%],2,255))' Kommentar zum Befehlsetzen
endproc
proc restore_const' Konstante (Eingabe) mit Kommentar wiederherstellen
settext coninp%, trim$( left$( gettext$(RAM%, conrow%,3) ,4) )
settext concomm%, trim$(mid$(comment$[conrow%],2,255))
endproc
proc restore_from_RAM' Befehl oder Konstante aus RAM mit Kommentar wiederherstellen
if (ramrow% > -1) AND (ramrow% < 128)' ramrow% ist -1 wenn auf "Teilzeile" am Ende der Gridbox geklickt wird!
coderow% = ramrow%
restore_instruction' Mnemonic Op1,2 und Kommentar in Eingabe-Edits setzen
endif
if (ramrow% > 127) AND (ramrow% < 256)
conrow% = ramrow%
restore_const' Konstante (Eingabe) mit Kommentar setzen
endif
endproc
Wird etwas aufwändiger, da der RAM in 3D gestaltet ist.
----------- |
|
|
| |
|
|
|
p.specht
| Die Industrie ätzt Chips ja mittlerweile auch in 3D bzw. viel-lagig. Anders wären die Smarthandys ja nie so flach zu kriegen. Faszinierend! |
|
|
| XProfan 11Computer: Gerät, daß es in Mikrosekunden erlaubt, 50.000 Fehler zu machen, zB 'daß' statt 'das'... | 24.12.2020 ▲ |
|
|
|
|
HofK | Bisher bestand der RAM nur aus den 8 Bit Zellen in 3D. Da der Mensch die vielen Nullen und Einsen geistig aber in der Regel nicht verkraftet, habe ich die Assemblerbefehle danebengestellt.
Nach einigen Tests habe ich mich entschieden, diese als THREE.PlaneBufferGeometry zu realisieren. Dabei wird der dynamische Inhalt mittels Canvas Textur dargestellt.
Das ist nicht echt 3D, aber three.js 3D Text ist zu aufwändig und diese "Hilfsdarstellung" würde zu sehr vom eigentlichen RAM mit Nullen und Einsen in den transparenten 3D Zellen ablenken.
Da instanced Meshes zwar unterschiedliche Farben und Positionen der einzelnen Meshes unterstützen [...] , nicht aber unterschiedliche Texturen, muss man ein Array von Rechtecken erzeugen und positionieren. Das Seitenverhältnis der PlaneBufferGeometry entspricht dem von canvas.
In der animate Funktion aktualisiert man den Text.
Dazu benutzt man die Funktion changeCanvas.
aktuell bei /dev |
|
|
| |
|
|
|
HofK | Beim RAM gab es noch einige Änderungen und er ist nun auch schon wesentlich funktioneller.
function changeCanvas( canvasTexture, ctx, txt ) ist nun function canvasSet( texture, ctx, bgr, w, h, txt )
Dazu kommt
um die aktuelle Assemblerzeile hervorzuheben. Bei XProfan erledigte das die Suche mit
in der Gridbox.
Hier sieht man, dass man Abläufe nicht so einfach übertragen kann.
Im Unterschied zur Windows Gridbox wird im Browser nur der Assemblerteil farblich hervorgehoben.
Man kann nun bereits im RAM (im Assemblerteil) herumklicken und dann links unter ASSEMBLER-COMMAND Befehle eingeben. Das sowohl mit der Auswahlliste, als auch durch Eintrag. Die Buttons für vorheriger/nächster Befehl funktionieren ebenfalls.
aktuell bei /dev |
|
|
| |
|
|
|
HofK | 3D macht an einige Stellen erheblich mehr Code notwendig. Bei der XProfan Gridbox
var RAM% = create("Gridbox", %hwnd, ramkopf$, 0, 4, 18, 379, 664)
bekommt man von Windows die Bedienung der Scrolleiste gratis dazu.
Für die Browservariante habe ich zwei 3D Pfeile gebastelt und sie mit Funktionalität versehen. Das wird mit raycast realisiert. Dabei funktioniert .name wie bei Radiobuttons als Gruppenname. Es wird also nur geprüft, ob das Element diesen Namen hat.
const RAMup = new THREE.Group( );
const geoRAMupCyl = new THREE.CylinderBufferGeometry( 0.2, 0.2, 6, 6, 1 );
const meshRAMupCyl = new THREE.Mesh( geoRAMupCyl, matRAMupDown );
meshRAMupCyl.name ='up';
RAMup.add( meshRAMupCyl );
objectsToRaycast.push( meshRAMupCyl );
const geoRAMupCone = new THREE.CylinderBufferGeometry( 0, 0.4, 1.6, 6, 1 );
const meshRAMupCone = new THREE.Mesh( geoRAMupCone, matRAMupDown );
meshRAMupCone.name ='up';
meshRAMupCone.position.y = 3.8;
RAMup.add( meshRAMupCone );
objectsToRaycast.push( meshRAMupCone );
RAMup.position.x = 24.5;
RAMup.position.y = 4;
sceneRight.add( RAMup )
Mittlerweile kann man Assemblerbefehle und Konstanten eingeben und den grünen Startknopf drücken. Da werden bisher nur die Programmierelemente verborgen. Mit dem x Button neben STOP kommen sie wieder.
aktuell bei /dev |
|
|
| |
|
|
|
HofK | Seit Ende 2020 gibt es einen deutschen Kanal für three.js auf discord.
Da ist bisher noch nicht viel los. Gestern kam eine Frage zum Import von Modellen. Daraufhin habe ich mein altes Beispiel aktualisiert und gleichzeitig ES6 Module benutzt. Dabei 3 Varianten zur Einbindung der Module zum Test aufgelistet.
<script type="module">
// ----- import from the web -----
// current revision from the repository
/*
import * as THREE from 'https://threejs.org/build/three.module.js';
import { OrbitControls } from 'https://threejs.org/examples/jsm/controls/OrbitControls.js';
import { OBJLoader } from 'https://threejs.org/examples/jsm/loaders/OBJLoader.js';
import { MTLLoader } from 'https://threejs.org/examples/jsm/loaders/MTLLoader.js';
*/
// or a specific revision from a CDN ( Content Delivery Network, e.g. https://www.jsdelivr.com/package/npm/three )
/*
import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.124.0/build/three.module.js';
import { OrbitControls } from 'https://cdn.jsdelivr.net/npm/three@0.124.0/examples/jsm/controls/OrbitControls.js';
import { OBJLoader } from 'https://cdn.jsdelivr.net/npm/three@0.124.0/examples/jsm/loaders/OBJLoader.js';
import { MTLLoader } from 'https://cdn.jsdelivr.net/npm/three@0.124.0/examples/jsm/loaders/MTLLoader.js';
*/
// ----- import local -----
// NOTE! changed identifiers (.rev) and changed import statements at the beginning of the files
// https://hofk.de/main/discourse.threejs/Local%20use%20of%20the%20examples.pdf
// see https://hofk.de/main/discourse.threejs/Module%20usage.pdf
import * as THREE from'../jsm/three.module.124.js'; //
import { OrbitControls } from'../jsm/OrbitControls.124.js';
import { OBJLoader } from'../jsm/OBJLoader.124.js';
import { MTLLoader } from'../jsm/MTLLoader.124.js';
Siehe discord [...]
und bei discourse [...] |
|
|
| |
|
|
|
HofK | Bei der CPU Simulation geht es stückweise weiter. Neben dem RAM ist nun auch in der CPU etwas darstellbar. Allerdings fehlt dort noch die Beschriftung der Bytes. Da sich die Übernahme des Codes der eigentlichen Verarbeitung recht schwierig gestaltet und fehleranfällig ist, habe ich einige JavaScript Erweiterungen eingebunden. Damit ist ein leichterer Vergleich des XProfan- und JS Codes möglich.
Die originalen JS Statements sind teilweise etwas umständlich/länger und nicht sehr übersichtlich. So ist .value kein Wert, sondern auch ein String. Mit const gettext = ( elm ) => ( elm.innerHTML || elm.value ); und neuem .val wird es übersichtlicher und passt besser zu XProfan. Momentan ist noch nicht der gesamte Code derart umgestellt,
Das .innerHTML stammt aus der Zeit, als HTML wirklich nur eine Seitenbeschreibung war und passt mit JS eigentlich nicht mehr. Aber solche "Alten Zöpfe" gibt es massenhaft bei der teils chaotischen Entwicklung in der IT.
Mit der JS-Anpassung an XProfan ist die Übernahme dann übersichtlicher.
Ein Beispiel aus define_constant:
Aus
settext conbin%, conbin$' binär anzeigen
settext conhex%, bin8_to_hex2(conbin$)' hexadezimal anzeigen
settext RAM%, conrow%, 2, conbin$' binär im RAM ablegen
sp_h$ = space$(5-len(coninp$)) +"h"' variable Leerzeichen vor h für hexadezimalen Wert
settext RAM%,conrow%,3,coninp$+sp_h$+gettext$(conhex%)' Wert im RAM darstellen
comment$[conrow%] = ";"+concomm$' Konstanten-Kommentar in Kommentarfeld speichern
wird
settext( conbin, conbin$ );// binär anzeigen
settext( conhex, bin8_to_hex2( conbin$ ) );// hexadezimal anzeigen
RAM[ conrow ][ 2 ] = conbin$;// binär im RAM ablegen
sp_h$ = mkstr$(' ', 5 - coninp$.length ) + 'h'; // variable Leerzeichen vor h für hexadezimalen Wert
RAM[ conrow ][ 3 ] = coninp$ +sp_h$ + gettext( conhex );// Wert im RAM darstellen
comment$[ conrow ] = ";" + concomm$;// Konstanten-Kommentar in Kommentarfeld speichern
Da CPU und RAM in 3D dargestellt werden, musste ich intern für die Inhalte Variablen oder Datenfelder anlegen, aus denen dann die 3D Darstellungen dynamisch generiert werden. Das ist etwas mehr Aufwand als mit den Windows Controls in XProfan, aber andererseits erspart es Code.
Aus
wird
for ( let i = 0; i < 4; i ++ ) {
R[i] = "00000000";// D, A-Register mit 0 initialisieren
S[i] = "00000000";// SD,SA-Register mit 0 initialisieren
}
IR = "00000000";// No Operation im IR
aktuell bei /dev |
|
|
| |
|
|