Pseudo-Sprites auf dem VC 20
Der VC 20 kennt von Haus aus leider nicht die freibeweglichen Grafikobjekte des C 64, die sogenannten Sprites. Das bedeutet aber nicht, daß man auf die Vorteile der Sprites oder MOBs gänzlich verzichten muß.
Das Programm ist für den VC 20 mit 8 KByte Speichererweiterung konzipiert. Es läuft jedoch mit einigen Änderungen auch bei nur 3 KByte Speichererweiterung.
Vor dem Eintippen oder Laden muß man POKE 44,32:POKE 8192,0: NEW eingeben, womit der Basic-Anfang im Speicher auf die Adresse dezimal 8193 ($2001) erhöht wird. Somit ergibt sich folgende Speicheraufteilung:
- 4096 — 4607 Bildschirm
- 4608 — 8191 frei
- 8192 — 16383 (bei + 8 KByte) Basic-Programmspeicher
- 8192 — 24575 (bei + 16 KByte) Basic-Programmspeicher
- 8192 — 32767 (bei + 24 KByte) Basic-Programmspeicher
Der freie Bereich wird nun vollständig von dem Maschinenspracheprogramm gebraucht. Die Aufteilung des Speicherraums ist die folgende:
4608 — 5119 | Sprite-Control-Block (SCB), wird später erklärt |
5120 — 6143 | freidefinierbarer Zeichensatz, die ersten 128 Zeichen, stehen zur freien Verfügung |
6144 — 7167 | freidefinierbarer Zeichensatz, die zweiten 128 Zeichen, werden vom Programm zur Erstellung der 9 Sprites gebraucht und stehen somit nicht zur freien Verfügung |
7168 — 8191 | Maschinenspracheprogramm, Beschreibung siehe Text |
Die Pseudo-Sprites sollten eine Auflösung von 16 x 16 Punkten haben, das sind 256 Punkte oder 4 Zeichen im freidefinierbaren Zeichensatz (Bild 1). Damit aber ein 16 x 16 Punkte großes Zeichen jede Position auf dem Bildschirm einnehmen kann, braucht man eine 24 x 24 Punkte große Umdefinier-Matrix, in die das Zeichen hineinkopiert wird. Das Aussehen dieser Umdefinier-Matrix ist in Bild 2 zu sehen. Das Programm übernimmt nun die Aufgabe, das Zeichen in die Umdefinier-Matrix zu kopieren (Bild 3), in die richtige X-Position zu schieben (Bild 4), und dasselbe mit der Y-Position zu tun.




Außerdem werden die Zeichen, die später auf dem Bildschirm von den Sprites verdeckt werden, mit in die Umdefinier-Matrix hineinkopiert. So entsteht der Eindruck, daß die Sprites wirklich über die Zeichen wandern. Beim späteren Löschen werden die verdeckten Zeichen wieder hergestellt. Wie funktioniert das nun?
Im Speicher ab dezimal 4608 ist 9mal (für jedes Sprite einer) der sogenannte Sprite-Control-Block (SCB) eingerichtet. Er hat die Aufgabe, die momentane X- und Y-Position, die Farbe des Sprites, den Bildschirmmodus (gesetzt/gelöscht) des Sprites, die durch die Umdefinier-Matrix verdeckten 9 Zeichen und Farben zwischenzuspeichern:
Byte 0 — 8 | Bildschirmcode der verdeckten Zeichen |
Byte 9 — 17 | Farbcode der verdeckten Zeichen |
Byte 18 | X-Position des Sprites |
Byte 19 | Y-Position des Sprites |
Byte 20 | Farbe des Sprites |
Byte 21 | Bildschirmmodus (gesetzt= $00/gelöscht=$FF) |
Die Basisadresse des SCB errechnet sich somit aus der Formel Basisadresse = 4608 + Spritenummer x 22. Das Zwischenspeichern und die Auswertung der Parameter übernimmt natürlich das Maschinenprogramm. Über den SCB werden auch im nachfolgend beschriebenen Programm »Sprite-Definer« die Sprites initialisiert und deren Farbe festgelegt. Da nur die oberen 128 Zeichen des Zeichensatzes für die Sprites verwendet werden, hat man eine ausreichende Anzahl von noch frei definierbaren Zeichen, nämlich genau 128, zur Verfügung. Außerdem kommen jeweils 13 Zeichen, nämlich 4 für das Sprite und 9 für die Umdefinier-Matrix hinzu, wenn man auf ein Sprite verzichtet. Die Matrixen werden im Speicher so abgelegt:
128 — 131 | Grundmatrix Sprite 0 |
132 — 140 | Umdef.-Matrix Sprite 0 |
141 — 144 | Grundmatrix Sprite 1 |
145 — 153 | Umdef.-Matrix Sprite 1 |
Konkret wird das Programm (Listing 1) nun folgendermaßen bedient: Vor dem Laden oder Eingeben wird POKE 44,32:POKE 8192,0:NEW eingetippt. Ist nun das Maschinenspracheprogramm im Speicher, kann es mit einem Monitorprogramm auch noch einmal abgespeichert werden. Später muß man es nur noch mit LOAD »name«, 1,1 laden.
Die Bedienung:
Sind die Sprites definiert, muß dem Maschinenspracheprogramm mitgeteilt werden, wo der Zeichensatz liegt, den es verwalten soll. Das geschieht mit den Befehlen POKE 677, Lowbyte:POKE 678, Highbyte, in unserem Fall also POKE 677,0:POKE 678,20, da der Zeichensatz auf der Adresse 5120 beginnt.
Soll nun ein Sprite auf den Bildschirm, muß zuerst einmal in Adresse 683 die Spritenummer gePOKEt werden (Achtung, keine Zahl über 8 angeben, da sich das Programm dann selbst zerstören könnte). Schließlich werden in Adresse 673 die X-Koordinate (maximal 159) und 674 die Y-Koordinate (maximal 167) gesetzt. Dann kann das Programm mit SYS 8021 sofort aufgerufen und auf dem Bildschirm das Sprite betrachtet werden, vorausgesetzt man hat vorher mit POKE 36869,205 auf den freidefinierbaren Zeichensatz geschaltet.
Wird nun das Sprite auf eine andere Position gesetzt, so verschwindet es vollständig von der alten Position, und die Zeichen, die auf diesem Platz waren, erscheinen wieder mit ihrer alten Farbe. Will man aber das Sprite ganz vom Bildschirm löschen, POKEt man wieder in 683 die Spritenummer und ruft das Maschinenspracheprogramm diesmal mit SYS 8099 auf. PRINT »CLR/HOME« sollte man nicht verwenden, da im SCB noch die alten Bildschirmzeichen gespeichert sind und beim nächsten Setzen wieder auf ihren alten Plätzen auf dem Bildschirm erscheinen würden.
Der Sprite-Generator
Nun zum Programm »Sprite-Definer« (Listing 2).
Dieses Programm ist ein Sprite-Generator in Basic, der bei der Erstellung von Sprites recht hilfreich sein kann. Das Programm verdeutlicht auch, wie die Definition der Sprites und die Bedienung des Maschinenspracheprogramms erfolgt.
Obwohl sich das Programm fast von selbst erklärt, hier doch einige kurze Erläuterungen:
Startet man das Programm mit RUN, erscheint als erstes die Begrüßung und die Aufforderung »Bitte warten!«. Das Programm kopiert nämlich jetzt den Zeichensatz aus dem ROM ins RAM, was in Basic naturgemäß etwas dauert.
Jedesmal, wenn man in einem Menüteil eine Eingabe gemacht hat, wird man »Richtig?« gefragt. Tippt man hier für N (Nein), so kann die Eingabe wiederholt werden. Drückt man aber den Linkspfeil, so kommt man wieder ins Hauptmenü.
Die Tastenbelegung im Editiermodus:
Cursor-Tasten | Cursor-Bewegungen |
Leertaste | Punkt setzen |
Delete-Taste | Punkt löschen |
CLR/HOME | Gitter löschen |
RETURN | Modus beenden mit Änderung des Sprites, vorher aber Abfrage |
Linkspfeil | Modus beenden, aber ohne Änderung des Sprites |
I-Taste | Sprite invertieren |
Bei der Funktion »Weiter« kommt man in ein zweites Menü, das weitere Funktionen zur Verfügung stellt. Aus diesem Menü gelangt man mit »zurück« wieder ins Hauptmenü. Beim Speichern werden die Sprites als reiner Speicherauszug auf Kassette gebracht, so daß das Laden im Prinzip auch mit LOAD »name«,1,1 möglich ist.
Sicherlich kann das Maschinenspracheprogramm noch weiter verbessert werden. So wäre zum Beispiel eine Spritesteuerung per Interrupt durchaus denkbar. Leider funktioniert das Maschinenprogramm nicht mit den üblichen Grafikmodulen, da diese den Bildschirminhalt auch mit dem freidefinierbaren Zeichensatz aufbauen. Sollen Sprites auch miteinander oder übereinander dargestellt werden, dann muß das Setzen und Löschen nach folgender Reihenfolge durchgeführt werden, da es sonst zu Schwierigkeiten mit dem SCB kommen kann:
Sprite 0 setzen, Sprite 1 setzen,…, Sprite n setzen. Hiernach die Berechnungen für die neuen Positionen durchführen.
Sprite n löschen,.Sprite n-1 löschen,…, Sprite 0 löschen. Danach Vorgang von oben wiederholen.
Noch eins zum »Sprite-Definer«: Die erste REM-Zeile muß auf jeden Fall mit 16 Sternchen eingegeben werden, da sich das Programm später mit POKEs selbst verändert und andernfalls, wäre die REM-Zeile kürzer, die folgende Zeile in Mitleidenschaft ziehen würde. Doch nun wünsche ich allen, die das Programm eintippen, viel Spaß und vielleicht ein bißchen C 64-Feeling.
(Markus Leberecht/ev)1 rem pseudosprites 2 rem fuer vc 20 3 rem (data-lader) 4 rem 5 rem sprites von 7168 bis 8192 6 rem 7 rem 'save' vor 'run' ! 8 rem 1001 data024,032,121,029,173,165,002,133 1002 data025,173,166,002,133,026,142,169 1003 data002,173,163,002,042,046,169,002 1004 data024,042,046,169,002,024,042,046 1005 data169,002,024,101,025,133,025,165 1006 data026,109,169,002,133,026,024,165 1007 data025,105,032,133,029,165,026,105 1008 data000,133,030,173,161,002,041,007 1009 data141,167,002,173,161,002,024,074 1010 data074,074,141,161,002,024,173,162 1011 data002,041,007,141,168,002,173,162 1012 data002,074,074,074,141,162,002,032 1013 data121,029,162,072,145,029,200,202 1014 data208,250,024,160,000,024,165,029 1015 data109,168,002,133,031,165,030,105 1016 data000,133,032,177,025,145,031,200 1017 data192,016,208,247,024,165,031,105 1018 data024,133,031,165,032,105,000,133 1019 data032,024,165,025,105,016,133,027 1020 data165,026,105,000,133,028,160,000 1021 data024,177,027,145,031,200,192,016 1022 data208,247,173,167,002,201,000,240 1023 data060,234,169,024,141,170,002,165 1024 data029,141,118,029,165,030,141,119 1025 data029,032,121,029,024,032,117,029 1026 data162,024,032,117,029,162,048,032 1027 data117,029,024,173,118,029,105,001 1028 data141,118,029,173,119,029,105,000 1029 data141,119,029,206,170,002,208,217 1030 data206,167,002,208,197,032,148,029 1031 data024,032,121,029,173,163,002,105 1032 data004,141,163,002,032,126,029,032 1033 data137,029,238,163,002,238,162,002 1034 data032,126,029,032,137,029,238,163 1035 data002,238,162,002,032,126,029,032 1036 data137,029,056,173,162,002,233,002 1037 data141,162,002,238,161,002,238,163 1038 data002,032,126,029,032,137,029,238 1039 data163,002,238,162,002,032,126,029 1040 data032,137,029,238,163,002,238,162 1041 data002,032,126,029,032,137,029,056 1042 data173,162,002,233,002,141,162,002 1043 data238,161,002,238,163,002,032,126 1044 data029,032,137,029,238,163,002,238 1045 data162,002,032,126,029,032,137,029 1046 data238,163,002,238,162,002,032,126 1047 data029,032,137,029,096,126,120,007 1048 data096,169,000,170,168,096,024,174 1049 data162,002,172,161,002,032,240,255 1050 data096,024,173,163,002,174,164,002 1051 data032,161,234,096,024,032,121,029 1052 data133,251,173,136,002,133,252,174 1053 data162,002,224,000,240,016,024,165 1054 data251,105,022,133,251,165,252,105 1055 data000,133,252,202,208,240,024,165 1056 data251,109,161,002,133,251,165,252 1057 data105,000,133,252,024,032,121,029 1058 data169,000,133,253,169,148,133,254 1059 data174,162,002,224,000,240,016,024 1060 data165,253,105,022,133,253,165,254 1061 data105,000,133,254,202,208,240,024 1062 data165,253,109,161,002,133,253,165 1063 data254,105,000,133,254,024,032,121 1064 data029,165,029,133,031,165,030,133 1065 data032,024,032,121,029,162,000,173 1066 data165,002,133,027,173,166,002,133 1067 data028,189,098,030,048,075,168,177 1068 data251,157,060,003,072,169,000,141 1069 data169,002,104,010,046,169,002,010 1070 data046,169,002,010,046,169,002,101 1071 data027,133,027,173,169,002,101,028 1072 data133,028,160,000,177,027,017,031 1073 data145,031,200,192,008,208,245,024 1074 data165,031,105,008,133,031,165,032 1075 data105,000,133,032,189,098,030,168 1076 data177,253,157,069,003,232,076,007 1077 data030,096,000,022,044,001,023,045 1078 data002,024,046,255,024,032,121,029 1079 data173,136,002,133,252,152,133,251 1080 data169,000,133,253,169,148,133,254 1081 data173,162,002,240,017,168,024,165 1082 data251,105,022,133,251,165,252,105 1083 data000,133,252,136,208,240,024,165 1084 data251,109,161,002,133,251,165,252 1085 data105,000,133,252,173,162,002,240 1086 data017,168,024,165,253,105,022,133 1087 data253,165,254,105,000,133,254,136 1088 data208,240,024,165,253,109,161,002 1089 data133,253,165,254,105,000,133,254 1090 data024,032,121,029,189,098,030,048 1091 data015,168,189,060,003,145,251,189 1092 data069,003,145,253,232,076,204,030 1093 data096,024,032,121,029,173,161,002 1094 data074,074,074,141,161,002,173,162 1095 data002,074,074,074,141,162,002,076 1096 data108,030,024,032,121,029,177,251 1097 data153,060,003,200,192,022,208,246 1098 data096,024,032,121,029,185,060,003 1099 data145,251,200,192,022,208,246,096 1100 data024,032,121,029,133,251,169,018 1101 data133,252,169,128,141,163,002,173 1102 data171,002,201,000,240,038,024,165 1103 data251,105,022,133,251,165,252,105 1104 data000,133,252,232,236,171,002,208 1105 data237,024,032,121,029,024,173,163 1106 data002,105,013,141,163,002,232,236 1107 data171,002,208,242,096,024,032,024 1108 data031,024,032,121,029,032,250,030 1109 data173,161,002,072,173,162,002,072 1110 data173,081,003,048,015,173,078,003 1111 data141,161,002,173,079,003,141,162 1112 data002,032,225,030,024,032,121,029 1113 data104,141,162,002,141,079,003,104 1114 data141,161,002,141,078,003,173,080 1115 data003,141,164,002,032,000,028,169 1116 data000,141,081,003,032,024,031,032 1117 data009,031,096,032,024,031,024,032 1118 data121,029,032,250,030,173,081,003 1119 data048,030,173,078,003,141,161,002 1120 data173,079,003,141,162,002,032,225 1121 data030,024,032,121,029,169,255,141 1122 data081,003,032,024,031,032,009,031 1123 data096,234,234,234,234,234,234,234 1124 data234,234,234,234,234,234,234,234 1125 data234,234,234,234,234,234,234,234 1126 data234,234,234,234,234,234,234,234 1127 data234,234,234,234,234,234,234,234 1128 data234,234,234,234,234,234,234,234 1130 s=0:fori=7168to8191:readd:s=s+d 1131 pokei,d:next 1132 ifs<>111729thenprint"{rvon}fehler!{rvof}"
1 rem sprite-generator 2 rem 10 poke36879,25:print"{clr}";:poke157,128 15 poke677,0:poke678,20 20 print"{pur}{rvon} sprite-definer " 30 print"{rvon}{rght}{rght}{rght} fuer vc=20 " 40 print"{down}{rvon}{rght}{rght}{rght} (c) 1984 by " 50 print"{down}{grn} markus leberecht{blu}" 60 print"{down}{down}{down}{rght}{rght}{rght}{rght}bitte warten!" 70 az=32768:nz=5120:fora=0to2047:pokenz+a,peek(az+a):next 80 printchr$(8);"{clr}"; 90 print"{rvon}{pur} menue {blu}" 100 print"{down}{rvon}{rght}f1{rvof} sprite erstellen 110 print"{down}{rvon}{rght}f2{rvof} sprite editieren 120 print"{down}{rvon}{rght}f3{rvof} sprite loeschen 130 print"{down}{rvon}{rght}f4{rvof} sp.-farbe aendern 150 print"{down}{rvon}{rght}f5{rvof} sprite(s) saven 160 print"{down}{rvon}{rght}f6{rvof} sprite(s) laden 170 print"{down}{rvon}{rght}f7{rvof} sprite kopieren 180 print"{down}{rvon}{rght}f8{rvof} {red}weiter 190 gosub61000 200 f$="{f1}{f2}{f3}{f4}{f5}{f6}{f7}{f8}":fora=1to8:ifmid$(f$,a,1)=a$then220 210 nexta:goto190 220 onagoto290,320,450,520,570,690,750 230 print"{clr}{rvon}{pur} menue {blu}" 240 print"{down}{down}{rght}{rvon}f1{rvof} verifizieren 250 print"{down}{down}{rght}{rvon}f2{rvof} initialisieren 251 print"{down}{down}{rght}{rvon}f3{rvof} sprite-demo 260 print"{down}{down}{rght}{rvon}f7{rvof} {red}zurueck{blu} 270 print"{down}{down}{rght}{rvon}f8{rvof} beenden 280 gosub61000 285 f$="{f1}{f2}{f3}{f4}{f5}{f6}{f7}{f8}":fora=1to8:ifmid$(f$,a,1)=a$then287 286 nexta:goto280 287 onagoto810,840,880,280,280,280,80,940 288 goto280 290 print"{clr}{blu}spritenummer:"; 300 inputs%:print"{down}richtig?":gosub61000:ifa$="n"thenprint"{up}{up}";:goto290 302 ifa$="_"thenpoke36879,25:goto80 305 print"{clr}";:gosub50000:ifa$="_"then80 310 gosub40000:goto80 320 poke36879,24:print"{clr}{blu}spritenummer";:inputs% 330 print"{down}richtig?":gosub61000:ifa$="n"then320 335 ifa$="_"thenpoke36879,25:goto80 340 ba%=nz+1024+s%*104 350 print"{clr}{down}{down}{down}{rght}{rght}{rght}";:fora=0to15:forb=0to7 360 ifpeek(ba%+a)and(2^(7-b))thenprint"Q";:goto380 370 print" "; 380 nextb:print:print"{rght}{rght}{rght}";:nexta 390 print"{home}{down}{down}{down}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}";:fora=0to15:forb=0to7 400 ifpeek(ba%+16+a)and(2^(7-b))thenprint"Q";:goto420 410 print" "; 420 nextb:print:print"{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}";:nexta 430 gosub50000:ifa$="_"thenpoke36879,25:goto80 440 gosub40000:poke36879,25:goto80 450 poke36879,26:print"{clr}{blu}spritenummer:":print"{down}(9=keins) 460 inputs%:print"{down}richtig?":gosub61000 470 ifa$="n"or(s%>9ors%<0)then450 480 ifs%=9thenpoke36879,25:goto80 490 print"{down}{rvon}!! loesche !!" 500 ba%=nz+1024+s%*104 510 fora=0to31:pokeba%+a,0:next:poke36879,25:goto80 520 poke36879,27:print"{clr}{blu}spritefarben:" 530 fora=0to8:print"{down}sprite nr."a"---"peek(4608+a*22+20)and15:nexta 540 input"{down}welches (9=exit)";s%:ifs%<0ors%>8thenpoke36879,25:goto80 550 input"farbe";f%:iff%<0orf%>15thenpoke36879,25:goto80 560 poke4608+22*s%+20,f%:goto520 570 poke36879,28:input"{clr}{blu}anf.-sprite:";sa%:ifsa%<0orsa%>8then570 580 input"{down}endsprite: {left}{left}{left}";se%:ifse%<0orse%>8thenprint"{up}{up}";:goto580 585 print"{down}richtig?":gosub61000:ifa$="n"then570 587 ifa$="_"thenpoke36879,25:goto80 590 ifsa%>se%then570 600 st%=nz+1024+sa%*104:en%=nz+1024+(se%+1)*104 610 poke185,3:input"{down}filename:";fi$:fi$=left$(fi$,16):iffi$=""thenprint"{up}{up}";:goto610 620 fora=1tolen(fi$):poke8192+5+a,asc(mid$(fi$,a,1)):next:poke183,len(fi$) 640 poke186,1 650 poke187,6:poke188,32 660 poke193,st%-256*int(st%/256):poke194,st%/256 670 poke174,en%-256*int(en%/256):poke175,en%/256 680 sys63106:poke36879,25:goto80 690 poke36879,29:input"{clr}{blu}{down}filename:";fi$ 700 print"{down}richtig?":gosub61000:ifa$="n"then690 705 ifa$="_"thenpoke36879,25:goto80 710 iflen(fi$)=0then730 720 fora=1tolen(fi$):poke8192+5+a,asc(mid$(fi$,a,1)):next 730 poke183,len(fi$):poke186,1:poke187,6:poke188,32 740 sys62786:poke36879,25:goto80 750 poke36879,30:input"{clr}{blu}quelle=";s1%:ifs1%<0ors1%>8thenpoke36879,25:goto80 760 input"{down}ziel=";s2%:ifs2%<0ors2%>8thenpoke36879,25:goto80 770 print"{down}richtig?":gosub61000:ifa$="n"then750 775 ifa$="_"thenpoke36879,25:goto80 780 print"{down}{rvon}!! kopiere !!" 790 s1%=nz+1024+104*s1%:s2%=nz+1024+104*s2% 800 fora=0to31:pokes2%+a,peek(s1%+a):next:poke36879,25:goto80 810 poke36879,31:print"{clr}{rvon}bestaetigen":gosub61000 815 ifa$="_"thenpoke36879,25:goto80 820 print:verify"",1,1:print"{down}{down}{rvon}taste":gosub61000 830 poke36879,25:goto80 840 poke36879,24:print"{clr}{down}{blu}{rvon}bestaetigen":gosub61000:ifa$="_"thenpoke36879,25:goto80 845 print"{down}{rvon}!! initialisiere !!" 850 fora=0to9:print"{down}sprite"a:forb=0to31:pokenz+1024+a*104+b,0:nextb 860 poke4608+a*22+20,0 870 forb=0to17:poke4608+a*22+b,32:nextb,a:poke36879,25:goto80 880 input"{clr}{blu}spritenummer:";s%:print"{down}richtig?":gosub61000 890 ifa$="n"then880 891 ifa$="_"then80 900 print"{clr}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{rght}{rght}{rght}{rght}{rght}{blk}sp{red}ri{cyn}te{pur}-d{grn}em{blu}o!" 910 poke36869,205 920 fora=-127to127:poke673,abs(a):poke674,abs(a):poke683,s%:sys8021 930 nexta:poke683,s%:sys8099:poke36869,192:goto80 940 print"{clr}{blu}wirklich?":gosub61000 950 ifa$="j"thennew 960 goto80 999 end 40000 print"{home}{rvon}!! werte aus !!"; 40005 fora=0to15:bb%=0:forb=0to7 40010 bb%=bb%-((peek(b%+a*22+b)and127)=81)*2^(7-b):nextb 40020 pokenz+128*8+s%*104+a,bb%:nexta 40030 b%=b%+8 40040 fora=0to15:bb%=0:forb=0to7 40050 bb%=bb%-((peek(b%+a*22+b)and127)=81)*2^(7-b):nextb 40060 pokenz+128*8+s%*104++16+a,bb%:nexta 40070 return 50000 print"{home}spritenr."s% 50010 print"{down}{rght}{rght}{CBM-A}{CBM-R}{CBM-R}{CBM-R}{CBM-R}{CBM-R}{CBM-R}{CBM-R}{CBM-R}{CBM-R}{CBM-R}{CBM-R}{CBM-R}{CBM-R}{CBM-R}{CBM-R}{CBM-R}{CBM-S}" 50020 fora=0to15:print"{rght}{rght}{CBM-Q}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{CBM-W}":next:print"{rght}{rght}{CBM-Z}{CBM-E}{CBM-E}{CBM-E}{CBM-E}{CBM-E}{CBM-E}{CBM-E}{CBM-E}{CBM-E}{CBM-E}{CBM-E}{CBM-E}{CBM-E}{CBM-E}{CBM-E}{CBM-E}{CBM-X}" 50030 b%=4096+22*3+3:x%=0:y%=0 50035 d%=b%+y%*22+x% 50040 if(peek(d%)and128)=0thenpoked%,peek(d%)or128:poked%+33792,6:goto50060 50050 if(peek(d%)and128)thenpoked%,peek(d%)and127:poked%+33792,6 50060 ax%=x%:ay%=y%:gosub61000 50070 ifa$="{down}"andy%<15theny%=y%+1:goto50200 50080 ifa$="{up}"andy%>0theny%=y%-1:goto50200 50090 ifa$="{rght}"andx%<15thenx%=x%+1:goto50200 50100 ifa$="{left}"andx%>0thenx%=x%-1:goto50200 50110 ifa$=" "thenpoked%,209:poked%+33792,6:goto50060 50120 ifa$=chr$(20)thenpoked%,160:poked%+33792,6:goto50060 50130 ifa$="{clr}"thenprint"{home}{down}{down}{down}";:fora=0to15:print"{rght}{rght}{rght} ":next:goto50030 50140 ifa$="i"thengosub60000:goto50035 50150 ifa$=chr$(13)then50240 50160 ifa$="_"thenreturn 50200 d%=b%+ay%*22+ax% 50210 if(peek(d%)and128)=0thenpoked%,peek(d%)or128:goto50230 50220 if(peek(d%)and128)thenpoked%,peek(d%)and127 50230 goto50035 50240 print"{home}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}wirklich(j/n)?"; 50250 gosub61000:ifa$="j"thenreturn 50260 print"{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left} {home}";:goto50000 60000 forx=0to15:fory=0to15:dd%=b%+22*y+x 60010 if(peek(dd%)and127)=81thenpokedd%,32:pokedd%+33792,6:next:next:return 60020 if(peek(dd%)and127)=32thenpokedd%,81:pokedd%+33792,6:next:next:return 61000 poke198,0:wait198,1:geta$:return