Zeitprobleme -> Canvas->Pixels
-
Hallo,
ich moechte eine Rechneremulation (8-BitCpu) eines fiktiven Rechners schreiben.
Der Rechner soll ein Character-Rom haben.
Er soll eine Aufloesung von 4025 Zeichen haben.
Und der Bildschirm soll eine Aufloesung von 320200 Pixel haben.
Es soll auch moeglich sein auf eine reine Graphikdarstellung umzuschalten.
Im Prinzip ähnlich einem C64'er.Ich benutze den Turbo C++ Compiler von Borland.
Vom Prinzip laeuft die Anzeige(natuerlich wie zu sehen nur ein Test), allerdings ist sie viel zu langsam.
Ich möchte 25 Bildaufbauten pro Sekunde erreichen.Ich habe die Beispielapplikation Canvas benutzt und zeichne jetzt mit
Canvas->Pixels[xPos][actDisplayLine] = clRed;
void __fastcall TFormMain::Timer1Timer(TObject *Sender) { if ( firstTimer ) { firstTimer = false; CpuMainLoop(); } } //--------------------------------------------------------------------- void __fastcall TFormMain::CpuMainLoop() { for (int i=1; i < 251*25*60; ++i) { // Lines*framePerSec*Sec DisplayScanLine(); } Timer1->Enabled = false; } void __fastcall TFormMain::DisplayScanLine() { Canvas->Pen->Color = actFrameColor; if ( (actDisplayLine < 26) || (actDisplayLine > 226) ) { Canvas->MoveTo(0, actDisplayLine); Canvas->LineTo(379, actDisplayLine); } else { Canvas->MoveTo(0, actDisplayLine); Canvas->LineTo(29, actDisplayLine); for (int xPos = 30; xPos < 350; ++xPos) { Canvas->Pixels[xPos][actDisplayLine] = clRed; } Canvas->MoveTo(350, actDisplayLine); Canvas->LineTo(379, actDisplayLine); } if (actDisplayLine < 251) { ++actDisplayLine; } else { actDisplayLine = 0; ++VSynccntr; Application->ProcessMessages(); } }
Die leere methode FormPaint wird soweit ich das feststellen konnte bei Application->ProcessMessages() einmal aufgerufen. So dass ich davon ausgehe, dass die methode direkt in das Canvas zu malen einfach zu langsam ist.
Wie kann man hier die Geschwindigkeit steigern?besten Dank
oldman
-
Da läuft aber noch einiges bei dir schief...
Du solltest ersteinmal im Timer nur einmalig das Bild anzeigen lassen.
Da du eine Refreshrate von 25/sec erreichen willst, setze also den Timer auf 40ms (d.h. Timer.Interval = 40).Um die Form neu anzeigen zu lassen, reicht es "Refresh()" aufzurufen.
In Code:void __fastcall TFormMain::Timer1Timer(TObject *Sender) { Refresh(); }
Nun brauchst du in der Form-Paint Methode nur die Anzeige (des gesamten Bildes)durchführen.
Was du genau mit der Scanline erreichen willst, ist mir nicht klar geworden...
Und deine Pixels-Schleife entspricht doch auch:
Canvas->Pen->Color = clRed; Canvas->MoveTo(30, actDisplayLine); Canvas->LineTo(350, actDisplayLine);
so daß deine Geschwindigkeitsprobleme damit behoben sein sollten.
-
@Th69
Erstmal danke fuer die Antwort.
Nochmal zur Erklaerung was ich moechte:
Die Schleife in DisplayScanLine soll die Ausgabe des Rechners auf dem Bildschirm sein, so dass dort schon jedes einzelne Pixel gesetzt werden muss.
Der jetzige Code war nur dazu gedacht, festzustellen ob die Anzeige vom Prinzip ueberhaupt so gemacht werden kann.
Die Geschwindigkeit der Anzeige soll nicht über Windowstimer gesteuert werden, sondern von der Ablaufgeschwindigkeit der Emulation. Die Ausbremsung der Emulation, also CPU laeuft mit x-MHz ist hierbei noch nicht beruecksichtigt.Spaeter saehe es in etwa so aus Pseudocode:
void __fastcall TFormMain::CpuMainLoop() { TCpuEmulator toEmulateCpu; bool stopCpu = false; int cycleCntr = 0; int cycleForOneScanLine = 200; // Anzahl der CpuCycles die fuer eine Bildschirmzeile(Pixel) zur Verfuegung steht. while (!stopCpu) { toEmulateCpu.executeNextCommand(); cycleCntr += toEmulateCpu.getCycles(); if (cycleCntr >= cycleForOneScanLine) { cycleCntr -= cycleForOneScanLine; DisplayScanLine(); } } } void __fastcall TFormMain::DisplayScanLine() { Canvas->Pen->Color = actFrameColor; // Zeichne die Aktuelle Zeile die Daten hole aus dem Speicher der emulierten CPU if (actDisplayLine < 251) { ++actDisplayLine; } else { actDisplayLine = 0; Refresh(); Application->ProcessMessages(); } }
-
Ich glaube, dass der Ansatz schon etwas unglücklich ist. Ich würde eine Offscreen Bitmap der Grösse 320x200 bei 24bit Farbtiefe benutzen und die Bitmapdaten direkt modifizieren. In der Paint() Methode des Canvas müsste man dann nur noch per BitBlt die Bitmap auf die Zeichenfläche kopieren und dann ist man fertig.