Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 253973c

Browse files
committed
Screen buffer; no more flickering on slower systems
1 parent c335386 commit 253973c

File tree

3 files changed

+108
-33
lines changed

3 files changed

+108
-33
lines changed

src/comp.cpp

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,14 @@
1818
#include "cpu.hpp"
1919
#include "renderer.hpp"
2020
#include "drawing.hpp"
21+
#include "output.hpp"
2122

2223
using namespace std;
2324

2425
extern "C" {
25-
typedef void (*callback_function)(void);
26+
extern volatile sig_atomic_t pleaseExit;
2627
void setEnvironment();
27-
void setOutput(callback_function drawScreen, int width, int height);
28-
void printCharXY(char c, int x, int y);
29-
void printString(const char s[], int x, int y);
30-
void redrawScreen();
3128
void resetEnvironment();
32-
extern volatile sig_atomic_t screenResized;
33-
extern volatile sig_atomic_t pleaseExit;
3429
}
3530

3631
Printer printer;
@@ -80,7 +75,7 @@ void highlightCursor(bool highlight) {
8075
if (highlight) {
8176
printf("\e[%dm\e[%dm", 30, 47);
8277
}
83-
printCharXY(c, cursorX+ramX, cursorY+ramY);
78+
printCharImediately(c, cursorX+ramX, cursorY+ramY);
8479
if (highlight) {
8580
printf("\e[%dm\e[%dm", 37, 40);
8681
}
@@ -301,7 +296,7 @@ void loadRamFromFileStream(ifstream* fileStream) {
301296
}
302297
}
303298

304-
299+
305300
void loadRamIfFileSpecified(int argc, const char* argv[]) {
306301
if (argc <= 1) {
307302
return;
@@ -542,6 +537,7 @@ int main(int argc, const char* argv[]) {
542537
setEnvironment();
543538
prepareOutput();
544539
loadRamIfFileSpecified(argc, argv);
540+
clearScreen();
545541
redrawScreen();
546542
highlightCursor(true);
547543
userInput();

src/output.c renamed to src/output.cpp

Lines changed: 88 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,25 @@
1-
#include <stdio.h>
2-
#include <sys/ioctl.h>
1+
#include "output.hpp"
2+
33
#include <signal.h>
4+
#include <stdio.h>
45
#include <string.h>
6+
#include <sys/ioctl.h>
7+
#include <string>
8+
#include <vector>
9+
10+
////////////////////////////
511

6-
typedef void (*callback_function)(void);
7-
void setOutput(callback_function drawScreen, int width, int height);
8-
void printCharXY(char c, int x, int y);
9-
void printString(char const s[], int x, int y);
1012
int getAbsoluteX(int x);
1113
int getAbsoluteY(int y);
1214
int getAbsoluteCoordinate(int value, int console, int track);
1315
int coordinatesOutOfBounds(int x, int y);
1416
void clearScreen(void);
15-
void redrawScreen();
1617
void registerSigWinChCatcher(void);
1718
void sigWinChCatcher(int signum);
1819
void updateConsoleSize(void);
1920
void copyArray(char dest[], const char src[], int width);
2021

21-
/////////////////////////////
22+
////////////////////////////
2223

2324
#define PRINT_IN_CENTER 1
2425
#define DEFAULT_WIDTH 80
@@ -33,38 +34,72 @@ int rows = DEFAULT_HEIGHT;
3334
callback_function drawScreen;
3435
volatile sig_atomic_t screenResized = 0;
3536

36-
///////// PUBLIC ////////////
37+
vector<string> screenBuffer;
38+
vector<string> onScreen;
39+
40+
////////// PUBLIC //////////
3741

3842
void setOutput(callback_function drawScreenThat, int width, int height) {
3943
drawScreen = drawScreenThat;
4044
pictureWidth = width;
4145
pictureHeight = height;
4246
registerSigWinChCatcher();
4347
updateConsoleSize();
44-
// set colors
48+
// Set colors.
4549
printf("\e[%dm\e[%dm", 37, 40);
4650
}
4751

48-
/////////////////////////
52+
void updateScreen() {
53+
for (size_t i = 0; i < screenBuffer.size(); i++) {
54+
if (onScreen.size() <= i) {
55+
onScreen.push_back("");
56+
}
57+
if (screenBuffer.at(i) != onScreen.at(i)) {
58+
onScreen.at(i) = screenBuffer.at(i);
59+
printf("\033[%d;%dH%s", getAbsoluteY(i), getAbsoluteX(0), screenBuffer.at(i).c_str());
60+
}
61+
}
62+
}
63+
64+
void setBuffer(string s, int x, int y) {
65+
int size = screenBuffer.size();
66+
if (size <= y) {
67+
for (int i = size; i <= y+1; i++) {
68+
screenBuffer.push_back("");
69+
}
70+
}
71+
screenBuffer.at(y).replace(x, s.length(), s);
72+
}
4973

5074
void printCharXY(char c, int x, int y) {
51-
if (coordinatesOutOfBounds(x, y))
75+
if (coordinatesOutOfBounds(x, y)) {
76+
return;
77+
}
78+
setBuffer(string(1, c), x, y);
79+
//printf("\033[%d;%dH%c", getAbsoluteY(y), getAbsoluteX(x), c);
80+
}
81+
82+
void printCharImediately(char c, int x, int y) {
83+
if (coordinatesOutOfBounds(x, y)) {
5284
return;
85+
}
5386
printf("\033[%d;%dH%c", getAbsoluteY(y), getAbsoluteX(x), c);
5487
}
5588

5689
void printString(char const s[], int x, int y) {
5790
if (coordinatesOutOfBounds(x, y))
5891
return;
59-
int itDoesntFitTheScreen = strlen(s) + x > columns;
92+
int itDoesntFitTheScreen = strlen(s) + (unsigned) x > (unsigned) columns;
6093
if (itDoesntFitTheScreen) {
6194
int distanceToTheRightEdge = columns - x - 1;
6295
char subArray[distanceToTheRightEdge+2];
6396
copyArray(subArray, s, distanceToTheRightEdge+2);
6497
s = subArray;
65-
printf("\033[%d;%dH%s", getAbsoluteY(y), getAbsoluteX(x), subArray);
98+
setBuffer(subArray, x, y);
99+
//printf("\033[%d;%dH%s", getAbsoluteY(y), getAbsoluteX(x), subArray);
66100
} else {
67-
printf("\033[%d;%dH%s", getAbsoluteY(y), getAbsoluteX(x), s);
101+
setBuffer(s, x, y);
102+
//printf("\033[%d;%dH%s", getAbsoluteY(y), getAbsoluteX(x), s);
68103
}
69104
}
70105

@@ -79,7 +114,7 @@ int getAbsoluteY(int y) {
79114
int getAbsoluteCoordinate(int value, int console, int track) {
80115
int offset = 0;
81116
if (PRINT_IN_CENTER) {
82-
offset = (console - track) / 2;
117+
offset = ((console - track) / 2) + ((console - track) % 2);
83118
if (offset < 0)
84119
offset = 0;
85120
}
@@ -90,22 +125,48 @@ int coordinatesOutOfBounds(int x, int y) {
90125
return x >= columns || y >= rows || x < 0 || y < 0;
91126
}
92127

93-
94-
////////// DRAW ///////////
128+
/////////// DRAW ///////////
129+
130+
void refresh() {
131+
for (size_t i = 0; i < screenBuffer.size(); i++) {
132+
if (onScreen.size() <= i) {
133+
onScreen.push_back("");
134+
}
135+
printf("\033[%d;%dH%s", getAbsoluteY(i), getAbsoluteX(0), screenBuffer.at(i).c_str());
136+
if (screenBuffer.at(i) != onScreen.at(i)) {
137+
onScreen.at(i) = screenBuffer.at(i);
138+
}
139+
}
140+
}
95141

96142
void clearScreen(void) {
143+
onScreen = {};
144+
screenBuffer = {};
97145
printf("\e[1;1H\e[2J");
98146
}
99147

100-
void redrawScreen() {
148+
void refreshScreen() {
101149
screenResized = 0;
102150
updateConsoleSize();
103151
clearScreen();
104152
drawScreen();
153+
refresh();
105154
fflush(stdout);
106155
}
107156

108-
/////////// SIGNALS /////////////
157+
158+
void redrawScreen() {
159+
if (screenResized == 1) {
160+
refreshScreen();
161+
} else {
162+
updateConsoleSize();
163+
drawScreen();
164+
updateScreen();
165+
fflush(stdout);
166+
}
167+
}
168+
169+
///////// SIGNALS //////////
109170

110171
void registerSigWinChCatcher() {
111172
struct sigaction action;
@@ -117,20 +178,24 @@ void registerSigWinChCatcher() {
117178
sigaction(SIGWINCH, &action, NULL);
118179
}
119180

120-
// Fires when window size changes
181+
/*
182+
* Fires when window size changes.
183+
*/
121184
void sigWinChCatcher(int signum) {
122185
screenResized = 1;
123186
}
124187

125-
// Asks system about window size
188+
/*
189+
* Asks system about window size.
190+
*/
126191
void updateConsoleSize() {
127192
struct winsize w;
128193
ioctl(0, TIOCGWINSZ, &w);
129194
columns = w.ws_col;
130195
rows = w.ws_row;
131196
}
132197

133-
///////// UTIL //////////
198+
/////////// UTIL ///////////
134199

135200
void copyArray(char dest[], const char src[], int width) {
136201
int i;
Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,25 @@
11
#ifndef OUTPUT_H
22
#define OUTPUT_H
33

4+
//#include "const.hpp"
5+
6+
#include <signal.h>
7+
8+
using namespace std;
9+
410
typedef void (*callback_function)(void);
11+
12+
// Initializes the output
513
void setOutput(callback_function drawScreen, int width, int height);
14+
15+
// API
616
void printCharXY(char c, int x, int y);
717
void printString(const char s[], int x, int y);
818
void redrawScreen();
9-
extern volatile sig_atomic_t screenResized;
19+
void printCharImediately(char c, int x, int y);
1020

21+
void clearScreen(void);
22+
23+
extern volatile sig_atomic_t screenResized;
24+
1125
#endif

0 commit comments

Comments
 (0)