-
Notifications
You must be signed in to change notification settings - Fork 0
/
AmiGoDOS.php
1042 lines (1022 loc) · 40.7 KB
/
AmiGoDOS.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?php
$usermode = "SERIAL_MODE_AUX";
$server_name = $_ENV['SERVER_NAME'];
$prompt = '0.SYS:> ';
//we need to now if AmiGoDOS is called from within the TAWS environment
if (!isset($_GET['mode'])){$mode=2;}else{$mode=$_GET['mode'];}
if (!isset($_GET['amiga'])){$amiga='Buffy';}else{$amiga=$_GET['amiga'];}
//behaviour.. if set then autoboot
if ( !isset($_GET['autoboot']) ){ $init=''; }
else{ $init='onInit: function() { TS0CA("'.$amiga.'");},'; }
//only for serial mode
if (!isset($_GET['baudrate'])){$baudrate=31250;}else{$baudrate=$_GET['baudrate'];}
if ( !isset($_GET['boot']) ){
$boot = '';
$snapshot=" buttons: [
{run: true, script:`global_apptitle='$amiga';action('5000ms=>restore_last_snapshot');`}
]";
}else{
$boot = $_GET['boot'];
$snapshot="url:'$boot'";
}
if (!isset($_ENV['HTTP_REFERER'])){ $REFERRER="EMPTY"; $TAWS_THANKS1="";$TAWS_THANKS2="";}
else{ $REFERRER=$_ENV['HTTP_REFERER']; }
//for TAWS detection we use /WB.php from subdir but the original TAWS uses /WB.html from root
if (str_contains($REFERRER, '/WB.')) {
$AmiGoTAWS = '<a href=\"https://'.$server_name.'/TS0CA/AmiGoDOS.php\" title=\"Jump to AmiGoDOS (Standalone)..\" target=\"_blank\"><img src=\"Art/TS0CA_Model_MA2RTJE2K.png\" width=\"88\" height=\"88\"></a>';
$TAWS_THANKS1='Thanks TAWS-developer Michael Rupp! [ https://taws.ch ]\n';
$TAWS_THANKS2='<a href=\"https://taws.ch\" title=\"Visit the latest TAWS in Switzerland..\" target=\"_blank\"><img src=\"Art/TS0CA_TAWS_THANKS.png\" width=\"88\" height=\"88\"></a>';
}
else{
$AmiGoTAWS = '<a href=\"http://tsoca.'.$server_name.'\" title=\"Visit our AmiGoXPE Salvation Platform (TAWS-based)..\" target=\"_blank\"><img src=\"Art/TS0CA_Model_MA2RTJE2K.png\" width=\"88\" height=\"88\"></a>';
}
//the emulator files are in the same folder as the run.html let touch=(typeof touched!='undefined')?touched:false;touched=false;
//you can also enable this and disable the players toolbar (see styles section above) //let touch=(typeof touched!='undefined')?touched:false;touched=false;
$config_1="
vAmigaWeb_player.vAmigaWeb_url='./';
let config={
touch:false,
AROS:false,
x_wait_for_kickstart_injection:true,
navbar:false,
wide:true,
border:false,
mouse:true,
port2:false,
$snapshot
//kickstart_rom_url:'./roms/kick31.rom'
};
vAmigaWeb_player.load(this,encodeURIComponent(JSON.stringify(config)));
return false;";
?>
<!DOCTYPE html>
<html>
<head>
<script src="js/jquery.js"></script>
<script src="js/jquery.terminal.min.js"></script>
<link href="css/jquery.terminal.min.css" rel="stylesheet"/>
<script src="js/vAmigaWeb_player.js"></script>
<script src="js/keyboard.js"></script>
<script>
var term;
//we need to store the ports for future reference
//but every pc differs..
//1 relative constant is COM1 which refers to the internal serial port (if available)
//for now the other serial ports via USB should be ignored..
var portserial = null; // global SERIALAccess object
var midi = null; // global MIDIAccess object
var this_frame = null;
var that_frame = null;
var vAmigaWeb0 = null;
var vAmigaWeb1 = null;
var vAmigaWeb2 = null;
const ADOS_TCP_ECHO = "ws://127.0.0.1:8800/echo";
const ADOS_TCP_ADOS = "ws://127.0.0.1:8800/ados";
const ADOS_TCP_NULLMODEM = "ws://127.0.0.1:8800/nullmodem";
var ADOS_Socket = null; //global TCP-Client WebSocket
const ados_version = "AmiGoDOS v1.0b (20240701)";
const server_name = "<?php echo $server_name;?>"
const AMIGA_NAME = "<?php echo $amiga;?>";
//var PROMPT_TRIGGERS = ["> ","/N ","S/ ","/K "];
const MODE_AUX = 0;
const MODE_MIDI_MONITOR = 1;
const MODE_AUX_CONSOLE = 2;
const MODE_MIDI_RUNTIME = 3;
const MODE_DEBUG = 4;
const MODE_MIDI_STUDIO = 5;
//experimental mode to communicate between 2 embedded vAmigaWeb instances
const MODE_AMIGONET = 6;
//experimental mode to connect to real amiga via 3wire nullmodem cable
const MODE_NULLMODEM0 = 7;
//experimental mode to communicate between 2 embedded vAmigaWeb instances
const MODE_NULLMODEM1 = 8;
const MODE_NULLMODEM2 = 9;
const MODE_HARDWARE = 10;
//const MODE_NULLMODEM0_BETA = 11;
//const MODE_DEBUG_UAT = 12;
//only for processing SYSEX not to be called directly
const MODE_MIDI_STUDIO_SYSEX = 55;
//var CURRENT_MODE = MODE_DEBUG;
var CURRENT_MODE = Number("<?php echo $mode;?>"); //MODE_AUX_CONSOLE;
var AMIGADOS_HELP_MODE = 0;
const help = [];
const user_mode = [
"<?php echo $usermode;?>" ,
"SERIAL_MODE_MIDI_MONITOR",
"SERIAL_MODE_AUX_CONSOLE",
"SERIAL_MODE_MIDI_RUNTIME",
"SERIAL_MODE_DEBUG",
"SERIAL_MODE_MIDI_STUDIO",
"SERIAL_MODE_AMIGONET",
"SERIAL_MODE_NULLMODEM0",
"SERIAL_MODE_NULLMODEM1",
"SERIAL_MODE_NULLMODEM2",
"SERIAL_MODE_HARDWARE",
"SERIAL_MODE_MIDI_STUDIO_SYSEX"
];
//how to receive AUX: serial data from the Amiga formatted in a compact way (trimmed)
let out_buffer="";
let skip=0;
let count=0;
let midi_byte_from_amiga = 0;
let midi_running_status_note_on = false;
let midi_running_status_note_off = false;
let midi_sysex = false; //
let midi_use_sysex = false;
const midi_output_id =[];
//const midi_in_event_note_on=[];
//const midi_in_event_note_off=[];
const midi_event_note_on=[];
const midi_event_note_off=[];
const midi_event_polyphonic_aftertouch=[];
const midi_event_control_change=[];
const midi_event_program_change=[]; //1 databyte
const midi_event_channel_aftertouch=[]; //1 databyte
const midi_event_pitch_bend=[];
const midi_event_sysex=[]; // lets try it
// check also for lowecase
//const Amigas_by_Name = ["Amy","Buffy","Claire","Daisy","Eva","Faith","Gwen"];
//const Amigas_by_Type = ["A500","A600","A1000","A2000","A3000","CDTV"];
//const Amigas_by_Scene = ["BlitzBasic","ScalaMM","Music-X"];
function OPEN_TCPCLIENT(protocol){
ADOS_Socket = new WebSocket( protocol,);
ADOS_Socket.onmessage = (event) => {
// relay it to the Amiga
// relay it to the console.log
// console.log(event.data);
// relay it to the terminal
switch (CURRENT_MODE) {
case MODE_AUX_CONSOLE:
//term.echo(event.data);
let vAmigaWeb_window = document.getElementById("vAmigaWeb").contentWindow;
let data = event.data;
//check help mode
AMIGADOS_HELP_MODE=0;
if (data.length>2){
if ( data.slice(-2)==" ?" ){AMIGADOS_HELP_MODE=1;}
}
data = data + "\r";
vAmigaWeb_window.postMessage({cmd:"ser:", text: data}, "*");
break;
default:
term.echo(event.data);
}
};
ADOS_Socket.onopen = (event) => {
// send it to Server at open
ADOS_Socket.send("say setclock load");//+AMIGA_NAME);//
};
}
function CLOSE_TCPCLIENT(){
ADOS_Socket.close();
ADOS_Socket = null;
}
function TCP_SAY(msg){
if (ADOS_Socket != null){
ADOS_Socket.send(msg);
}
}
function INIT_NULLMODEM(){
switch (CURRENT_MODE) {
case MODE_NULLMODEM0/*MODE_NULLMODEM0_BETA*/:
vAmigaWeb0 = document.getElementById("vAmigaWeb").contentWindow;
if ("serial" in navigator) {
// bOpenSerial = document.getElementById("openserial_button");
// bindEvent(bOpenSerial, "click", async () => {
const asyncReaderFunc = async () => {
const port = await navigator.serial.requestPort();
await port.open({ baudRate: <?php echo $baudrate;?> });
portserial = port;
while (port.readable) {
const reader = port.readable.getReader();
try {
while (true) {
const { value, done } = await reader.read();
if (done) {
// |reader| has been canceled & allow the serial port to be closed later.
break;
}// Do something with |value|...
if (value) {
vAmigaWeb0.postMessage({cmd:"ser:", bytes: value}, "*");
//term.echo(value);
//console.log(value);
}
}
}catch (error) {
// Handle |error|...
} finally {
reader.releaseLock();
}
}
}//);
asyncReaderFunc();
}
else {
term.echo('There is NO HW-Serial support in your browser.');
//alert("No SERIAL support in your browser.");
}
break;
case MODE_NULLMODEM1:
that_frame = top.document.getElementById("that_frame");
vAmigaWeb2 = that_frame.contentWindow.document.getElementById("vAmigaWeb").contentWindow;
break;
case MODE_NULLMODEM2:
this_frame = top.document.getElementById("this_frame");
vAmigaWeb1 = this_frame.contentWindow.document.getElementById("vAmigaWeb").contentWindow;
break;
}
}
function ADOS_PTX_LINE(msg){
var that_frame = document.getElementById("that_frame");
msg="<H2><?php echo $amiga;?> says: "+msg+"</H2>";
// Send a message to the parent
window.parent.postMessage(msg, "*");
}
function ADOS_TX_LINE(msg){
let vAmigaWeb_window = document.getElementById("vAmigaWeb").contentWindow;
let data = msg;
switch (CURRENT_MODE) {
case MODE_AUX_CONSOLE:
case MODE_DEBUG:
data = data + "\r";
break;
}
vAmigaWeb_window.postMessage({cmd:"ser:", text: data}, "*");
}
function ADOS_TX_CHAR(msg){
let vAmigaWeb_window = document.getElementById("vAmigaWeb").contentWindow;
if (msg == "_BREAK_"){
let _BREAK_=0x03;
let data = String.fromCharCode(_BREAK_);
vAmigaWeb_window.postMessage({cmd:"ser:", text: data}, "*");
}
}
window.addEventListener('message', event => {
if(event.data.msg == 'serial_port_out')
{
switch (CURRENT_MODE) {
case MODE_AUX:
case MODE_AUX_CONSOLE:
let byte_from_amiga=event.data.value;
switch (byte_from_amiga & 0xff){
case 0x0d: //skip
case 0x0f: //skip
break;
case 0x1b: //filter os3.2 Escape Sequence
skip=4;
break;
case 0x9b: //filter os3.2 Control Sequence Introducer and skip next 3 bytes 20h
skip=3;
break;
case 0x0a:
if (ADOS_Socket != null){ ADOS_Socket.send(out_buffer);}
else { term.echo(out_buffer.trim());}
skip=0;
out_buffer="";
break;
default:
if (skip==0){
out_buffer+=String.fromCharCode( byte_from_amiga & 0xff );
}else{
skip-=1;
}
}
if (ADOS_Socket == null){
if (AMIGADOS_HELP_MODE==1){
//AmigaDOS switches for AUX CONSOLE cmdline help mode [CMD ?]
if (out_buffer.slice(-4)=="/N: "){term.set_prompt(out_buffer.trim());out_buffer="";}
if (out_buffer.slice(-4)=="/S: "){term.set_prompt(out_buffer.trim());out_buffer="";}
if (out_buffer.slice(-4)=="/K: "){term.set_prompt(out_buffer.trim());out_buffer="";}
}
if (out_buffer.slice(-2)=="> " && out_buffer!="> "){term.set_prompt(out_buffer.trim());out_buffer="";}
//3.2 uses the string "> " as marker for a softlink so we need a second confirmation
//Check if EndCLI was called
}//experimental
else{
if (AMIGADOS_HELP_MODE==1){
//AmigaDOS switches for AUX CONSOLE cmdline help mode [CMD ?]
//just a hack to let the prompt detection do its work
if (out_buffer.slice(-4)=="/N: "){ADOS_Socket.send(out_buffer.trim()+"> ");out_buffer="";}
if (out_buffer.slice(-4)=="/S: "){ADOS_Socket.send(out_buffer.trim()+"> ");out_buffer="";}
if (out_buffer.slice(-4)=="/K: "){ADOS_Socket.send(out_buffer.trim()+"> ");out_buffer="";}
}
if (out_buffer.slice(-2)=="> "){ADOS_Socket.send(out_buffer);out_buffer="";}
}
if (out_buffer.includes("Process ")==true){
if (out_buffer.includes(" ending")==true){term.set_prompt("> ");out_buffer="";}
}
break;
case MODE_MIDI_STUDIO_SYSEX:
midi_event_sysex[midi_event_sysex.length]=midi_byte_from_amiga;
switch (midi_byte_from_amiga){
case 0xF7:
// do something with the buffered sysex_msg
if (midi_use_sysex == true){
const output = midi.outputs.get(midi_output_id[0]);
output.send(midi_event_sysex); // sends the message
}
midi_event_sysex.length=0; //just clear the buffer
midi_sysex = false;
CURRENT_MODE = MODE_MIDI_STUDIO; //back to normal midi handling
break;
}
break;
case MODE_MIDI_STUDIO:
midi_byte_from_amiga=event.data.value & 0xff ;
// implement RUNNING-STATUS where after a ststusbyte PAIRS
// of Key/Velocity values need to be processed..
if (midi_byte_from_amiga > 0x7F){ //STATUS_BYTE
status_msb_nibble = midi_byte_from_amiga >> 4; //not sure if msb but keep it for now
status_lsb_nibble = midi_byte_from_amiga & 0xf;
switch(status_msb_nibble){
case 0x9: //NOTE_ON
//turn off running status
midi_event_note_on[0]=midi_byte_from_amiga;
midi_running_status_note_on = true;
midi_running_status_note_off = false;
break;
case 0x8: //NOTE_OFF
midi_event_note_off[0]=midi_byte_from_amiga;
midi_running_status_note_on = false;
midi_running_status_note_off = true;
break;
case 0xA: //POLYPHONIC_AFTERTOUCH
midi_event_polyphonic_aftertouch[0]=midi_byte_from_amiga;
midi_running_status_note_on = false;
midi_running_status_note_off = false;
break;
case 0xB: //CONTROL_CHANGE
midi_event_control_change[0]=midi_byte_from_amiga;
midi_running_status_note_on = false;
midi_running_status_note_off = false;
break;
case 0xC: //PROGRAM_CHANGE
midi_event_program_change[0]=midi_byte_from_amiga;
midi_running_status_note_on = false;
midi_running_status_note_off = false;
break;
case 0xD: //CHANNEL_AFTERTOUCH
midi_event_channel_aftertouch[0]=midi_byte_from_amiga;
midi_running_status_note_on = false;
midi_running_status_note_off = false;
break;
case 0xE: //PITCH_BEND
midi_event_pitch_bend[0]=midi_byte_from_amiga;
midi_running_status_note_on = false;
midi_running_status_note_off = false;
break;
case 0xF: //SYSEX or REALTIME COMMAND
midi_running_status_note_on = false;
midi_running_status_note_off = false;
switch (status_lsb_nibble){
case 0x0: // START SYSTEN_EXCLUSIVE BLOCK
midi_event_sysex[0]=midi_byte_from_amiga;
midi_sysex = true;
CURRENT_MODE = MODE_MIDI_STUDIO_SYSEX;
break;
//SYSTEM_COMMON_MESSAGES
case 0x1: //MTC quarter-frame
break;
case 0x2: //SPP
break;
case 0x3: //SONG_SELECT
break;
case 0x4: //UNDEFINED
break;
case 0x5: //UNDEFINED
break;
case 0x6: //TUNE_REQUEST
break;
case 0x7: //EOX End Of eXclusive
break;
//SYSTEM_REALTIME_MESSAGES
case 0x8: //TIMING_CLOCK for now Music-X sending clocks is turned off
break;
case 0x9: //UNDEFINED1
break;
case 0xA: //START we also use this from the MIDI Shell
break;
case 0xB: //CONTINUE idem..
break;
case 0xC: //STOP idem..
break;
case 0xD: //UNDEFINED2
break;
case 0xE: //ACTIVE_SENSING used to check physical connection status cables
break;
case 0xF: //SYSTEM_RESET
break;
}
break;
}
}else{
//0xF0 initiated SYSEX DATA IS HANDLED IN SUB MODE 55
//if (midi_sysex == true){
//}
//else
//{
//DATA_BYTE
if (midi_running_status_note_on == true){
switch (midi_event_note_on.length){ //NOTE_ON
case 1: midi_event_note_on[1]=midi_byte_from_amiga; break;
case 2:
midi_event_note_on[2]=midi_byte_from_amiga;
const output = midi.outputs.get(midi_output_id[0]);
output.send(midi_event_note_on); // sends the message
midi_event_note_on.length=1; //keep running status
break;
}
}
if (midi_running_status_note_off == true){
switch (midi_event_note_off.length){ //NOTE_OFF
case 1: midi_event_note_off[1]=midi_byte_from_amiga; break;
case 2:
midi_event_note_off[2]=0x00;//midi_byte_from_amiga;
const output = midi.outputs.get(midi_output_id[0]);
output.send(midi_event_note_off); // sends the message
midi_event_note_off.length=1;
break;
}
}
switch (midi_event_polyphonic_aftertouch.length){ //POLYPHONIC_AFTERTOUCH
case 1: midi_event_polyphonic_aftertouch[1]=midi_byte_from_amiga; break;
case 2:
midi_event_polyphonic_aftertouch[2]=midi_byte_from_amiga;
const output = midi.outputs.get(midi_output_id[0]);
output.send(midi_event_polyphonic_aftertouch);
midi_event_polyphonic_aftertouch.length=0;
break;
}
switch (midi_event_control_change.length){ //CONTROL_CHANGE
case 1: midi_event_control_change[1]=midi_byte_from_amiga; break;
case 2:
midi_event_control_change[2]=midi_byte_from_amiga;
const output = midi.outputs.get(midi_output_id[0]);
output.send(midi_event_control_change);
midi_event_control_change.length=0;
break;
}
switch (midi_event_program_change.length){ //PROGRAM_CHANGE
case 1:
midi_event_program_change[1]=midi_byte_from_amiga;
//midi_event_program_change[2]=0x0;
const output = midi.outputs.get(midi_output_id[0]);
output.send(midi_event_program_change);
midi_event_program_change.length=0;
break;
}
switch (midi_event_channel_aftertouch.length){ //CHANNEL_AFTERTOUCH
case 1:
midi_event_channel_aftertouch[1]=midi_byte_from_amiga;
const output = midi.outputs.get(midi_output_id[0]);
output.send(midi_event_channel_aftertouch);
midi_event_channel_aftertouch.length=0;
break;
}
switch (midi_event_pitch_bend.length){ //PITCH_BEND
case 1: midi_event_pitch_bend[1]=midi_byte_from_amiga; break;
case 2:
midi_event_pitch_bend[2]=midi_byte_from_amiga;
const output = midi.outputs.get(midi_output_id[0]);
output.send(midi_event_pitch_bend);
midi_event_pitch_bend.length=0;
break;
}
//}
};
break;
case MODE_AMIGONET:
term.echo("WIP.. this sutosensing mode enables a duplex serial (nullmodem/midi)connection at 31250 BAUD between multiple vAmigaWeb instances..");
break;
case MODE_NULLMODEM0:
let byte_from_amiga0=event.data.value;
navigator.serial.getPorts().then((ports) => {
portserial=ports[0];
});
if (portserial!=null){
//term.echo("PORT IS INITIALIZED.. READY FOR ACTION!");
;(async () => {
//const ports = await navigator.serial.getPorts();
const writer = portserial.writable.getWriter();
const data = new Uint8Array([byte_from_amiga0]);
await writer.write(data);
// Allow the serial port to be closed later.
writer.releaseLock();
})()
//console.log(byte_from_amiga0);
}else{
term.echo("PORT IS NOT INITIALIZED!");
}
break;
case MODE_NULLMODEM1:
//let tx1 = "";
let byte_from_amiga1=event.data.value;
//tx1 = String.fromCharCode(byte_from_amiga1 & 0xff) ;
// let raw_byte_from_amiga1=event.data.value & 0xff ;
vAmigaWeb2.postMessage({cmd:"ser:", byte: byte_from_amiga1}, "*");
//vAmigaWeb2.postMessage({cmd:"ser:", text: tx1}, "*");
//term.echo("WIP.. send data to vAmigaWeb instance 2..");
break;
case MODE_NULLMODEM2:
//let tx2 = "";
let byte_from_amiga2=event.data.value;
//tx2 = String.fromCharCode(byte_from_amiga2 & 0xff) ;
//vAmigaWeb1.postMessage({cmd:"ser:", text: tx2}, "*");
vAmigaWeb1.postMessage({cmd:"ser:", byte: byte_from_amiga2}, "*");
// term.echo("WIP.. send data to vAmigaWeb instance 1..");
break;
case MODE_MIDI_RUNTIME:
//disabled but here comes the special modus on demand..
//Amiga Music-X is OOTB Supported in MODE_MIDI_STUDIO
//but maybe ScalaMM, Octamed or even MidiPlayer need other settings
//so a placeholder for future usage..
term.echo("This mode is not enabled..");
break;
case MODE_MIDI_MONITOR:
midi_byte_from_amiga=event.data.value & 0xff ;
switch ( midi_byte_from_amiga ){
case 0xF8: break; //filter midiclocks
default:
count = count +1;
if (count<31){
term.echo( " 0x"+midi_byte_from_amiga.toString(16).toUpperCase().padStart(2, 0), {newline: false} );
}else{
term.echo( " 0x"+midi_byte_from_amiga.toString(16).toUpperCase().padStart(2, 0) );
count = 0;
}
break;
}
break;
case MODE_DEBUG:
let raw_byte_from_amiga=event.data.value & 0xff ;
switch ( raw_byte_from_amiga ){
default:
count = count +1;
if (count<31){
term.echo( " 0x"+raw_byte_from_amiga.toString(16).toUpperCase().padStart(2, 0), {newline: false} );
}else{
term.echo( " 0x"+raw_byte_from_amiga.toString(16).toUpperCase().padStart(2, 0) );
count = 0;
}
break;
}
break;
}
}
});
// MIDI_RUNTIME
function ADOS_TX_MIDI(msg){
let vAmigaWeb_window = document.getElementById("vAmigaWeb").contentWindow;
// if (data != ""){ vAmigaWeb_window.postMessage({cmd:"ser:", text: data}, "*");}
if (msg == 'start'){ var b = 0xFA;}
else if (msg == 'cont'){ var b = 0xFB;}
else if (msg == 'stop'){ var b = 0xFC;}
switch (b){
case 0xFA: vAmigaWeb_window.postMessage({cmd:"ser:", byte: b}, "*");break;
case 0xFB: vAmigaWeb_window.postMessage({cmd:"ser:", byte: b}, "*");break;
case 0xFC: vAmigaWeb_window.postMessage({cmd:"ser:", byte: b}, "*");break;
default:
term.echo("UNASSIGNED_BYTE");
}
}
function onMIDISuccess( midiAccess ) {
term.echo( "WebMIDI API ready!" );
midi = midiAccess; // store in the global (in real usage, would probably keep in an object instance)
// autostart the first MIDI output
startMIDIOutput(midi,0);
}
function onMIDIFailure(msg) {
term.echo( "Failed to get MIDI access - " + msg );
}
function onMIDISYSEXSuccess( midiAccess ) {
term.echo( "WebMIDI SYSEX API ready!" );
midi = midiAccess; // store in the global (in real usage, would probably keep in an object instance)
// autostart the first MIDI output
startMIDIOutput(midi,0);
}
function onMIDISYSEXFailure(msg) {
term.echo( "Failed to get MIDI SYSEX access - " + msg );
}
function GET_MIDI_INPUTS( midiAccess ) {
for (const entry of midiAccess.inputs) {
const input = entry[1];
term.echo(
`Input port [type:'${input.type}']` +
` id:'${input.id}'` +
` manufacturer:'${input.manufacturer}'` +
` name:'${input.name}'` +
` version:'${input.version}'`
);
}
}
function GET_MIDI_OUTPUTS( midiAccess ) {
for (const entry of midiAccess.outputs) {
const output = entry[1];
term.echo(
`Output port [type:'${output.type}'] id:'${output.id}' manufacturer:'${output.manufacturer}' name:'${output.name}' version:'${output.version}'`
);
}
}
function apiMIDI_INS_OUTS( midiAccess ) {
GET_MIDI_OUTPUTS(midiAccess);
GET_MIDI_INPUTS(midiAccess);
}
function apiMIDI_INIT( midiAccess ) {
// request MIDI access
if(navigator.requestMIDIAccess){
navigator.requestMIDIAccess({sysex: false}).then(onMIDISuccess, onMIDIFailure);
}
else { alert("No MIDI support in your browser.");}
}
function onMIDIMessage(event) {
switch (CURRENT_MODE) {
case MODE_MIDI_MONITOR:
let str = `MIDI message received at timestamp ${event.timeStamp}[${event.data.length} bytes]: `;
for (const character of event.data) {
str += `0x${character.toString(16)} `;
}
term.echo(str);
break;
case MODE_MIDI_RUNTIME:
break;
case MODE_MIDI_STUDIO:
let vAmigaWeb_window = document.getElementById("vAmigaWeb").contentWindow;
for (const character of event.data){
vAmigaWeb_window.postMessage({cmd:"ser:", byte: character}, "*");
//vAmigaWeb_window.postMessage({cmd:"ser:", bytes: event.data}, "*");
}
break;
}
}
function startLoggingMIDIInput(midiAccess, indexOfPort) {
midiAccess.inputs.forEach((entry) => {
entry.onmidimessage = onMIDIMessage;
});
}
function startMIDIOutput(midiAccess, indexOfPort) {
for (const entry of midiAccess.outputs) {
const output = entry[1];
//term.echo("Midi-Out_Open:".output.id);
midi_output_id.push(output.id);
output.open();
//break;
}
}
function START_SERIAL( serAccess ) {
if ("serial" in navigator) {
// The Web Serial API is supported.
navigator.serial.getPorts().then((ports) => {
// Initialize the list of available ports with `ports` on page load.
});
term.echo('HARDWARE SERIAL support enabled.');
// Prompt user to select any serial port. major bug when using await navigator.serial.requestPort();
const port = navigator.serial.requestPort();
}
else {
term.echo('No HARDWARE SERIAL support in your browser.');
//alert("No SERIAL support in your browser.");
}
}
// local functions when not connected to AUX:
function ADOS_ALIAS(key, value){
}
function ADOS_ASSIGN(key, value){
}
function TS0CA(modelID='Buffy') {
switch (CURRENT_MODE) {
case MODE_MIDI_MONITOR:
case MODE_MIDI_RUNTIME:
// case MODE_MIDI_STUDIO:
case MODE_MIDI_STUDIO_SYSEX:
// request MIDI access
if(navigator.requestMIDIAccess){
navigator.requestMIDIAccess({sysex: true}).then(onMIDISYSEXSuccess, onMIDISYSEXFailure);
}
else {
alert("No MIDI SYSEX support in your browser.");
}
// navigator.requestMIDIAccess().then( onMIDISuccess, onMIDIFailure );
break;
}
const modelAmiga = document.getElementById(modelID);
modelAmiga.click();
}
//function removeDiv(machineID='container')
//{
// var vAmigaWebDiv = document.getElementById(machineID);
// vAmigaWebDiv.parentNode.removeChild();
//}
</script>
<style>
.terminal,span,.cmd,div{
--background: silver;
--color:rgba(45,45,45,0.99);
--font: NewTopaz;
}
.terminal,span{--size: 1.0;}
@font-face{
font-family: NewTopaz;
src: url("fonts/Topaz_a1200_v2.0.ttf");
}
body {
background-color: darkgray;
color: white;
}
#vAmigaWeb {
border:none;
}
#player_container div {
display: none !important;
}
</style>
</head>
<body>
<div id="vAmigaWebContainer" style="display: flex;align-items: center;justify-content: left;">
<div id="container">
<img id="<?php echo $amiga;?>" style="width:960px; height:633px" src="Art/C1084_<?php echo $amiga;?>.gif"
onclick="<?php echo $config_1;?>"
/>
</div>
</div>
<div id="AmiGoDOS" style="display: flex;align-items: center;justify-content: left;">
<div id="NewShell">
<script>
jQuery( function($){
var id = 1;
term = $('body').terminal(
function(command, term) {
const command_arr = command.split(" ");
let cmd = command_arr[0];
if (cmd!=''){
switch(command_arr.length){
case 1:
if (cmd == 'help') { term.echo("AmiGoDOS commands:\n"+
" alias, assign, cls, echo, exit, help, prompt, version\n"+
" clear, click, close, engage, logout, mode, lic\n"+
"Available Amiga's by Name: amy, buffy, claire, daisy, eva, faith, gwen\n"+
"Available Amiga's by Type: a500, a600, a1000, a2000, a3000, cdtv\n"+
"Command Shells: nullmodem, serial, midi, vamiga, tcp, ftp(dummy)"); }
else if (cmd == 'about1'){ term.echo("AmiGoDOS dialect is my amiga-ish syntax flavoured devshell originated in Delphi7 Pascal in 2002..");}
else if (cmd == 'about2'){ term.echo("tried to keep the AmigaDOS syntax somehow alive.. to get things done on MS side.. even in Amiga GUI style");}
else if (cmd == 'about3'){ term.echo("used to connect to Amiga (FS-UAE) via TCP-COMPORT and relay to MIDI or REMOTE-CONSOLE..");}
else if (cmd == 'about4'){ term.echo("now using it to connect to vAmigaWeb..AUX/SER/MIDI for Classic Amiga Web usage and using the experience..");}
else if (cmd == 'about5'){ term.echo("IT also works for our version of TAWS.. on behalf of the ultimate Amiga Anywhere experience IYKWIM..");}
else if (cmd == 'about6'){ term.echo("AmiGoDOS for the Web uses JavaScript JQueryTerminal as versatile framework.. with AmiGoDOS syntax/functions..");}
else if (cmd == 'about7'){ term.echo("a for Web usage simplified AmiGoDOS is just a nice nostalgic label for WIP to keep the momentum going..");}
else if (cmd == 'about8'){ term.echo("with kind regards.. PTz(Peter Slootbeek)uAH");}
else if (cmd == 'thx'){
term.echo("Thank you for beta-testing AmiGoDOS..");
break;
}
else if (cmd == 'lic'){
new Audio('Art/Y0_UP.mp3').play();
term.echo(
"AmiGoDOS (TS0CA) thankslist, licenses, attributions & more..\n"+
"This just-for-the-fun-damen-tal-edu-art-zen-project utilises the following frameworks:\n"+
"TAWS by Michael Rupp! [ https://taws.ch ]\n"+
"vAmigaWeb (GPL-3.0) by Mithrendal [ https://github.com/vAmigaWeb/vAmigaWeb ]\n"+
"vAmiga-core (GPL-3.0) by Dirk W. Hoffmann [ https://github.com/dirkwhoffmann/vAmiga ]\n"+
"Jquery.Terminal (MIT) by Jakub T. Jankiewicz [ https://github.com/jcubic/jquery.terminal ]\n"+
"AmiGoDOS (TS0CA) by PTz(Peter Slootbeek)uAH [ https://github.com/PTz0uAH/AmiGoDOS ]\n"+
"You as a private user may test AmiGoDOS for free to maintain & preserve \"The Spirit Of Commodore Amiga\"..\n"+
"any usage outside this (TS0CA) scope may need explicit oral consent..\n"+
"\"Yo..up!\" tune performed by \"Maartje2K& The BigDreamers\" for PTz(SL02TBE2K-SYSTEMS)uAH..\n"+
"\"Sunny\" logo (re)designed by Youp for PTz(SL02TBE2K-SYSTEMS)uAH..\n"+
"other gfx/art created/provided by \"Brother G.\" [ https://www.facebook.com/genetic.wisdom ]\n"+
"All trademarks belong to their respective owners!"
);
return $('<img src=\"Art/SL02TBE2K-SYSTEMS_logo.png\" width=\"64\" height=\"88\">'+
'<img src=\"Art/AmiGoDOS_logo.png\" width=\"88\" height=\"88\">'+
'<?php echo "$AmiGoTAWS";?>'+
'<a href=\"https://github.com/vAmigaWeb\" title=\"Click to visit the vAmigaWeb dev-site on GitHub\" target=\"_blank\"><img src=\"Art/TS0CA_vAmigaWeb_THANKS.png\" width=\"88\" height=\"88\"></a>'+
'<a href=\"https://taws.ch\" title=\"Visit the latest TAWS in Switzerland..\" target=\"_blank\"><img src=\"Art/TS0CA_TAWS_THANKS.png\" width=\"88\" height=\"88\"></a>'+
'<a href=\"https://terminal.jcubic.pl/\" title=\"Click if you wish to visit the JQuery.Terminal support site in Poland\" target=\"_blank\"><img src=\"Art/TS0CA_JQueryTerminal_THANKS.png\" width=\"88\" height=\"88\"></a>'+
'<a href=\"https://www.facebook.com/groups/612005812580097/\" title=\"AmiGoDOS is endorsed by the Admins of 47PAINFBAT.. Support (y)our Troops!\" target=\"_blank\"><img src=\"Art/TS0CA_670613165_TANKS.png\" width=\"88\" height=\"88\"></a>'
);
}
else if (cmd == 'version'){term.echo(ados_version);}
else if (cmd == 'alias'){ term.echo("WIP: make short version of long commands/args"); }
else if (cmd == 'assign'){
switch (CURRENT_MODE){
case MODE_MIDI_STUDIO:
case MODE_MIDI_MONITOR:
case MODE_MIDI_RUNTIME:
term.echo("WIP: assign i.e. 0xFA midi byte to trigger function in the webpage");
break;
case MODE_AUX:
case MODE_AUX_CONSOLE:
case MODE_DEBUG:
ADOS_TX_LINE(cmd);
break;
default:
term.echo(cmd + ': Unknown command for chosen MODE');
break;
}
}
//else if (cmd == 'click') { parent.newcli(); }
//else if Amigas_by_Name.includes(cmd) {parent.location.assign("AmiGoDOS.php?amiga="+cmd+"&autoboot");}
else if (cmd == 'a500') { parent.location.assign("AmiGoDOS.php?amiga=A500");}
else if (cmd == 'A500') { parent.location.assign("AmiGoDOS.php?amiga=A500&autoboot");}
else if (cmd == 'a600') { parent.location.assign("AmiGoDOS.php?amiga=A600");}
else if (cmd == 'A600') { parent.location.assign("AmiGoDOS.php?amiga=A600&autoboot");}
else if (cmd == 'a1000') { parent.location.assign("AmiGoDOS.php?amiga=A1000");}
else if (cmd == 'A1000') { parent.location.assign("AmiGoDOS.php?amiga=A1000&autoboot");}
else if (cmd == 'a2000') { parent.location.assign("AmiGoDOS.php?amiga=A2000");}
else if (cmd == 'A2000') { parent.location.assign("AmiGoDOS.php?amiga=A2000&autoboot");}
else if (cmd == 'a3000') { parent.location.assign("AmiGoDOS.php?amiga=A3000");}
else if (cmd == 'A3000') { parent.location.assign("AmiGoDOS.php?amiga=A3000&autoboot");}
else if (cmd == 'cdtv') { parent.location.assign("AmiGoDOS.php?amiga=CDTV");}
else if (cmd == 'CDTV') { parent.location.assign("AmiGoDOS.php?amiga=CDTV&autoboot");}
// use Amy for MIDI stuff like Music-X, Octamed, Scala etc..
else if (cmd == 'amy') { parent.location.assign("AmiGoDOS.php?amiga=Amy");}
else if (cmd == 'Amy') { parent.location.assign("AmiGoDOS.php?amiga=Amy&mode=5&autoboot");}
else if (cmd == 'buffy') { parent.location.assign("AmiGoDOS.php?amiga=Buffy");}
else if (cmd == 'Buffy') { parent.location.assign("AmiGoDOS.php?amiga=Buffy&autoboot");}
else if (cmd == 'claire') { parent.location.assign("AmiGoDOS.php?amiga=Claire");}
else if (cmd == 'Claire') { parent.location.assign("AmiGoDOS.php?amiga=Claire&autoboot");}
else if (cmd == 'daisy') { parent.location.assign("AmiGoDOS.php?amiga=Daisy");}
else if (cmd == 'Daisy') { parent.location.assign("AmiGoDOS.php?amiga=Daisy&autoboot");}
else if (cmd == 'eva') { parent.location.assign("AmiGoDOS.php?amiga=Eva");}
else if (cmd == 'Eva') { parent.location.assign("AmiGoDOS.php?amiga=Eva&autoboot");}
else if (cmd == 'faith') { parent.location.assign("AmiGoDOS.php?amiga=Faith");}
else if (cmd == 'Faith') { parent.location.assign("AmiGoDOS.php?amiga=Faith&autoboot");}
else if (cmd == 'gwen') { parent.location.assign("AmiGoDOS.php?amiga=Gwen");}
else if (cmd == 'Gwen') { parent.location.assign("AmiGoDOS.php?amiga=Gwen&autoboot");}
else if (cmd == 'close') { parent.close(); }
else if (cmd == 'cls') { term.clear(); term.echo("AmiGoDOS - Developer Shell [" + user_mode[CURRENT_MODE] + "]"); }
else if (cmd == 'engage') { TS0CA("<?php echo $amiga;?>"); }
else if (cmd == 'exit') { parent.location.assign("../home.php"); }
else if (cmd == 'halt') { vAmigaWeb_player.stop_emu_view(); }
//else if (cmd == 'loadwb') { parent.location.assign("../taws.php"); }
else if (cmd == 'logout') { parent.location.assign("../access/logout.php"); }
else if (cmd == 'prompt') { term.echo("<?php echo "$prompt";?>"); }
else if (cmd == 'tcp'){
term.push(
function(command, term) {
if (command.trim()!=''){
const sub_command_arr = command.split(" ");
let sub_cmd = sub_command_arr[0];
switch(sub_command_arr.length){
case 1:
if (sub_cmd == 'help') {
term.echo('Available TCP-mode commands:\n'+
'exit [leave TCP mode]\n'+
'open [open a TCP connection to AmiGoDOS - NewShell Server]\n'+
'close [close the TCP connection with AmiGoDOS - NewShell Server]\n'+
'say [send a string to the server]\n' +
'cls [clear shell]');
}
else if (sub_cmd == 'cls'){ term.clear(); term.echo("AmiGoDOS - Developer Shell [" + user_mode[CURRENT_MODE] + "]"); }
else if (sub_cmd == 'open') {OPEN_TCPCLIENT(ADOS_TCP_ADOS);} //DEFAULT
else if (sub_cmd == 'open_echo') {OPEN_TCPCLIENT(ADOS_TCP_ECHO);} //DEFAULT
else if (sub_cmd == 'close') {CLOSE_TCPCLIENT();}
else if (sub_cmd == 'menu') {return $('<button id="openserial_button">Open Serial Port</button>');}
else if (sub_cmd == 'exit') {term.pop();}
else {term.echo('SYNTAX_ERROR: unknown TCP-mode command ' + sub_cmd);}
break;
default:
if (sub_command_arr.length>>1){ sub_command_arr.splice(0,1);}
if (sub_cmd == 'say') { TCP_SAY( sub_command_arr.join(" ") );}
else if (sub_cmd == 'open') { OPEN_TCPCLIENT( sub_command_arr.join(" ") );}
else {term.echo('SYNTAX_ERROR: unknown TCP-mode command ' + sub_cmd);}
}//END SWITCH
}else{term.echo('SYNTAX_ERROR: EMPTY COMMAND! hint: type "help" to get help..');}
},{ prompt: 'TCP> ', name: 'tcp' }
);
}
else if (cmd == 'ftp'){
term.push(
function(command, term) {
if (command == 'help') {term.echo('Available FTP (dummy) commands: ping');}
else if (command == 'ping') {term.echo('pong');}
else if (command == 'exit') {term.pop();}
else { term.echo('unknown FTP command ' + command); }
},
{ prompt: 'FTP> ', name: 'ftp' }
);
}
else if (cmd == 'nullmodem'){
term.push(
function(command, term) {
if (command == 'help') {term.echo('Available NULLMODEM commands:\n'+
'exit [leave NULLMODEM mode]\n'+
'init [start NULLMODEM Inputs/Outputs] depending on MODE_SERIAL_NULLMODEMx\n'+
'cls [clear shell]');}
else if (command == 'cls'){ term.clear(); term.echo("AmiGoDOS - Developer Shell [" + user_mode[CURRENT_MODE] + "]"); }
else if (command == 'init') {INIT_NULLMODEM();}
else if (command == 'menu') {
return $('<button id="openserial_button">Open Serial Port</button>');
}
else if (command == 'exit') {term.pop();}
else { term.echo('unknown NULLMODEM command ' + command); }
},
{ prompt: 'NULLMODEM> ', name: 'ser' }
);
}
else if (cmd == 'midi'){
term.push(
function(command, term) {
if (command == 'help') {term.echo('Available MIDI commands:\n'+
'exit [leave MIDI mode]\n'+
'info [show MIDI Inputs/Outputs]\n'+
'midi_in_open [monitor data received from Inputs]\n'+
'start [send MIDI_START byte to the Amiga serial input]\n'+
'cont [send MIDI_CONTINUE byte to the Amiga serial input]\n'+
'stop [send MIDI_STOP byte to the Amiga serial input]');}
else if (command == 'cls'){ term.clear(); term.echo("AmiGoDOS - Developer Shell [" + user_mode[CURRENT_MODE] + "]"); }
else if (command == 'start') {count=0; ADOS_TX_MIDI(command);}
else if (command == 'cont') {ADOS_TX_MIDI(command);}
else if (command == 'stop') {ADOS_TX_MIDI(command);}
else if (command == 'info') {apiMIDI_INS_OUTS(midi);}
else if (command == 'init') {apiMIDI_INIT(midi);}
else if (command == 'midi_in_open') {startLoggingMIDIInput(midi,0);}
//else if (command == 'midi_out_open') {startMIDIOutput(midi,0);}
// else if (command == 'midi_out_close') {startMIDIOutput(midi,0);}
else if (command == 'exit') {term.pop();}
else { term.echo('unknown MIDI command ' + command); }
},
{ prompt: 'MIDI> ', name: 'midi' }
);
}
else if (cmd == 'vamiga'){
term.push(
function(command, term) {
if (command == 'help') {term.echo('vAmigaWeb commands:\n'+
'exit [leave the vAmigaWeb Shell]\n'+
'reset [reset the vAmiga]\n'+
'toggle_run [run/pause vAmiga]\n'+
'take_snapshot [save snapshot to local storage]\n'+
'restore_snapshot [restore snapshot from local storage]');}
else if (command == 'restore_snapshot') {term.echo('dummy restore_snapshot');}
else if (command == 'take_snapshot') { vAmigaWeb_player.exec(()=>action('take_snapshot')); }
//else if (command == 'take_snapshot') { vAmigaWeb_player.exec(()=>alert('Hoi!')); }
//{term.echo('dummy take_snapshot');}
else if (command == 'exit') { term.pop(); }
else if (command == 'reset') { vAmigaWeb_player.reset(); }
else if (command == 'toggle_run') { vAmigaWeb_player.toggle_run(); }
else { term.echo('unknown vAmigaWeb command ' + command); }
},
{ prompt: 'vAmigaWeb> ', name: 'vamiga' }
);
}
else {
// pass_through to AUX
switch (CURRENT_MODE){
case MODE_AUX:
case MODE_AUX_CONSOLE:
case MODE_DEBUG:
ADOS_TX_LINE(cmd);
break;
default:
term.echo(cmd + ': Unknown command for chosen MODE');
break;
}
}
break;
default:
if (command_arr.length>>1){ command_arr.splice(0,1);}
if (cmd == 'click'){ parent.newcli(command_arr[0]); }
else if (cmd == 'echo') { term.echo( command_arr.join(" ") ); }
else if (cmd == 'exit'){ parent.location.assign(command_arr[0]); }