-
Notifications
You must be signed in to change notification settings - Fork 1
/
init.c
136 lines (114 loc) · 4.15 KB
/
init.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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "snesc.h"
#include "mem.h"
extern void* __nmi_handler;
unsigned char snesc_do_copy; /* bit 7: do sprite copy, bit 6: do palette copy
bits 0-5: DMA transfer count */
unsigned char snesc_timer_enabled; /* each bit one timer */
unsigned int snesc_timers[16];
struct oam_table1 snesc_oam_table1[128]; /* OAM low table */
unsigned int snesc_oam_table2[16]; /* OAM high table */
unsigned char snesc_palette[512]; /* palette */
unsigned int snesc_controllers[4]; /* data from 4 controllers */
struct dma_transfer snesc_dma_transfers[64]; /* DMA transfers
0 (src_addr, src_bank) src address (24 bit)
3 (dest) dest address (16 bit)
5 (size) size (16 bit)
7 (type) type (8 bit, 0 == VRAM, 1 == OAM, 2 == CGRAM, >2 == ???) */
void do_dma(unsigned char do_flags)
{
if(do_flags & 0x80) /* copy sprites? */
{
*((unsigned short*)0x4300) = 0x400; /* DMA channel 0 Bus B addr $2104 (OAM write) */
/* the original code loads $8000, turning on sprite priority and
messing up the gfx (some emulators don't emulate this
correctly, which is probably why it has slipped through) */
*(unsigned short*)0x2102 = 0; /* OAM address 0 */
*((void**)0x4302) = snesc_oam_table1; /* DMA source address (24 bits); hairy: writes 32 bits... */
*(unsigned short*)0x4305 = 0x220; /* DMA size */
*(unsigned char*)0x420b = 1; /* enable DMA 0 */
}
if(do_flags & 0x40) /* copy palette? */
{
*(unsigned short*)0x4300 = 0x2200; /* DMA channel 0 Bus B addr $2122 (CGRAM write) */
*((void**)0x4302) = snesc_palette; /* DMA source address; see above */
*(unsigned short*)0x4305 = 0x200; /* DMA size */
*(unsigned char*)0x2121 = 0; /* CGRAM address 0 */
*(unsigned char*)0x420b = 1; /* enable DMA 0 */
}
}
void snesc_vblank(void)
{
/* stuff pending for DMA? */
unsigned char do_flags = snesc_do_copy;
if(do_flags)
{
snesc_do_copy = 0;
do_dma(do_flags);
do_flags &= 0x3f; /* mask out palette and sprite flags (used by do_dma) */
if(do_flags)
{
int x = 0;
while(do_flags)
{
switch(snesc_dma_transfers[x].src.c.type) /* type of transfer */
{
case 0: /* VRAM */
poke16(0x4300, 0x1801); // 2 regs write once, Bus B addr $2118 (VRAM data write)
poke16(0x2116, snesc_dma_transfers[x].dest); // VRAM address
break;
case 1: /* OAM */
poke16(0x4300, 0x400); // DMA OAM write
poke16(0x2102, snesc_dma_transfers[x].dest); // OAM address
break;
case 2: /* CGRAM */
poke16(0x4300, 0x2200); // CGRAM write
poke(0x2121, snesc_dma_transfers[x].dest); // CGRAM address (trunc'd to 8 bits)
break;
}
*((unsigned short*)0x4302) = snesc_dma_transfers[x].src.c.addr; /* DMA source address (16-bit) */
*((unsigned short*)0x4305) = snesc_dma_transfers[x].size; /* DMA size */
*((unsigned char*)0x4304) = snesc_dma_transfers[x].src.c.bank; /* DMA source address (bank) */
*((unsigned char*)0x420b) = 1; /* enable DMA 0 */
x++;
do_flags--;
}
}
}
while(peek(0x4212) & 1)
{
}
/* update input buffers */
unsigned int pad;
for(pad = 0; pad < 4; pad++)
{
snesc_controllers[pad] |= ((unsigned short*)0x4218)[pad];
}
/* timer ticks */
unsigned char timers_enabled = snesc_timer_enabled;
unsigned int tc = 0;
while(timers_enabled & 1)
{
snesc_timers[tc]++;
tc++;
timers_enabled >>= 1;
}
}
void snesc_init(void)
{
int i;
__nmi_handler = snesc_vblank; /* register vblank handler */
*((unsigned char*)0x4200) = 0x81; /* enable NMI, enable autojoy */
snesc_timer_enabled = snesc_do_copy = snesc_controllers[0] = 0;
/* snesc sprite init stuff */
for(i = 0; i < 128; i++)
{
snesc_oam_table1[i].x = 0;
snesc_oam_table1[i].y = 0xe8;
snesc_oam_table1[i].t = 0;
snesc_oam_table1[i].p = 0;
}
for(i = 0; i < 32; i += 2)
{
snesc_oam_table2[i] = 0;
}
}