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:
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.
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 .