chip8

A simple C CHIP8 VM.
git clone git://git.vgx.fr/chip8
Log | Files | Refs | README

media-sdl.c (3697B)


      1 #include <assert.h>
      2 #include <string.h>
      3 
      4 #include <SDL2/SDL.h>
      5 
      6 #include "media.h"
      7 
      8 #define PIXEL_RADIUS 16
      9 
     10 #define SCREEN_WIDTH (64*PIXEL_RADIUS)
     11 #define SCREEN_HEIGHT (32*PIXEL_RADIUS)
     12 
     13 #define WINDOW_NAME "CHIP-8 emulator"
     14 
     15 #define NUM_PIXELS (SCREEN_WIDTH*SCREEN_HEIGHT)
     16 #define SCREEN_RECT ((SDL_Rect){.x=0,.y=0,.w=SCREEN_WIDTH,.h=SCREEN_HEIGHT})
     17 
     18 #define SOUND_DEV_FREQ 48000
     19 #define SOUND_SAMPLES 1024
     20 #define BUZZER_FREQ 440
     21 #define BUZZER_VOL .05
     22 
     23 unsigned char *pixels;
     24 
     25 SDL_Window *window;
     26 SDL_Renderer *renderer;
     27 SDL_Texture *texture;
     28 
     29 /* sound state*/
     30 int buzzer_state = 0;
     31 
     32 /*
     33 ┌───┬───┬───┬───┐
     34 │ 1 │ 2 │ 3 │ C │
     35 ├───┼───┼───┼───┤
     36 │ 4 │ 5 │ 6 │ D │
     37 ├───┼───┼───┼───┤
     38 │ 7 │ 8 │ 9 │ E │
     39 ├───┼───┼───┼───┤
     40 │ A │ 0 │ B │ F │
     41 └───┴───┴───┴───┘
     42 */
     43 
     44 SDL_Keycode keys[16] = {
     45 	SDLK_v,
     46 	SDLK_3, SDLK_4, SDLK_5,
     47 	SDLK_e, SDLK_r, SDLK_t,
     48 	SDLK_d, SDLK_f, SDLK_g,
     49 	SDLK_c, SDLK_b,
     50 	SDLK_6, SDLK_y, SDLK_h, SDLK_n
     51 };
     52 
     53 static void buzzer_callback(void* userdata, Uint8* stream, int len){
     54 	static long sample_num = 0;
     55 	(void) userdata;
     56 	for(int i=0 ; i<len ; i++){
     57 		if(buzzer_state == 0)
     58 			stream[i] = 0;
     59 		else /* saw waves at the moment */
     60 			stream[i] =
     61 				((sample_num++*256*BUZZER_FREQ/SOUND_DEV_FREQ)
     62 				 %256)*BUZZER_VOL;
     63 	}
     64 }
     65 
     66 int m_init(int argc, char **argv){
     67 	(void)argc, (void)argv;
     68 	/*TODO: check every init */
     69 	
     70 	pixels = calloc(1,NUM_PIXELS);
     71 	
     72 	SDL_Init( SDL_INIT_EVERYTHING );
     73 	window = SDL_CreateWindow(
     74 			WINDOW_NAME,
     75 			SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
     76 			SCREEN_WIDTH, SCREEN_HEIGHT,
     77 			0);
     78 
     79 	renderer = SDL_CreateRenderer(
     80 			window, -1,
     81 			SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
     82 
     83 	texture = SDL_CreateTexture(
     84 			renderer,
     85 			SDL_PIXELFORMAT_RGB332, SDL_TEXTUREACCESS_STREAMING,
     86 			SCREEN_WIDTH, SCREEN_HEIGHT);
     87 
     88 	SDL_RenderClear(renderer);
     89 
     90 	SDL_OpenAudio(&(SDL_AudioSpec){
     91 			.freq = SOUND_DEV_FREQ,
     92 			.format = AUDIO_U8,
     93 			.channels = 1,
     94 			.samples = SOUND_SAMPLES,
     95 			.callback = buzzer_callback,
     96 			}, NULL);
     97 
     98 	SDL_PauseAudio(0);
     99 
    100 	return 0;
    101 }
    102 
    103 void m_quit(void){
    104 	SDL_DestroyTexture(texture);
    105 	SDL_DestroyRenderer(renderer);
    106 	SDL_DestroyWindow(window);
    107 
    108 	SDL_CloseAudio();
    109 
    110 	SDL_Quit();
    111 
    112 	free(pixels);
    113 }
    114 
    115 unsigned short get_input(unsigned short input){
    116 	SDL_Event e;
    117 
    118 	while(SDL_PollEvent(&e)){
    119 		if (e.type == SDL_QUIT) {
    120 			return -1;
    121 		}
    122 		if (e.type == SDL_KEYDOWN || e.type == SDL_KEYUP) {
    123 			for(int i=0;i<16;i++){
    124 				if(e.key.keysym.sym == keys[i]){
    125 					if(e.type == SDL_KEYDOWN){
    126 						input |= 1<<i;
    127 					} else {
    128 						input &= ~(1<<i);
    129 					}
    130 					break;
    131 				}
    132 			}
    133 		}
    134 	}
    135 
    136 	return input;
    137 }
    138 unsigned short wait_input(unsigned short input){
    139 	/* TODO: better version */
    140 	int new_input;
    141 	
    142 	while((new_input = get_input(input)) == input)
    143 		SDL_Delay(1);
    144 
    145 	return new_input;
    146 }
    147 
    148 void clear_screen(void){
    149 	memset(pixels,0,NUM_PIXELS);
    150 }
    151 
    152 void draw(int x, int y, int value){
    153 	assert(0<=x && x<64);
    154 	assert(0<=y && y<32);
    155 
    156 	for(int i=0 ; i<PIXEL_RADIUS ; i++){
    157 		for(int j=0 ; j<PIXEL_RADIUS ; j++){
    158 			pixels[(y*PIXEL_RADIUS+i)*SCREEN_WIDTH +
    159 				x*PIXEL_RADIUS+j] = value ? 255 : 0;
    160 		}
    161 	}
    162 }
    163 
    164 void frame(void){
    165 	void *texture_pixels;
    166 	int pitch; /* we don't actually use this, yolo */
    167 	SDL_LockTexture(texture, &SCREEN_RECT, &texture_pixels, &pitch);
    168 	memcpy(texture_pixels, pixels, NUM_PIXELS);
    169 	SDL_UnlockTexture(texture);
    170 
    171 	SDL_RenderCopy(renderer, texture, &SCREEN_RECT, &SCREEN_RECT);
    172 	SDL_RenderPresent(renderer);
    173 	SDL_RenderClear(renderer);
    174 }
    175 
    176 void set_buzzer_state(int state){
    177 	buzzer_state = state;
    178 }