I'm trying my hand at making a chip8 emulator using just plain C. I got most of the opcodes set so I just need to work on the display. I decided on using GLUT for the display since it appeared quick setup. The main idea is to display the chip8 sprites onto the 2D texture. I got it to display some digits though some opcode execution but it's flickering. I'm using double buffering since from what I read it's the best way to make sure something is ready to be displayed but I'm still getting flickering. Any ideas on what can cause it?
Here's all the code for OpenGL and GLUT for the display.
int main(int argc, char * argv[]) {
// if(argc < 2){
// printf("Usage: %s <bin file>\n", argv[0]);
// exit(0);
// }
//initialize chip 8
chip8_Init();
//load file if exists
chip8_load("test6.bin");
//setup graphics
glutInit(&argc, argv);
glutInitWindowSize(display_width, display_height);
glutInitWindowPosition(320, 320);
glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH);
glutCreateWindow("Chip8 GL");
setupTexture();
glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);
glutIdleFunc(renderScene);
glutKeyboardFunc(chip8_keypad);
glutKeyboardUpFunc(chip8_keypadUp);
glutMainLoop();
return 0;
}
void setupTexture(){
glClearColor (0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);
glEnable(GL_DEPTH_TEST);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGenTextures(1, &texName);
glBindTexture(GL_TEXTURE_2D, texName);
//set texture parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST);
//update texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCREEN_WIDTH,
SCREEN_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE,
screenData);
}
void updateTexture(){ //display()
//update pixels
for (int i = 0; i < SCREEN_HEIGHT; i++) {
for (int j = 0; j < SCREEN_WIDTH; j++) {
if(chip8.gfx[(i * SCREEN_WIDTH)+j] == 0){
screenData[i][j][0] = 0;
screenData[i][j][1] = 0;
screenData[i][j][2] = 0;
}
else{
screenData[i][j][0] = 255;
screenData[i][j][1] = 255;
screenData[i][j][2] = 255;
}
}
}
//update texture
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCREEN_WIDTH,
SCREEN_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE,
screenData);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glBindTexture(GL_TEXTURE_2D, texName);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex2d(0.0, 0.0);
glTexCoord2f(1.0, 0.0); glVertex2d(display_width, 0.0);
glTexCoord2f(1.0, 1.0); glVertex2d(display_width, display_height);
glTexCoord2f(0.0, 1.0); glVertex2d(0.0, display_height);
glEnd();
glutSwapBuffers();
}
void renderScene(){
chip8_emulateCycle();
if(drawFlag == 1){
updateTexture();
drawFlag = 0;
}
}
void changeSize(int w, int h){
glClearColor(0.0f, 0.0f, 0.5f, 0.0f);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, w, h, 0);
glMatrixMode(GL_MODELVIEW);
glViewport(0, 0, w, h);
// Resize quad
display_width = w;
display_height = h;
}
Edit: I might have figured it out. In the draw opcode, it uses XOR. So when the draw command for the first time the sprite is displayed and when called again it disappears and so on so forth.
My opengl is very dusty, but I saw some points in your code:
You should enable
GL_TEXTURE_2D
before initialize it:You should select the texture before modifying it
Moreover, you may test for the result of called functions, by using
glGetError()
:Said that, I don't know the data inside
chip8.gfx[]
, may be they are not as you expect.