Frage deutsch
~~~~~~~~~~~~~~~~
Wie greife ich direkt auf den Bildschirmspeicher zu?
Wie greife ich direkt auf das Video-RAM von SCREEN 12 zu? zu?
 

Question English
~~~~~~~~~~~~~~~~
How to access the video memory directly ?
How to access directly the video memory of SCREEN 12 ?
 
 

Antwort 1
~~~~~~~~~~~~~~~~
[ von dusky_joe ( dusky_joe*lycos.de ) im QB-Forum, 30.3.2005 ]
 
Das geht tatsächlich, und zwar so:
 
 
DIM Bildschirm (79, 24, 1) AS INTEGER
'Array, in dem später der Bildschirm gespeichert wird.
DIM offset AS LONG
'Adresse, auf die zugegriffen wird.
 
DEF SEG=&HB800
'Greife auf Bildschirmspeicher zu
FOR spalte = 0 TO 79
FOR zeile = 0 TO 24
FOR typ = 0 TO 1
'typ bedeutet entweder farbe oder zeichen
offset = (zeile * 80 + spalte) * 2 + typ
Bildschirm (spalte, zeile, typ) = PEEK(offset)
NEXT
NEXT
NEXT
DEF SEG
'Standardsegment wiederherstellen - nicht wichtig, aber man sollte
'es trotzdem tun *g*

Ich weiß nicht sicher, ob das Array so ohne weiteres in den BASIC-Speicher passt... wenn Du QB 4.5 oder höher hast, kannst du es mit dem Parameter
QB /AH
aufrufen, dann werden dynamische Felder im "Far Heap" Speicher abgelegt und können viel größer sein. Dann sollte es keine Probleme geben. Oder Du speicherst die Bildschirmdaten direkt in eine Datei. Aber das bleibt dir mal überlassen *g*
 
Die gespeicherten Bildschirmdaten wieder anzuzeigen ist ebenfalls kein Problem. Dazu POKEst Du das Array einfach wieder:
...
FOR spalte = 0 TO 79
FOR zeile = 0 TO 24
FOR typ = 0 TO 1
'typ bedeutet entweder Farbe oder Zeichen
offset = (zeile * 80 + spalte) * 2 + typ
POKE (offset), Bildschirm (spalte, zeile, typ)
NEXT
NEXT
NEXT

In der FAQ-Kategorie
"Direkter Speicherzugriff (PEEK, POKE, INP, OUT & Co)" ist übrigens detailliert erklärt, wie man mit DEF SEG, PEEK und POKE direkt auf den Speicher zugreift.
 
 

Antwort 2
~~~~~~~~~~~~
[ von Andreas meile ("Dreael",
www.dreael.ch ) im QB-Forum, 29.3.05 ]
 
Der Video-Speicher ist wie folgt aufgebaut:
 
B800:0000 als Videospeicheradresse gilt speziell für
 
SCREEN 0,,0,0
 
d.h. Videoseite 0
=> bei den übrigen Videoseiten gelten entsprechend höhere Adressen. Hierbei kommt es noch darauf an, ob man sich im 80- oder 40-Zeichenmodus befindet, ebenso, ob eine Textdarstellung mit 25, 43 oder 50 Zeilen aktiviert ist.
 
Bei 40x25 gilt der 2048-Byte-Sprung, bei 80x25 der 4096-Byte-Sprung. Bei 43 und 50 Zeilen hat es dagegen keine Lücken. Beispiele:
 
SCREEN 0
WIDTH 40, 25
SCREEN ,,3, 3
DEF SEG=&HB800
POKE 3*2048, 65 ' linke obere Ecke
 
 
SCREEN 0
WIDTH 40, 43
SCREEN ,,1, 1
DEF SEG=&HB800
POKE 1*(40*43*2), 65 ' linke obere
 
Und wenn Du den Bildschirminhalt in eine Datei abspeicher willst, so ist das auch
kein Problem. Nichts Leichteres als das: BSAVE und BLOAD bieten Dir exakt das an, z.B.
 
' Bildschirm speichern
DEF SEG=&HB800
BSAVE "BILDSCH.DAT", 0, 4000
' Bildschirm wiederherstellen
DEF SEG=&HB800
BLOAD "BILDSCH.DAT", 0
 
 
Zur Cursorposition: Auslesen geht mit POS(0) und CSRLIN, Setzen mit LOCATE, z.B.
 
 
' Position sichern
x% = POS(0)
y% = CSRLIN
' Position wiederherstellen
LOCATE y%, x%

 

Antwort 3
~~~~~~~~~~~~~~~
[ von Ch@rly ( karl.pircher*gmx.net ) Im QB-Forum, 25.5.2003 ]
 

Wie greife ich direkt auf den Video-Speicher des SREEN 12 zu?
 
Die Speicherverwaltung des Screen 12 ist etwas kompliziert. Es ist keine lineare Verwaltung wie in anderen Modi, sondern er ist seitenweise organisiert. Der Grund liegt darin, dass das Bildschirmsegment einfach zu klein ist. Das Segment beginnt bei &HA000, wie auch bei den andern Modi.
 
Die Größe eines Segments ist systembedingt auf 64 KB beschränkt. Der Speicherbedarf für Screen 12 errechnet sich wie folgt: 640 x 480 Pixel mal 16 Farben. Zum Darstellen eines Pixels werden also 4 Bits benötigt. 2 hoch 4 ergibt die 16 Farben. 640 mal 480 ergibt 307.200 Pixel. Für 2 Pixel wird ein Byte benötigt, also ergibt sich eine Größe von 153.600, also weit mehr als die 64 KB (65536 Byte) des Segments.
 
Die Daten werden daher in 4 sogenannte Bit Planes aufgeteilt. Der Speicher selbst befindet sich nicht im Video-RAM des PCs, sondern auf der VGA Karte. Um auf den Speicher zuzugreifen, wird jeweils eine Plane „hinter" das Video-RAM geblendet, und man kann darauf z.B. mit ganz normalen PEEK/POKE-Befehlen zugreifen. Die Organisation der Daten ist dabei ählich wie beim Zugriff mit GET/PUT. Jeweils ein Bit eines jeden Pixel wird auf eine Plane gelegt. Das 1. Bit (also das Bit Nr. 0, das mit der niedrigsten Wertigkeit) des ersten Pixel links oben befindet sich also im ersten Bit des ersten Byte der ersten Bitplane.
 
Anders ausgedrückt befindet sich dieses Byte an der Adresse &HA000, unter der Voraussetzung, dass diese Plane eingeblendet ist. Das 4. Pixel in der ersten Zeile befindet sich ebenfalls im selben Byte, aber eben im vierten Bit. Das 9. Pixel dagegen befindet sich im 1 Bit des 2. Bytes usw. Die Bitplane an sich ist also linear organisiert. Das erste Bit der 2 Zeile z.B. befindet sich somit im 81. Byte. Die Bildschirmbreite in SCREEN 12 ist 640 Pixel, das ergibt 80 Byte.
 
Zum Ein- und Ausblenden der Planes werden OUT Befehle benutzt. Dabei wird unterschieden, ob der Zugriff lesend oder schreiben erfolgen soll.
 
Zum Schreiben gilt folgendes:
Einblenden der 1. Plane :
OUT &H3C4, 2: OUT &H3C5, 1
Einblenden der 2. Plane : OUT &H3C4, 2: OUT &H3C5, 2
Einblenden der 3. Plane : OUT &H3C4, 2: OUT &H3C5, 4
Einblenden der 4. Plane : OUT &H3C4, 2: OUT &H3C5, 8
 
Zuletzt sollte immer der Originalzustand hergestellt werden mit:
OUT &H3CE, 4: OUT &H3CF, 0
 
Zum Lesen dagegen folgendes:
Einblenden der 1. Plane :
OUT &H3CE, 4: OUT &H3CF, 0
Einblenden der 2. Plane : OUT &H3CE, 4: OUT &H3CF, 1
Einblenden der 3. Plane : OUT &H3CE, 4: OUT &H3CF, 2
Einblenden der 4. Plane : OUT &H3CE, 4: OUT &H3CF, 3
 
Auch hier sollte zuletzt immer der Originalzustand hergestellt werden mit:
OUT &H3C4, 2: OUT &H3C5, 15
 
Hier noch ein Beispiel:
 
 
'**************************************************************
' SCREEN12.BAS = Direktzugriff auf das Video-RAM von SCREEN 13
' ============
' Dieses Q(uick)Basic-Programm demonstriert, wie man direkt
' auf den Bildschirmspeicher des Grafikbildschirms SCREEN 12
' zugreifen kann.
'
' Das Programm enthaelt eine SUBroutine, welche einen Punkt vom
' Bildschirm einliest. Dazu wird zuerst die Farbe abgefragt,
' dann wird ein kleines Quadrat in dieser Farbe gezeichnet und
' anschliessend wird die Farbe eines Pixels innerhalb dieses
' Quadrats durch die SUBroutine ermittelt und angezeigt. Das
' Beispiel dient nur zur Demonstration und ist nicht auf
' Geschwindigkeit ausgelegt. Verschiedene Tests von mir haben
' sowieso ergeben, dass die schnellste Methode, einen Pixel in
' SCREEN 12 zu lesen, immer noch die QB-eigene Methode POINT
' ist.
'
' (c) Ch@rly (karl.pircher*gmx.net), 25.5.2003
'**************************************************************
DEFINT A-Z
DECLARE SUB GetPoint (x%, y%, f%)
'
SCREEN 12
DEFINT A-Z
'
PRINT
INPUT "Farbe (0 - 15) ", f
f = f MOD 16
x = 2
y = 0
'
LINE (0, 0)-STEP(7, 7), f, BF
GetPoint x, y, f
PRINT "Die Farbe ="; f
'
SUB GetPoint (x, y, f)
adr = y * 80
Byte = x \ 8
bit = x - Byte * 8
m = 2 ^ bit
'
adr = adr + Byte
'
DEF SEG = &HA000
OUT &H3CE, 4: OUT &H3CF, 0
b = SGN(PEEK(adr) AND m)
OUT &H3CE, 4: OUT &H3CF, 1
g = SGN(PEEK(adr) AND m)
'
OUT &H3CE, 4: OUT &H3CF, 2
r = SGN(PEEK(adr) AND m)
'
OUT &H3CE, 4: OUT &H3CF, 3
i = SGN(PEEK(adr) AND m)
'
f = b + g * 2 + r * 4 + i * 8
END SUB
 
Das obige Programm steht im Verzeichnis Progs\ zur Verfügung sowie online unter www.antonis.de/faq/progs/screen12.bas .

 

[ The QBasic-MonsterFAQ --- Start Page: www.antonis.de/faq ]