/
ppu.c
88 lines (72 loc) · 1.42 KB
/
ppu.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <stdlib.h>
#include "ppu.h"
#include "cpu.h"
#include "sdl.h"
struct PPU {
int vblank_nmi;
int frame;
unsigned char *mem;
unsigned char *tiles;
unsigned char *nametable;
unsigned int increment;
unsigned int addr;
unsigned int addr_count;
unsigned int bg;
};
static struct PPU p;
void ppu_write_reg1(unsigned int val)
{
/* Possible addresses for name tables */
unsigned int name_tables[] = {0x2000, 0x2400, 0x2800, 0x2C00};
/* Creates a pointer into p.mem at the correct offset */
p.nametable = &p.mem[name_tables[val&0x3]];
p.increment = val & 0x4 ? 32 : 1;
if(val & 0x10)
p.tiles = &p.mem[0x1000];
else
p.tiles = &p.mem[0x0000];
p.vblank_nmi = !!(val & 0x80);
}
void ppu_write_reg2(unsigned int val)
{
p.bg = !!(val & 0x8);
}
void ppu_write_addr(unsigned int val)
{
if(p.addr_count == 0){
p.addr = (val & 0x3F)<<8;
p.addr_count = 1;
} else {
p.addr |= val;
p.addr_count = 0;
}
}
void ppu_write_data(unsigned int val)
{
p.mem[p.addr] = val;
p.addr += p.increment;
}
void init_ppu(void)
{
init_sdl();
p.frame = 0;
p.addr_count = 0;
p.mem = calloc(1, 0x4000);
}
static void ppu_vblank_starts(void)
{
sdl_frame();
if(p.vblank_nmi)
cpu_nmi(0xFFFA);
}
void ppu(unsigned int cycles)
{
int frame;
if(!sdl_update()) /* returns false if SDL caught a quit event */
return;
frame = cycles / 113.6f;
frame %= 262;
if(frame == 242 && p.frame == 241)
ppu_vblank_starts();
p.frame = frame;
}