1 // license:GPL-2.0+
2 // copyright-holders:Fabio Priuli, byuu, Nach
3 /***************************************************************************
4
5 snescx4.c
6
7 File to handle emulation of the SNES "CX4" add-on chip.
8
9 Code based on original work by zsKnight, anomie and Nach.
10 This implementation is based on C++ "cx4*.cpp" by byuu
11 (up to date with source v 0.49).
12
13 ***************************************************************************/
14
15 #include "emu.h"
16 #include "machine/snescx4.h"
17
18 static CX4 cx4;
19
20 static uint16_t CX4_readw(uint16_t addr);
21 static uint32_t CX4_readl(uint16_t addr);
22
23 static void CX4_writew(running_machine &machine, uint16_t addr, uint16_t data);
24 //static void CX4_writel(running_machine &machine, uint16_t addr, uint32_t data);
25
26 static void CX4_C4DrawLine(int32_t X1, int32_t Y1, int16_t Z1, int32_t X2, int32_t Y2, int16_t Z2, uint8_t Color);
27
28 #include "machine/cx4data.hxx"
29 #include "machine/cx4fn.hxx"
30
CX4_ldr(uint8_t r)31 static uint32_t CX4_ldr(uint8_t r)
32 {
33 uint16_t addr = 0x0080 + (r * 3);
34 return (cx4.reg[addr + 0] << 0)
35 | (cx4.reg[addr + 1] << 8)
36 | (cx4.reg[addr + 2] << 16);
37 }
38
CX4_str(uint8_t r,uint32_t data)39 static void CX4_str(uint8_t r, uint32_t data)
40 {
41 uint16_t addr = 0x0080 + (r * 3);
42 cx4.reg[addr + 0] = (data >> 0);
43 cx4.reg[addr + 1] = (data >> 8);
44 cx4.reg[addr + 2] = (data >> 16);
45 }
46
CX4_mul(uint32_t x,uint32_t y,uint32_t * rl,uint32_t * rh)47 static void CX4_mul(uint32_t x, uint32_t y, uint32_t *rl, uint32_t *rh)
48 {
49 int64_t rx = x & 0xffffff;
50 int64_t ry = y & 0xffffff;
51 if(rx & 0x800000)rx |= ~0x7fffff;
52 if(ry & 0x800000)ry |= ~0x7fffff;
53
54 rx *= ry;
55
56 *rl = (rx) & 0xffffff;
57 *rh = (rx >> 24) & 0xffffff;
58 }
59
CX4_sin(uint32_t rx)60 static uint32_t CX4_sin(uint32_t rx)
61 {
62 cx4.r0 = rx & 0x1ff;
63 if(cx4.r0 & 0x100)
64 {
65 cx4.r0 ^= 0x1ff;
66 }
67 if(cx4.r0 & 0x080)
68 {
69 cx4.r0 ^= 0x0ff;
70 }
71 if(rx & 0x100)
72 {
73 return CX4_sin_table[cx4.r0 + 0x80];
74 }
75 else
76 {
77 return CX4_sin_table[cx4.r0];
78 }
79 }
80
CX4_cos(uint32_t rx)81 static uint32_t CX4_cos(uint32_t rx)
82 {
83 return CX4_sin(rx + 0x080);
84 }
85
CX4_immediate_reg(uint32_t start)86 static void CX4_immediate_reg(uint32_t start)
87 {
88 uint32_t i = 0;
89 cx4.r0 = CX4_ldr(0);
90 for(i = start; i < 48; i++)
91 {
92 if((cx4.r0 & 0x0fff) < 0x0c00)
93 {
94 cx4.ram[cx4.r0 & 0x0fff] = CX4_immediate_data[i];
95 }
96 cx4.r0++;
97 }
98 CX4_str(0, cx4.r0);
99 }
100
CX4_transfer_data(running_machine & machine)101 static void CX4_transfer_data(running_machine &machine)
102 {
103 uint32_t src;
104 uint16_t dest, count;
105 uint32_t i;
106
107 src = (cx4.reg[0x40]) | (cx4.reg[0x41] << 8) | (cx4.reg[0x42] << 16);
108 count = (cx4.reg[0x43]) | (cx4.reg[0x44] << 8);
109 dest = (cx4.reg[0x45]) | (cx4.reg[0x46] << 8);
110
111 address_space &space = machine.device<cpu_device>("maincpu")->space(AS_PROGRAM);
112 for(i=0;i<count;i++)
113 {
114 CX4_write(machine, dest++, space.read_byte(src++));
115 }
116 }
117
118 #include "machine/cx4oam.hxx"
119 #include "machine/cx4ops.hxx"
120
CX4_write(running_machine & machine,uint32_t addr,uint8_t data)121 void CX4_write(running_machine &machine, uint32_t addr, uint8_t data)
122 {
123 addr &= 0x1fff;
124
125 if(addr < 0x0c00)
126 {
127 //ram
128 cx4.ram[addr] = data;
129 return;
130 }
131
132 if(addr < 0x1f00)
133 {
134 //unmapped
135 return;
136 }
137
138 //command register
139 cx4.reg[addr & 0xff] = data;
140
141 if(addr == 0x1f47)
142 {
143 //memory transfer
144 CX4_transfer_data(machine);
145 return;
146 }
147
148 if(addr == 0x1f4f)
149 {
150 //c4 command
151 if(cx4.reg[0x4d] == 0x0e && !(data & 0xc3))
152 {
153 //c4 test command
154 cx4.reg[0x80] = data >> 2;
155 return;
156 }
157
158 switch(data)
159 {
160 case 0x00: CX4_op00(machine); break;
161 case 0x01: CX4_op01(machine); break;
162 case 0x05: CX4_op05(machine); break;
163 case 0x0d: CX4_op0d(machine); break;
164 case 0x10: CX4_op10(); break;
165 case 0x13: CX4_op13(); break;
166 case 0x15: CX4_op15(machine); break;
167 case 0x1f: CX4_op1f(machine); break;
168 case 0x22: CX4_op22(); break;
169 case 0x25: CX4_op25(); break;
170 case 0x2d: CX4_op2d(machine); break;
171 case 0x40: CX4_op40(); break;
172 case 0x54: CX4_op54(); break;
173 case 0x5c: CX4_op5c(); break;
174 case 0x5e: CX4_op5e(); break;
175 case 0x60: CX4_op60(); break;
176 case 0x62: CX4_op62(); break;
177 case 0x64: CX4_op64(); break;
178 case 0x66: CX4_op66(); break;
179 case 0x68: CX4_op68(); break;
180 case 0x6a: CX4_op6a(); break;
181 case 0x6c: CX4_op6c(); break;
182 case 0x6e: CX4_op6e(); break;
183 case 0x70: CX4_op70(); break;
184 case 0x72: CX4_op72(); break;
185 case 0x74: CX4_op74(); break;
186 case 0x76: CX4_op76(); break;
187 case 0x78: CX4_op78(); break;
188 case 0x7a: CX4_op7a(); break;
189 case 0x7c: CX4_op7c(); break;
190 case 0x89: CX4_op89(); break;
191 }
192 }
193 }
194
195 #ifdef UNUSED_FUNCTION
CX4_writeb(running_machine & machine,uint16_t addr,uint8_t data)196 void CX4_writeb(running_machine &machine, uint16_t addr, uint8_t data)
197 {
198 CX4_write(machine, addr, data);
199 }
200 #endif
201
CX4_writew(running_machine & machine,uint16_t addr,uint16_t data)202 static void CX4_writew(running_machine &machine, uint16_t addr, uint16_t data)
203 {
204 CX4_write(machine, addr + 0, data >> 0);
205 CX4_write(machine, addr + 1, data >> 8);
206 }
207
208 #ifdef UNUSED_FUNCTION
CX4_writel(running_machine & machine,uint16_t addr,uint32_t data)209 void CX4_writel(running_machine &machine, uint16_t addr, uint32_t data)
210 {
211 CX4_write(machine, addr + 0, data >> 0);
212 CX4_write(machine, addr + 1, data >> 8);
213 CX4_write(machine, addr + 2, data >> 16);
214 }
215 #endif
216
CX4_read(uint32_t addr)217 uint8_t CX4_read(uint32_t addr)
218 {
219 addr &= 0x1fff;
220
221 if(addr < 0x0c00)
222 {
223 return cx4.ram[addr];
224 }
225
226 if(addr >= 0x1f00)
227 {
228 return cx4.reg[addr & 0xff];
229 }
230
231 return 0xff;
232 }
233
234 #ifdef UNUSED_FUNCTION
CX4_readb(uint16_t addr)235 uint8_t CX4_readb(uint16_t addr)
236 {
237 return CX4_read(addr);
238 }
239 #endif
240
CX4_readw(uint16_t addr)241 static uint16_t CX4_readw(uint16_t addr)
242 {
243 return CX4_read(addr) | (CX4_read(addr + 1) << 8);
244 }
245
CX4_readl(uint16_t addr)246 static uint32_t CX4_readl(uint16_t addr)
247 {
248 return CX4_read(addr) | (CX4_read(addr + 1) << 8) | (CX4_read(addr + 2) << 16);
249 }
250
251 #ifdef UNUSED_FUNCTION
CX4_reset()252 void CX4_reset()
253 {
254 memset(cx4.ram, 0, 0x0c00);
255 memset(cx4.reg, 0, 0x0100);
256 }
257 #endif
258