commit f5a1325664fa0b7dda67a7273c5ec3c33654963d
parent 024662694be4fddbe0ccbdd0631a14406d9c2497
Author: Léo Villeveygoux <leo.villeveygoux@u-bordeaux.fr>
Date: Sat, 1 Dec 2018 01:35:22 +0100
add sdl media handling
Simple, probably buggy at the moment, SDL input, graphics output, timer
handling.
Still no sound at the moment.
Diffstat:
A | build.sh | | | 1 | + |
M | chip8.c | | | 26 | ++++++++++++++++++-------- |
A | media-sdl.c | | | 149 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | media.h | | | 17 | +++++++++++++++++ |
4 files changed, 185 insertions(+), 8 deletions(-)
diff --git a/build.sh b/build.sh
@@ -0,0 +1 @@
+gcc chip8.c media-sdl.c -o chip8 $(sdl2-config --cflags --libs)
diff --git a/chip8.c b/chip8.c
@@ -3,6 +3,8 @@
#include <time.h>
#include <unistd.h>
+#include "media.h"
+
unsigned char RAM[0x1000];
unsigned char V[16];
@@ -147,6 +149,8 @@ void step(){
case 0x00E0: /* clear screen */
for(int i=0 ; i<256 ; i++)
SCREEN[i] = 0;
+ clear_screen();
+ send_draw();
break;
case 0x00EE: /* return from a subroutine */
if(SP)
@@ -257,7 +261,7 @@ void step(){
*screen_tile ^= sprite_tile;
}
}
- /*XXX:debug*/
+ /*TODO: mybe uptade just the right part*/
display();
//usleep(500000);
break;
@@ -335,11 +339,11 @@ void display(){
for(int y=0 ; y<32 ; y++){
for(int xc=0 ; xc<8 ; xc++){
for(int xb=7 ; xb>=0 ; xb--){
- printf("%s",SCREEN[y*8+xc]&1<<xb ? "█":" ");
+ draw(xc*8 + 7-xb, y, SCREEN[y*8+xc]&1<<xb ? 1:0);
}
}
- printf("\n");
}
+ send_draw();
}
int main(int argc, char **argv){
@@ -360,16 +364,20 @@ int main(int argc, char **argv){
fclose(rom);
/*TODO: init more stuff: graphics, input, sound, timer*/
+ m_init(argc, argv);
/* Let's go */
for(int i=0 ; 1 ; i++){
+ KEYBOARD = get_input(KEYBOARD);
+ if(KEYBOARD == (unsigned short)-1)
+ break;
+
step();
- /*XXX:debug*/
- /*TODO: other stuff*/
- //display();
- nanosleep(&(struct timespec){0,1000000},NULL);
+
+ //nanosleep(&(struct timespec){0,1000000},NULL);
+ wait_tick();
+
if(!(i%16)){
- //display();
if(DT)
DT--;
if(ST)
@@ -378,5 +386,7 @@ int main(int argc, char **argv){
printf("i=%5d, DT=%3d \r", i, (int)DT);
}
+ m_quit();
+
return 0;
}
diff --git a/media-sdl.c b/media-sdl.c
@@ -0,0 +1,149 @@
+#include <SDL2/SDL.h>
+#include <string.h>
+
+#include "media.h"
+
+#define PIXEL_RADIUS 16
+
+#define SCREEN_WIDTH (64*PIXEL_RADIUS)
+#define SCREEN_HEIGHT (32*PIXEL_RADIUS)
+
+#define WINDOW_NAME "CHIP-8 emulator"
+
+#define NUM_PIXELS (SCREEN_WIDTH*SCREEN_HEIGHT)
+unsigned char *pixels;
+
+SDL_Window *window;
+SDL_Renderer *renderer;
+SDL_Texture *texture;
+SDL_Rect rect = {.x=0,.y=0,.w=SCREEN_WIDTH,.h=SCREEN_HEIGHT};
+
+unsigned clock;
+
+/*
+┌────┬────┬────┬────┐
+│ 1 │ 2 │ 3 │ C │
+├────┼────┼────┼────┤
+│ 4 │ 5 │ 6 │ D │
+├────┼────┼────┼────┤
+│ 7 │ 8 │ 9 │ E │
+├────┼────┼────┼────┤
+│ A │ 0 │ B │ F │
+└────┴────┴────┴────┘
+*/
+
+SDL_Keycode keys[16] = {
+ SDLK_v,
+ SDLK_QUOTEDBL, SDLK_QUOTE, SDLK_LEFTPAREN,
+ SDLK_e, SDLK_r, SDLK_t,
+ SDLK_d, SDLK_f, SDLK_g,
+ SDLK_c, SDLK_b,
+ SDLK_MINUS, SDLK_y, SDLK_h, SDLK_n
+};
+
+int m_init(int argc, char **argv){
+ (void)argc, (void)argv;
+ /*TODO: check every init */
+
+ pixels = calloc(1,NUM_PIXELS);
+
+ SDL_Init( SDL_INIT_EVERYTHING );
+ window = SDL_CreateWindow(
+ WINDOW_NAME,
+ SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
+ SCREEN_WIDTH, SCREEN_HEIGHT,
+ 0);
+
+ renderer = SDL_CreateRenderer(
+ window, -1,
+ SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
+
+ texture = SDL_CreateTexture(
+ renderer,
+ SDL_PIXELFORMAT_RGB332, SDL_TEXTUREACCESS_STREAMING,
+ SCREEN_WIDTH, SCREEN_HEIGHT);
+
+ SDL_RenderClear(renderer);
+
+ clock = SDL_GetTicks();
+
+ return 0;
+}
+
+void m_quit(void){
+ SDL_DestroyTexture(texture);
+ SDL_DestroyRenderer(renderer);
+ SDL_DestroyWindow(window);
+ SDL_Quit();
+
+ free(pixels);
+}
+
+unsigned short get_input(unsigned short input){
+ SDL_Event e;
+
+ while(SDL_PollEvent(&e)){
+ if (e.type == SDL_QUIT) {
+ return -1;
+ }
+ if (e.type == SDL_KEYDOWN || e.type == SDL_KEYUP) {
+ for(int i=0;i<16;i++){
+ if(e.key.keysym.sym == keys[i]){
+ if(e.type == SDL_KEYDOWN){
+ input |= 1<<i;
+ } else {
+ input &= ~(1<<i);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ return input;
+}
+unsigned short wait_input(unsigned short input){
+ /* TODO: better version */
+ int new_input;
+
+ while((new_input = get_input(input)) == input)
+ SDL_Delay(1);
+
+ return new_input;
+}
+
+void clear_screen(void){
+ memset(pixels,0,NUM_PIXELS);
+}
+
+void draw(int x, int y, int value){
+ for(int i=0 ; i<PIXEL_RADIUS ; i++){
+ for(int j=0 ; j<PIXEL_RADIUS ; j++){
+ pixels[(y*PIXEL_RADIUS+i)*SCREEN_WIDTH +
+ x*PIXEL_RADIUS+j] = value ? 255 : 0;
+ }
+ }
+}
+
+void send_draw(void){
+ void *texture_pixels;
+ int pitch; /* we don't actually use this, yolo */
+ SDL_LockTexture(texture, &rect, &texture_pixels, &pitch);
+ memcpy(texture_pixels, pixels, NUM_PIXELS);
+ SDL_UnlockTexture(texture);
+
+ SDL_RenderCopy(renderer, texture, &rect, &rect);
+ SDL_RenderPresent(renderer);
+ SDL_RenderClear(renderer);
+}
+
+void wait_tick(void){
+ /* TODO: tunable frequency */
+ unsigned new_clock = SDL_GetTicks();
+
+ if(new_clock == clock){
+ SDL_Delay(1);
+ }
+
+ clock = SDL_GetTicks();
+}
diff --git a/media.h b/media.h
@@ -0,0 +1,17 @@
+#ifndef C8_MEDIA_H
+#define C8_MEDIA_H
+
+int m_init(int argc, char **argv);
+
+void m_quit(void);
+
+unsigned short get_input(unsigned short input);
+unsigned short wait_input(unsigned short input);
+
+void clear_screen(void);
+void draw(int x, int y, int value);
+void send_draw(void);
+
+void wait_tick(void);
+
+#endif /* C8_MEDIA_H */