Autor Thema: Bildschirmbereich sichern und wiederherstellen (C/C++)  (Gelesen 13175 mal)

0 Mitglieder und 3 Gäste betrachten dieses Thema.

Offline Count

  • Benutzer
  • Beiträge: 251
Bildschirmbereich sichern und wiederherstellen (C/C++)
« am: So 22.11.2015, 19:30:46 »
Hallo zusammen,

in einem C++-Programm, das aus Geschwindigkeitsgründen vorwiegend über die BIOS-Funktion Bconout Textausgabe macht, möchte ich eine Fileselectbox aufrufen. Dafür möchte ich vorher den Bildschirmbereich, der von der Fileselectbox beansprucht wird, sichern und anschließend wiederherstellen.

Das ganze möchte ich natürlich so kompatibel wie möglich lösen, also unabhängig von der TOS-Version, der Bildschirmauflösung und vor allem unabhängig von irgendwelchen Erweiterungen wie NVDI o.ä.

Ich habe mir überlegt, den betreffenden Bereich mit vro_cpyfm() vom Bildschirmspeicher in einen mit malloc() reservierten Speicherbereich zu kopieren und anschließend wieder zurück. Die Frage, die ich mir nun stelle, ist die, wie ich den benötigten Speicher berechne? Hat das schon mal jemand von euch gelöst?

Ich habe den Code im Anhang mal so zusammengestrichen, dass es für das Verständnis sicher ausreicht.

VdiHdl vdi_handle, wk_handle;
short work_out[57];
short work_out_extnd[57];


int main() {
    short work_in[11] = { Getrez()+2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2 };
    short dummy;
    void* screen_buffer;
   
    vdi_handle = graf_handle(&dummy, &dummy, &dummy, &dummy);

    // Workstation öffnen
    v_opnvwk(work_in, &wk_handle, work_out);
   
    // Erweiterte Informationen holen (Planes)
    vq_extnd(vdi_handle, 1, work_out_extnd);
   
    ... tu was ...
   
    // (100,100) bis (200,200) sichern
    screen_buffer = getScreenContent(100, 100, 200, 200);
   
    ... Fileselector aufrufen ...
   
    // und wiederherstellen
    putScreenContent(100, 100, 200, 200, screen_buffer);

    // Speicher wieder freigeben
    free(screen_buffer);
   
    ... tu was ...
   
    return 0;
}


void* getScreenContent(short x1, short y1, short x2, short y2) {
    void*        buffer;
    MFDB         copysrc, copydst;
    short        width       = x2 - x1 + 1;
    short        height      = y2 - y1 + 1;
    short        pxyarray[8] = { x1, y1, x2,        y2
                               , 0,  0,  width - 1, height - 1
                               };
    const size_t wordlen     = sizeof(short);
    size_t       buflen;

    // Speicherbedarf berechnen
    buflen = height * wordlen * (width / wordlen + (width % wordlen != 0 ? wordlen : 0));
    buffer = malloc(buflen);

    // Kopieren von      Bildschirm    -->    Puffer
    copysrc.fd_addr    = Physbase();          copydst.fd_addr = buffer;
    copysrc.fd_w       = copydst.fd_w       = m_work_out[0] + 1;
    copysrc.fd_h       = copydst.fd_h       = m_work_out[1] + 1;
    copysrc.fd_stand   = copydst.fd_stand   = 0;
    copysrc.fd_wdwidth = copydst.fd_wdwidth = m_work_out[0] + 1 / wordlen;
    copysrc.fd_nplanes = copydst.fd_nplanes = m_work_out_extnd[4];

    v_hide_m(vdi_handle);
    vro_cpyfm(vdi_handle, S_ONLY, pxyarray, &copysrc, &copydst);
    v_show_m(vdi_handle, 1);

    return buffer;
}


void putScreenContent(short x1, short y1, short x2, short y2, void* buffer) {
    MFDB         copysrc, copydst;
    short        width       = x2 - x1 + 1;
    short        height      = y2 - y1 + 1;
    short        pxyarray[8] = { 0,  0,  width - 1, height - 1
                               , x1, y1, x2,        y2
                               };

    // Kopieren von      Puffer      -->      Puffer
    copysrc.fd_addr    = buffer;              copydst.fd_addr = Physbase();
    copysrc.fd_w       = copydst.fd_w       = m_work_out[0] + 1;
    copysrc.fd_h       = copydst.fd_h       = m_work_out[1] + 1;
    copysrc.fd_stand   = copydst.fd_stand   = 0;
    copysrc.fd_wdwidth = copydst.fd_wdwidth = m_work_out[0] + 1 / sizeof(short);
    copysrc.fd_nplanes = copydst.fd_nplanes = m_work_out_extnd[4];

    v_hide_m(vdi_handle);
    vro_cpyfm(vdi_handle, S_ONLY, pxyarray, &copysrc, &copydst);
    v_show_m(vdi_handle, 1);
}

guest3744

  • Gast
Re: Bildschirmbereich sichern und wiederherstellen (C/C++)
« Antwort #1 am: Mo 23.11.2015, 10:31:44 »
Gibt es keine Refresh-Befehl für solche Dinge auf dem Desktop?

Gruss

Offline mfro

  • Benutzer
  • Beiträge: 1.640
Re: Bildschirmbereich sichern und wiederherstellen (C/C++)
« Antwort #2 am: Mo 23.11.2015, 11:44:57 »
...Ich habe mir überlegt, den betreffenden Bereich mit vro_cpyfm() vom Bildschirmspeicher in einen mit malloc() reservierten Speicherbereich zu kopieren und anschließend wieder zurück. Die Frage, die ich mir nun stelle, ist die, wie ich den benötigten Speicher berechne? Hat das schon mal jemand von euch gelöst?

Der Speicherbedarf für die Kopie des Bildschirmausschnitts ist unabhängig von der Auflösung

Breite in Worten x 2 Bytes/Wort x Anzahl Planes x Höhe in Pixel Bytes

mit

Breite in Worten = (Breite in Pixel + 15) / 16;
And remember: Beethoven wrote his first symphony in C

Offline ST-Oldie

  • Benutzer
  • Beiträge: 158
Re: Bildschirmbereich sichern und wiederherstellen (C/C++)
« Antwort #3 am: Di 24.11.2015, 23:28:40 »
Hi,

Der Speicherbedarf für die Kopie des Bildschirmausschnitts ist unabhängig von der Auflösung

Du meinst wohl abhängig? Zumindest die Farbtiefe geht da schon ein.

Breite in Worten x 2 Bytes/Wort x Anzahl Planes x Höhe in Pixel Bytes

mit

Breite in Worten = (Breite in Pixel + 15) / 16;

Wobei "Anzahl Planes" die Abhängigkeit zur Farbtiefe darstellt.

Tschüß
Michael
atari.mbernstein.de, the ATARI way of computing

guest3744

  • Gast
Re: Bildschirmbereich sichern und wiederherstellen (C/C++)
« Antwort #4 am: Mi 25.11.2015, 12:09:08 »
Mit welchem "C++" programmierst du auf den ST ?

Danke.
Gruss

Offline Count

  • Benutzer
  • Beiträge: 251
Re: Bildschirmbereich sichern und wiederherstellen (C/C++)
« Antwort #5 am: Fr 27.11.2015, 12:49:34 »
Danke für die Antworten. Ich habe die Berechnung mal so umgesetzt, aber irgendwie funktioniert das (mit Steem 3.2 und TOS 2.06) nur mit MiNT.  :o

@Peter: Ich nehme Cross-Mint-G++ unter Cygwin.
http://vincent.riviere.free.fr/soft/m68k-atari-mint/

guest3744

  • Gast
Re: Bildschirmbereich sichern und wiederherstellen (C/C++)
« Antwort #6 am: Sa 28.11.2015, 13:23:15 »
Ja danke für die Info.

Gruss

Offline Count

  • Benutzer
  • Beiträge: 251
Re: Bildschirmbereich sichern und wiederherstellen (C/C++)
« Antwort #7 am: Mi 02.12.2015, 17:37:34 »
Kurzes Update:

Es funktioniert jetzt auch ohne NVDI, wenn ich als Bildschirmadresse in fd_addr statt Physbase() einfach 0 angebe, dann wird automatisch der Bildschirmspeicher genommen. Und wordlen ist natürlich nicht sizeof(short), sondern 8*sizeof(short) bzw. einfach 16.

Nach dem Zurückkopieren des Puffers in den Bildschirmspeicher muss man auf jeden Fall das Clipping neu setzen, da die Rasterkopierfunktion dieses auf den zu kopierenden Ausschnitt begrenzt.

Offline ST-Oldie

  • Benutzer
  • Beiträge: 158
Re: Bildschirmbereich sichern und wiederherstellen (C/C++)
« Antwort #8 am: Do 03.12.2015, 22:53:24 »
Hi,

Es funktioniert jetzt auch ohne NVDI, wenn ich als Bildschirmadresse in fd_addr statt Physbase() einfach 0 angebe, dann wird automatisch der Bildschirmspeicher genommen.

Das ist auch so dokumentiert.

Tschüß
Michael
atari.mbernstein.de, the ATARI way of computing