diff options
| -rw-r--r-- | CMakeLists.txt | 2 | ||||
| -rw-r--r-- | chip8.c | 132 | ||||
| -rw-r--r-- | main.c | 6 | 
3 files changed, 122 insertions, 18 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index bda00bc..9f3f950 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ add_executable(  	chip8  	main.c chip8.c chip8.h) -target_compile_options(chip8 PRIVATE -Wall) +target_compile_options(chip8 PRIVATE -Wall -Wextra)  target_link_libraries(chip8 PRIVATE SDL2::SDL2) @@ -96,10 +96,8 @@ chip8_draw_sprite(int startx, int starty, uint16_t mem, uint8_t size)  	/*  	 * draw sprite located at loc of height size at startx,starty  	 */ -  	uint8_t byte = 0;  	uint8_t mask = 0x1; -	V[0xF] = 0; /* set collision register to 0 */  	for (uint8_t byteoffset = 0; byteoffset < size; byteoffset++)  	{  		/* loop through each byte from mem to mem+size */ @@ -110,12 +108,10 @@ chip8_draw_sprite(int startx, int starty, uint16_t mem, uint8_t size)  			if (byte & mask)  			{  				uint32_t pixel = WIDTH*(starty%HEIGHT)+((startx%WIDTH)+bit); -				if (video[pixel] != 0) -				{ -					/* if the video bit is already set, we need to set the collision register */ -					V[0xF] = 1; -				} +				/* if the video bit is already set, we need to set the collision register */ +				V[0xF] = (video[pixel] != 0) ? 1 : 0;  				video[pixel] ^= PIXEL_COLOR; +				draw_flag = 1;  			}  			bit++;  		} @@ -155,7 +151,7 @@ chip8_cycle()  	uint8_t x = (opcode >> 8) & 0x000F;	// lower 4 bits of the high byte, we discard the low byte by right shifting it out  	uint8_t y = (opcode >> 4) & 0x000F;	// upper 4 bits of the low byte, so we need to discard the lower 4 bits  	uint8_t kk = opcode & 0x00FF;		// lowest 8 bits -	printf("parsing at 0x%03X\n", PC); +	printf("parsing at 0x%03X opcode = 0x%04X\n", PC, opcode);  	PC += 2; // TODO: remove  	switch (opcode & 0xF000)  	{ @@ -189,18 +185,15 @@ chip8_cycle()  		break;  	case 0x3000: /* SE Vx, byte (skip next instruction if Vx = kk) */  		// TODO: not tested -		if (V[x] == kk) -			PC += 2; +		PC += (V[x] == kk) ? 2 : 0;  		break;  	case 0x4000: /* SN Vx, byte (skip next instruction if Vx != kk) */  		// TODO: not tested -		if (V[x] != kk) -			PC += 2; +		PC += (V[x] != kk) ? 2 : 0;  		break;  	case 0x5000: /* SE Vx, Vy (skip next instruction if Vx == Vy) */  		// TODO: not tested -		if (V[x] == V[y]) -			PC += 2; +		PC += (V[x] == V[y]) ? 2 : 0;  		break;  	case 0x6000: /* LD Vx, byte (load byte in register x) */  	{ @@ -264,6 +257,117 @@ chip8_cycle()  			break;  		default: unknown_opcode(opcode);  		} +		break; +	} +	case 0x9000: /* SNE Vx, Vy (skip next instruction if Vx != Vy) */ +		// TODO: not tested +		PC += (V[x] != V[y]) ? 2 : 0; +		break; +	case 0xA000: /* LD I, addr (load register I with addr) */ +		// TODO: not tested +		I = nnn; +		break; +	case 0xB000: /* JP V0, addr (set PC to location nnn + V0) */ +		// TODO: not tested +		PC = V[0] + nnn; +		break; +	case 0xC000: /* RND Vx, byte (set Vx to a random byte and AND it by kk) */ +		// TODO: not tested +		V[x] = (rand() % 256) & kk; // random number between 0 and 255 +		break; +	case 0xD000: /* DRW Vx, Vy, n (read n bytes from starting starting at address in register I, and draws then at coordinates x,y */ +		// TODO: not tested +		chip8_draw_sprite(V[x], V[y], I, n); +		break; +	case 0xE000: /* key input */ +	{ +		switch(kk) +		{ +		case 0x9E: /* SKP Vx (skip next instruction if key Vx is pressed) */ +			// TODO: not tested +			PC += (key[V[x]] == 1) ? 2 : 0; +			break; +		case 0xA1: /* SKNP Vx (skip next instruction if key Vx is not pressed) */ +			// TODO: not tested +			PC += (key[V[x]] == 0) ? 2 : 0; +			break; +		default: unknown_opcode(opcode); +		} +		break; +	} +	case 0xF000: +	{ +		switch (kk) +		{ +		case 0x07: /* LD Vx, DT (load Vx with the value of delay timer register) */ +			// TODO: not tested +			V[x] = delay_timer; +			break; +		case 0x0A: /* LD Vx, K (all execution stops until a key is pressed, then that key is put into Vx) */ +		{ +			// TODO: not tested +			int found_key = 0; +			for (int i = 0; i < 15; i++) +			{ +				V[x] = key[i]; +				if (V[x] == 1) +					found_key = 1; +			} +			PC -= (found_key == 0) ? 2 : 0; +			break; +		} +		case 0x15: /* LD DT, Vx (delay timer is set to the value of Vx */ +			// TODO: not tested +			delay_timer = V[x]; +			break; +		case 0x18: /* LD ST, Vx (sound timer is set to the value of Vx */ +			// TODO: not tested +			sound_timer = V[x]; +			break; +		case 0x1E: /* ADD I, Vx (set I register to I + Vx) */ +			// TODO: not tested +			I += V[x]; +			break; +		case 0x29: /* LD F, Vx (set register I to location of the hex sprite Vx) */ +			// TODO: not tested +			I = V[x] * 5; +			break; +		case 0x33: /* LD B, Vx (store BCD representation of Vx in memory locations I, I+1 and I+2) */ +			// TODO: not tested +			memory[I]  = (V[x] % 1000) / 100; +			memory[I+1] = (V[x] % 100) / 10; +			memory[I+2] = (V[x] % 10); +			break; +		case 0x55: /* LD [I], Vx (store registers V0 through Vx starting at memory location I) */ +		{ +			// TODO: not tested +			int reg = 0; +			do +			{ +				memory[I+reg] = V[reg]; +				reg++; +			} +			while (reg <= V[x]); +			break; +		} +		case 0x65: /* LD Vx, [I] (read registers V0 through Vx from memory starting at I) */ +		{ +			// TODO: not tested +			int reg = 0; +			int target = V[x]; +			do +			{ +				V[reg] = memory[I+reg]; +				reg++; +			} +			while (reg < target); +			break; +		} +			break; + +		default: unknown_opcode(opcode); +		} +		break;  	}  	default: unknown_opcode(opcode);  	} @@ -14,7 +14,7 @@   */  #define VIDEO_SCALE 5 -#define STEPPING 1 // set to 1 to step manually through program +#define STEPPING 0 // set to 1 to step manually through program  SDL_Window *window;  SDL_Renderer *renderer; @@ -205,13 +205,14 @@ int main(int argc, char *argv[])  	init_video(); -	const int fps = 1; +	const int fps = 500;  	const int frame_delay = 1000/fps;  	uint32_t  frame_start;  	uint32_t frame_time;  	int do_quit = 0; +	/*  	chip8_draw_sprite(0, 0, 0xD*5, 0x5);  	chip8_draw_sprite(5, 0, 0xE*5, 0x5);  	chip8_draw_sprite(10, 0, 0xA*5, 0x5); @@ -230,7 +231,6 @@ int main(int argc, char *argv[])  	chip8_draw_sprite(30, 9, 0xE*5, 0x5);  	chip8_draw_sprite(35, 9, 0xf*5, 0x5); -	/*  	chip8_draw_sprite(0, 20, 0x200, 0x6);  	chip8_draw_sprite(8, 20, 0x200, 0x6);  	chip8_draw_sprite(16, 20, 0x200, 0x6);  | 
