Last active
May 16, 2019 23:15
-
-
Save cust0m/5da509c2d9cd0fbdf80b3056d795633b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <SDL.h> | |
#include <stdio.h> | |
#include <time.h> | |
// Screen dimension constants | |
const int SCREEN_WIDTH = 160; | |
const int SCREEN_HEIGHT = 160; | |
// Registers | |
uint16_t pc; | |
uint16_t sp; | |
uint16_t a; | |
uint16_t x; | |
uint16_t y; | |
uint16_t p; | |
// Memory | |
uint8_t* memory; | |
// Break Flag | |
int break_flag = 0; | |
// Instruction Functions | |
void brk(); | |
void lda_imm(); | |
void lda_zer(); | |
void sta_zer(); | |
void sta_abs(); | |
void sta_iny(); | |
void and_imm(); | |
void adc_imm(); | |
void jmp(); | |
// Renderer of screen | |
SDL_Renderer *renderer; | |
// Instruction Table | |
void (*instructions[256])(); | |
// Populate Instruction Table | |
void init_ins_table(){ | |
for(int i = 0; i < 256; i++) { | |
instructions[i] = &brk; | |
} | |
instructions[0xA9] = &lda_imm; | |
instructions[0xA5] = &lda_zer; | |
instructions[0x85] = &sta_zer; | |
instructions[0x8D] = &sta_abs; | |
instructions[0x91] = &sta_iny; | |
instructions[0x29] = &and_imm; | |
instructions[0x69] = &adc_imm; | |
instructions[0x4c] = &jmp; | |
} | |
// Read from memmory | |
uint8_t read_mem(uint16_t address) { | |
if(address==0xfe){ | |
uint8_t rand_return = (uint8_t) rand(); | |
return rand_return; | |
} | |
return memory[address]; | |
} | |
// Write in memory | |
void write_mem(uint16_t address, uint8_t value) { | |
memory[address] = value; | |
} | |
void reset_cpu(){ | |
memory = malloc(65536); | |
memset(memory, 0, 65536); | |
// Initialize regiters | |
a = 0; | |
pc = 0x0600; | |
// Initialize program | |
/* memcpy(memory+0x0600, "\xA9\x01\x8d\x00\x02\xA9\x05\x8d\x01\x02\xA9\x08\x8d\x02\x02", 19); */ | |
memcpy(memory+0x0600, "\xa5\xfe\x85\x00\xa5\xfe\x29\x03\x69\x02\x85\x01\xa5\xfe\x91\x00\x4c\x00\x06", 19); | |
/* memcpy(memory+pc, "\xa5\xfe\x85\x01\x91\x01\x4c\x00\x06", 0); */ | |
} | |
// Instructions implementations | |
void brk(){ | |
break_flag = 1; | |
} | |
void lda_imm(){ | |
a = read_mem(++pc); | |
pc++; | |
} | |
void lda_zer(){ | |
uint8_t mem_address = read_mem(++pc); | |
a = read_mem(mem_address); | |
pc++; | |
} | |
void sta_zer(){ | |
write_mem(read_mem(++pc),a); | |
pc++; | |
} | |
void sta_abs(){ | |
uint8_t low_address = read_mem(++pc); | |
uint8_t high_address = read_mem(++pc); | |
uint16_t mem_address = low_address + (high_address << 8); | |
write_mem(mem_address,a); | |
pc++; | |
} | |
void sta_iny(){ | |
uint16_t base_address = read_mem(++pc); | |
uint16_t low_address = read_mem(base_address); | |
uint16_t high_address = read_mem(base_address + 1); | |
uint16_t mem_address = (low_address + (high_address << 8)) + y; | |
write_mem(mem_address,a); | |
pc++; | |
} | |
void and_imm(){ | |
a = a & read_mem(++pc); | |
pc++; | |
} | |
void adc_imm(){ | |
uint8_t m = read_mem(++pc); | |
a = a + m; | |
pc++; | |
} | |
void jmp(){ | |
uint8_t low_address = read_mem(++pc); | |
uint8_t high_address = read_mem(++pc); | |
uint16_t mem_address = low_address + (high_address << 8); | |
pc = mem_address; | |
} | |
void set_renderer_color(uint8_t color){ | |
color = color & 0x0F; | |
switch(color) { | |
case 0x0: SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); | |
break; | |
case 0x1: SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); | |
break; | |
case 0x2: SDL_SetRenderDrawColor(renderer, 136, 0, 255, 255); | |
break; | |
case 0x3: SDL_SetRenderDrawColor(renderer, 170, 255, 238, 255); | |
break; | |
case 0x4: SDL_SetRenderDrawColor(renderer, 204, 68, 204, 255); | |
break; | |
case 0x5: SDL_SetRenderDrawColor(renderer, 0, 204, 85, 255); | |
break; | |
case 0x6: SDL_SetRenderDrawColor(renderer, 0, 0, 170, 255); | |
break; | |
case 0x7: SDL_SetRenderDrawColor(renderer, 238, 238, 119, 255); | |
break; | |
case 0x8: SDL_SetRenderDrawColor(renderer, 221, 136, 85, 255); | |
break; | |
case 0x9: SDL_SetRenderDrawColor(renderer, 102, 68, 0, 255); | |
break; | |
case 0xa: SDL_SetRenderDrawColor(renderer, 255, 119, 199, 255); | |
break; | |
case 0xb: SDL_SetRenderDrawColor(renderer, 51, 51, 51, 255); | |
break; | |
case 0xc: SDL_SetRenderDrawColor(renderer, 119, 199, 119, 255); | |
break; | |
case 0xd: SDL_SetRenderDrawColor(renderer, 170, 255, 102, 255); | |
break; | |
case 0xe: SDL_SetRenderDrawColor(renderer, 0, 136, 255, 255); | |
break; | |
case 0xf: SDL_SetRenderDrawColor(renderer, 187, 187, 187, 255); | |
break; | |
} | |
} | |
void render_screen(){ | |
for(uint16_t i = 0x200; i <= 0x5ff;i++){ | |
uint16_t screen_pos = (i-512); | |
uint16_t line = (uint16_t)screen_pos/32; | |
uint16_t column = (uint16_t)(screen_pos-(line*32)); | |
set_renderer_color(memory[i]); | |
SDL_RenderDrawPoint(renderer, column, line); | |
} | |
SDL_RenderPresent(renderer); | |
} | |
void run_cpu(){ | |
SDL_Event event; | |
break_flag = 0; | |
/* for(;;){ */ | |
while (1) { | |
/* SDL_RenderClear(renderer); */ | |
if (SDL_PollEvent(&event) && event.type == SDL_QUIT) | |
break; | |
/* printf("A: %04x \n", a); */ | |
/* printf("PC: %04x \n", pc); */ | |
if(break_flag==1) | |
break; | |
(*instructions[read_mem(pc)])(); | |
render_screen(); | |
} | |
} | |
int main( int argc, char* args[] ) | |
{ | |
srand(time(NULL)); | |
SDL_Event event; | |
SDL_Window *window; | |
init_ins_table(); | |
reset_cpu(); | |
SDL_Init(SDL_INIT_VIDEO); | |
SDL_CreateWindowAndRenderer(SCREEN_WIDTH, SCREEN_HEIGHT, 0, &window, &renderer); | |
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); | |
SDL_RenderClear(renderer); | |
SDL_RenderSetScale(renderer, 5, 5); | |
/* render_screen(); */ | |
run_cpu(); | |
/* SDL_SetRenderDrawColor(renderer, 255, 0, 255, 255); */ | |
/* SDL_RenderDrawPoint(renderer, 0, 0); */ | |
SDL_RenderPresent(renderer); | |
/* SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255); */ | |
/* SDL_RenderDrawPoint(renderer, 1, 0); */ | |
while (1) { | |
if (SDL_PollEvent(&event) && event.type == SDL_QUIT) | |
break; | |
} | |
SDL_DestroyRenderer(renderer); | |
SDL_DestroyWindow(window); | |
SDL_Quit(); | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment