Skip to content

Commit

Permalink
starting threading
Browse files Browse the repository at this point in the history
  • Loading branch information
mwillsey committed Feb 25, 2014
1 parent 2f3e824 commit ba79fe9
Show file tree
Hide file tree
Showing 3 changed files with 188 additions and 78 deletions.
11 changes: 8 additions & 3 deletions nes.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,17 @@ void nes_init (nes *n) {
n->chr_rom = &n->p->mem->ram[0x0000];
}

void nes_step (nes *n) {
void nes_step (nes *n) {
int i;
cpu_step(n);
for (i = 0; i < 7; i++)
ppu_step(n);
for (i=0; i<7; i++) {
/* give 3 cycles to ppu */
sem_post(n->p->clock);
sem_post(n->p->clock);
sem_post(n->p->clock);
}
}


byte *nes_frame_buffer(nes *n) {
return (byte*) n->p->frame_buffer;
Expand Down
14 changes: 14 additions & 0 deletions nes.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#include <stdlib.h>
#include <stdbool.h>

#include <pthread.h>
#include <semaphore.h>

typedef uint8_t byte;
typedef uint16_t addr;
typedef bool bit;
Expand All @@ -35,6 +38,7 @@ typedef struct {
} memory;

struct cpu_s {
sem_t clock;
memory *mem;
/* registers */
byte A; /* accumulator */
Expand All @@ -45,6 +49,9 @@ struct cpu_s {
};

struct ppu_s {
sem_t clock;
sem_t render_clock, bg_clock, oam_clock;

memory *mem;

int cycle; /* 341 per scanline */
Expand All @@ -67,6 +74,11 @@ struct ppu_s {
addr pt_shift_lo, pt_shift_hi;

/*** sprite stuff ***/
byte oam1[64][4];
byte oam2[8][4];
byte spr_shift[8][2];
byte spr_latch[8];
byte spr_count[8];


/* registers */
Expand All @@ -88,6 +100,8 @@ void nes_init(nes *n);
void nes_step(nes *n);
byte* nes_frame_buffer(nes *n);
void nes_destroy(nes *n);
/* new structure */
void nes_run(nes *n);

void cpu_init (nes *n);
void cpu_load (nes *n);
Expand Down
241 changes: 166 additions & 75 deletions ppu.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,102 +123,193 @@ void ppu_read_pt (ppu *p, bit hi) {
p->pt_latch_lo = mem_read(p->mem, pt_base_addr + pt_offset);
}

void render_run (ppu *p) {
byte bg_palette, pixel, color;
/* loop unit is one clock */
while (1) {
sem_wait(p->render_clock);
/* find out which palette we're using */
bg_palette = 0x3f01 + 3 * (p->at_latch >> ((p->cycle % 32 / 8) * 2));
/* make the pixel from the bit pattern */
pixel = ((p->pt_shift_hi >> i) << p->cycle % 8) |
(p->pt_shift_lo >> p->cycle % 8);
/* get the color from the palette (or universal bg color) */
color = pixel ? mem_read(p->mem, bg_palette + pixel) : mem_read(p->mem, 0x3f00);
/* draw it */
p->frame_buffer[p->scanline][p->cycle] = color;
}
}

void bg_run (ppu *p) {
while (1) {
for
switch (p->cycle % 8) {
case 1:
ppu_read_nt(p);
break;
case 3:
ppu_read_at(p);
break;
case 5:
ppu_read_pt(p, 0);
break;
case 7:
ppu_read_pt(p, 1);
/* shift and load from latches*/
p->at_shift = (p->at_shift >> 8) | ((addr)(p->at_latch << 8));
p->pt_shift_lo = (p->pt_shift_lo >> 8) | ((addr)(p->pt_latch_lo << 8));
p->pt_shift_hi = (p->pt_shift_hi >> 8) | ((addr)(p->pt_latch_hi << 8));
break;
}

}
}

void oam_run (ppu *p) {
while (1) {

}
}


void ppu_run (nes *n) {
ppu *p = n->p;

while (1) {
/* wait for a clock, then give it to components */
sem_wait(p->clock);
sem_post(p->render_clock);
sem_post(p->bg_clock);
sem_post(p->oam_clock);

/* propertly increment cycle */
p->cycle++;
if (p->cycle > 340) {
p->cycle = 0;
p->scanline++;
if (p->scanline > 261) {
p->scanline = 0;
p->even_frame = !p->even_frame;
}
}

}

/* clean up? */

}

void ppu_step (nes *n) {
ppu* p = n->p;
addr bg_palette;
byte pix;
int i;

//printf("cycle: %d, scanline: %d\n",p->cycle, p->scanline);

if (240 <= p->scanline && p->scanline <= 260) {
printf("cycle: %d, scanline: %d\n",p->cycle, p->scanline);
if (p->scanline == 241 && p->cycle == 0) {
printf("starting vblank");
p->status |= 0x80;
}
ppu_cycle_inc(p);
return;
}
sem_post(p->render_clock);

/* else in rendering scanline */

if (p->cycle == 0) {
/* this is an idle cycle */
ppu_cycle_inc(p);
return;
}
//printf("cycle: %d, scanline: %d\n",p->cycle, p->scanline);

if (p->cycle <= 256) {
if (p->scanline <= 239) {
/* visible scanlines */

i = p->cycle % 8;
if (p->cycle == 0) {
/* this is an idle cycle */
}

bg_palette = 0x3f01 + 3 * (p->at_latch >> ((p->cycle % 32 / 8) * 2));
pix = ((p->pt_shift_hi >> i) << 1) | (p->pt_shift_lo >> i);
pix = pix ? mem_read(p->mem, bg_palette + pix) : mem_read(p->mem, 0x3f00);
p->frame_buffer[p->scanline][p->cycle] = pix;
else if (p->cycle <= 256) {
/* /\* oam stuff *\/ */
/* if (p->cycle <= 64 && p->cycle % 2) { */
/* /\* clearing oam2 *\/ */
/* oam2[p->cycle / 4][p->cycle % 4] = 0xff; */
/* } else { */
/* /\* sprite handling *\/ */
/* int n = 0; */
/* int m = 0; */
/* int oam2_open = 0; */
/* byte b; */

/* while (oam2_open < 8) { */
/* b = oam1[n][0]; */
/* oam2[oam2_open][0] = b; */
/* if (0 <= p->scanline - b && p->scanline - b < 8) { */
/* /\* sprite is in range, take the whole thing *\/ */
/* oam2[oam2_open][1] = oam1[n][1]; */
/* oam2[oam2_open][2] = oam1[n][2]; */
/* oam2[oam2_open][3] = oam1[n][3]; */
/* oam2_open++ */
/* } */

/* } */


i = p->cycle % 8;
bg_palette = 0x3f01 + 3 * (p->at_latch >> ((p->cycle % 32 / 8) * 2));
pix = ((p->pt_shift_hi >> i) << 1) | (p->pt_shift_lo >> i);
pix = pix ? mem_read(p->mem, bg_palette + pix) : mem_read(p->mem, 0x3f00);
p->frame_buffer[p->scanline][p->cycle] = pix;
switch (p->cycle % 8) {
case 1:
ppu_read_nt(p);
break;
case 3:
ppu_read_at(p);
break;
case 5:
ppu_read_pt(p, 0);
break;
case 7:
ppu_read_pt(p, 1);
/* shift and load from latches*/
p->at_shift = (p->at_shift >> 8) | ((addr)(p->at_latch << 8));
p->pt_shift_lo = (p->pt_shift_lo >> 8) | ((addr)(p->pt_latch_lo << 8));
p->pt_shift_hi = (p->pt_shift_hi >> 8) | ((addr)(p->pt_latch_hi << 8));
break;
}
}

switch (p->cycle % 8) {
case 1:
ppu_read_nt(p);
break;
case 3:
ppu_read_at(p);
break;
case 5:
ppu_read_pt(p, 0);
break;
case 7:
ppu_read_pt(p, 1);
/* shift and load from latches*/
p->at_shift = (p->at_shift >> 8) | ((addr)(p->at_latch << 8));
p->pt_shift_lo = (p->pt_shift_lo >> 8) | ((addr)(p->pt_latch_lo << 8));
p->pt_shift_hi = (p->pt_shift_hi >> 8) | ((addr)(p->pt_latch_hi << 8));
break;
else if(p->cycle <= 320) {
/* fetch sprites for next scanline */
}

ppu_cycle_inc(p);
return;
else if(p->cycle <= 336) {
/* load the shift registers for next scanline */
switch (p->cycle % 8) {
case 1:
ppu_read_nt(p);
break;
case 3:
ppu_read_at(p);
break;
case 5:
ppu_read_pt(p, 0);
break;
case 7:
ppu_read_pt(p, 1);
/* shift and load from latches*/
p->at_shift = (p->at_shift >> 8) | ((addr)(p->at_latch << 8));
p->pt_shift_lo = (p->pt_shift_lo >> 8) | ((addr)(p->pt_latch_lo << 8));
p->pt_shift_hi = (p->pt_shift_hi >> 8) | ((addr)(p->pt_latch_hi << 8));
break;
}
}
}

if(p->cycle <= 320) {
/* fetch sprites for next scanline */
ppu_cycle_inc(p);
return;
else if (p->scanline == 240) {
/* visible scanline, just idle*/
}

if(p->cycle <= 336) {
/* load the shift registers for next scanline */
switch (p->cycle % 8) {
case 1:
ppu_read_nt(p);
break;
case 3:
ppu_read_at(p);
break;
case 5:
ppu_read_pt(p, 0);
break;
case 7:
ppu_read_pt(p, 1);
/* shift and load from latches*/
p->at_shift = (p->at_shift >> 8) | ((addr)(p->at_latch << 8));
p->pt_shift_lo = (p->pt_shift_lo >> 8) | ((addr)(p->pt_latch_lo << 8));
p->pt_shift_hi = (p->pt_shift_hi >> 8) | ((addr)(p->pt_latch_hi << 8));
break;
}

if (p->scanline == 261) { /* leaving vblank */
p->status &= 0x7f;
printf("leaving vblank");
}
else if (p->scanline <= 260) {
/* vertical blanking lines */
if (p->scanline == 241 && p->cycle == 0)
p->status |= 0x80;
}

ppu_cycle_inc(p);
return;
else {
/* pre-render scanline (261) */
/* TODO: add in even odd timing? */
p->status &= 0x7f;
}

/* else */
ppu_cycle_inc(p);
return;
}
Expand Down

0 comments on commit ba79fe9

Please sign in to comment.