]> Shamusworld >> Repos - virtualjaguar/blob - src/jerry.cpp
Fixes to remove old (and unused) clock code
[virtualjaguar] / src / jerry.cpp
1 //
2 // JERRY Core
3 //
4 // Originally by David Raingeard
5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Carwin Jones (BeOS)
6 // Cleanups/rewrites/fixes by James L. Hammons
7 //
8 //      ------------------------------------------------------------
9 //      JERRY REGISTERS (Mapped by Aaron Giles)
10 //      ------------------------------------------------------------
11 //      F10000-F13FFF   R/W   xxxxxxxx xxxxxxxx   Jerry
12 //      F10000            W   xxxxxxxx xxxxxxxx   JPIT1 - timer 1 pre-scaler
13 //      F10002            W   xxxxxxxx xxxxxxxx   JPIT2 - timer 1 divider
14 //      F10004            W   xxxxxxxx xxxxxxxx   JPIT3 - timer 2 pre-scaler
15 //      F10008            W   xxxxxxxx xxxxxxxx   JPIT4 - timer 2 divider
16 //      F10010            W   ------xx xxxxxxxx   CLK1 - processor clock divider
17 //      F10012            W   ------xx xxxxxxxx   CLK2 - video clock divider
18 //      F10014            W   -------- --xxxxxx   CLK3 - chroma clock divider
19 //      F10020          R/W   ---xxxxx ---xxxxx   JINTCTRL - interrupt control register
20 //                        W   ---x---- --------      (J_SYNCLR - clear synchronous serial intf ints)
21 //                        W   ----x--- --------      (J_ASYNCLR - clear asynchronous serial intf ints)
22 //                        W   -----x-- --------      (J_TIM2CLR - clear timer 2 [tempo] interrupts)
23 //                        W   ------x- --------      (J_TIM1CLR - clear timer 1 [sample] interrupts)
24 //                        W   -------x --------      (J_EXTCLR - clear external interrupts)
25 //                      R/W   -------- ---x----      (J_SYNENA - enable synchronous serial intf ints)
26 //                      R/W   -------- ----x---      (J_ASYNENA - enable asynchronous serial intf ints)
27 //                      R/W   -------- -----x--      (J_TIM2ENA - enable timer 2 [tempo] interrupts)
28 //                      R/W   -------- ------x-      (J_TIM1ENA - enable timer 1 [sample] interrupts)
29 //                      R/W   -------- -------x      (J_EXTENA - enable external interrupts)
30 //      F10030          R/W   -------- xxxxxxxx   ASIDATA - asynchronous serial data
31 //      F10032            W   -x------ -xxxxxxx   ASICTRL - asynchronous serial control
32 //                        W   -x------ --------      (TXBRK - transmit break)
33 //                        W   -------- -x------      (CLRERR - clear error)
34 //                        W   -------- --x-----      (RINTEN - enable receiver interrupts)
35 //                        W   -------- ---x----      (TINTEN - enable transmitter interrupts)
36 //                        W   -------- ----x---      (RXIPOL - receiver input polarity)
37 //                        W   -------- -----x--      (TXOPOL - transmitter output polarity)
38 //                        W   -------- ------x-      (PAREN - parity enable)
39 //                        W   -------- -------x      (ODD - odd parity select)
40 //      F10032          R     xxx-xxxx x-xxxxxx   ASISTAT - asynchronous serial status
41 //                      R     x------- --------      (ERROR - OR of PE,FE,OE)
42 //                      R     -x------ --------      (TXBRK - transmit break)
43 //                      R     --x----- --------      (SERIN - serial input)
44 //                      R     ----x--- --------      (OE - overrun error)
45 //                      R     -----x-- --------      (FE - framing error)
46 //                      R     ------x- --------      (PE - parity error)
47 //                      R     -------x --------      (TBE - transmit buffer empty)
48 //                      R     -------- x-------      (RBF - receive buffer full)
49 //                      R     -------- ---x----      (TINTEN - enable transmitter interrupts)
50 //                      R     -------- ----x---      (RXIPOL - receiver input polarity)
51 //                      R     -------- -----x--      (TXOPOL - transmitter output polarity)
52 //                      R     -------- ------x-      (PAREN - parity enable)
53 //                      R     -------- -------x      (ODD - odd parity)
54 //      F10034          R/W   xxxxxxxx xxxxxxxx   ASICLK - asynchronous serial interface clock
55 //      F10036          R     xxxxxxxx xxxxxxxx   JPIT1 - timer 1 pre-scaler
56 //      F10038          R     xxxxxxxx xxxxxxxx   JPIT2 - timer 1 divider
57 //      F1003A          R     xxxxxxxx xxxxxxxx   JPIT3 - timer 2 pre-scaler
58 //      F1003C          R     xxxxxxxx xxxxxxxx   JPIT4 - timer 2 divider
59 //      ------------------------------------------------------------
60 //      F14000-F17FFF   R/W   xxxxxxxx xxxxxxxx   Joysticks and GPIO0-5
61 //      F14000          R     xxxxxxxx xxxxxxxx   JOYSTICK - read joystick state
62 //      F14000            W   x------- xxxxxxxx   JOYSTICK - latch joystick output
63 //                        W   x------- --------      (enable joystick outputs)
64 //                        W   -------- xxxxxxxx      (joystick output data)
65 //      F14002          R     xxxxxxxx xxxxxxxx   JOYBUTS - button register
66 //      F14800-F14FFF   R/W   xxxxxxxx xxxxxxxx   GPI00 - reserved (CD-ROM?)
67 //      F15000-F15FFF   R/W   xxxxxxxx xxxxxxxx   GPI01 - reserved
68 //      F16000-F16FFF   R/W   xxxxxxxx xxxxxxxx   GPI02 - reserved
69 //      F17000-F177FF   R/W   xxxxxxxx xxxxxxxx   GPI03 - reserved
70 //      F17800-F17BFF   R/W   xxxxxxxx xxxxxxxx   GPI04 - reserved
71 //      F17C00-F17FFF   R/W   xxxxxxxx xxxxxxxx   GPI05 - reserved
72 //      ------------------------------------------------------------
73 //      F18000-F1FFFF   R/W   xxxxxxxx xxxxxxxx   Jerry DSP
74 //      F1A100          R/W   xxxxxxxx xxxxxxxx   D_FLAGS - DSP flags register
75 //                      R/W   x------- --------      (DMAEN - DMA enable)
76 //                      R/W   -x------ --------      (REGPAGE - register page)
77 //                        W   --x----- --------      (D_EXT0CLR - clear external interrupt 0)
78 //                        W   ---x---- --------      (D_TIM2CLR - clear timer 2 interrupt)
79 //                        W   ----x--- --------      (D_TIM1CLR - clear timer 1 interrupt)
80 //                        W   -----x-- --------      (D_I2SCLR - clear I2S interrupt)
81 //                        W   ------x- --------      (D_CPUCLR - clear CPU interrupt)
82 //                      R/W   -------x --------      (D_EXT0ENA - enable external interrupt 0)
83 //                      R/W   -------- x-------      (D_TIM2ENA - enable timer 2 interrupt)
84 //                      R/W   -------- -x------      (D_TIM1ENA - enable timer 1 interrupt)
85 //                      R/W   -------- --x-----      (D_I2SENA - enable I2S interrupt)
86 //                      R/W   -------- ---x----      (D_CPUENA - enable CPU interrupt)
87 //                      R/W   -------- ----x---      (IMASK - interrupt mask)
88 //                      R/W   -------- -----x--      (NEGA_FLAG - ALU negative)
89 //                      R/W   -------- ------x-      (CARRY_FLAG - ALU carry)
90 //                      R/W   -------- -------x      (ZERO_FLAG - ALU zero)
91 //      F1A102          R/W   -------- ------xx   D_FLAGS - upper DSP flags
92 //                      R/W   -------- ------x-      (D_EXT1ENA - enable external interrupt 1)
93 //                      R/W   -------- -------x      (D_EXT1CLR - clear external interrupt 1)
94 //      F1A104            W   -------- ----xxxx   D_MTXC - matrix control register
95 //                        W   -------- ----x---      (MATCOL - column/row major)
96 //                        W   -------- -----xxx      (MATRIX3-15 - matrix width)
97 //      F1A108            W   ----xxxx xxxxxx--   D_MTXA - matrix address register
98 //      F1A10C            W   -------- -----x-x   D_END - data organization register
99 //                        W   -------- -----x--      (BIG_INST - big endian instruction fetch)
100 //                        W   -------- -------x      (BIG_IO - big endian I/O)
101 //      F1A110          R/W   xxxxxxxx xxxxxxxx   D_PC - DSP program counter
102 //      F1A114          R/W   xxxxxxxx xx-xxxxx   D_CTRL - DSP control/status register
103 //                      R     xxxx---- --------      (VERSION - DSP version code)
104 //                      R/W   ----x--- --------      (BUS_HOG - hog the bus!)
105 //                      R/W   -----x-- --------      (D_EXT0LAT - external interrupt 0 latch)
106 //                      R/W   ------x- --------      (D_TIM2LAT - timer 2 interrupt latch)
107 //                      R/W   -------x --------      (D_TIM1LAT - timer 1 interrupt latch)
108 //                      R/W   -------- x-------      (D_I2SLAT - I2S interrupt latch)
109 //                      R/W   -------- -x------      (D_CPULAT - CPU interrupt latch)
110 //                      R/W   -------- ---x----      (SINGLE_GO - single step one instruction)
111 //                      R/W   -------- ----x---      (SINGLE_STEP - single step mode)
112 //                      R/W   -------- -----x--      (FORCEINT0 - cause interrupt 0 on GPU)
113 //                      R/W   -------- ------x-      (CPUINT - send GPU interrupt to CPU)
114 //                      R/W   -------- -------x      (DSPGO - enable DSP execution)
115 //      F1A116          R/W   -------- -------x   D_CTRL - upper DSP control/status register
116 //                      R/W   -------- -------x      (D_EXT1LAT - external interrupt 1 latch)
117 //      F1A118-F1A11B     W   xxxxxxxx xxxxxxxx   D_MOD - modulo instruction mask
118 //      F1A11C-F1A11F   R     xxxxxxxx xxxxxxxx   D_REMAIN - divide unit remainder
119 //      F1A11C            W   -------- -------x   D_DIVCTRL - divide unit control
120 //                        W   -------- -------x      (DIV_OFFSET - 1=16.16 divide, 0=32-bit divide)
121 //      F1A120-F1A123   R     xxxxxxxx xxxxxxxx   D_MACHI - multiply & accumulate high bits
122 //      F1A148            W   xxxxxxxx xxxxxxxx   R_DAC - right transmit data
123 //      F1A14C            W   xxxxxxxx xxxxxxxx   L_DAC - left transmit data
124 //      F1A150            W   -------- xxxxxxxx   SCLK - serial clock frequency
125 //      F1A150          R     -------- ------xx   SSTAT
126 //                      R     -------- ------x-      (left - no description)
127 //                      R     -------- -------x      (WS - word strobe status)
128 //      F1A154            W   -------- --xxxx-x   SMODE - serial mode
129 //                        W   -------- --x-----      (EVERYWORD - interrupt on MSB of every word)
130 //                        W   -------- ---x----      (FALLING - interrupt on falling edge)
131 //                        W   -------- ----x---      (RISING - interrupt of rising edge)
132 //                        W   -------- -----x--      (WSEN - enable word strobes)
133 //                        W   -------- -------x      (INTERNAL - enables serial clock)
134 //      ------------------------------------------------------------
135 //      F1B000-F1CFFF   R/W   xxxxxxxx xxxxxxxx   Local DSP RAM
136 //      ------------------------------------------------------------
137 //      F1D000          R     xxxxxxxx xxxxxxxx   ROM_TRI - triangle wave
138 //      F1D200          R     xxxxxxxx xxxxxxxx   ROM_SINE - full sine wave
139 //      F1D400          R     xxxxxxxx xxxxxxxx   ROM_AMSINE - amplitude modulated sine wave
140 //      F1D600          R     xxxxxxxx xxxxxxxx   ROM_12W - sine wave and second order harmonic
141 //      F1D800          R     xxxxxxxx xxxxxxxx   ROM_CHIRP16 - chirp
142 //      F1DA00          R     xxxxxxxx xxxxxxxx   ROM_NTRI - traingle wave with noise
143 //      F1DC00          R     xxxxxxxx xxxxxxxx   ROM_DELTA - spike
144 //      F1DE00          R     xxxxxxxx xxxxxxxx   ROM_NOISE - white noise
145 //      ------------------------------------------------------------
146
147 //#include <math.h>
148 #include "wavetable.h"
149 #include "jerry.h"
150
151 //#define JERRY_DEBUG
152
153 /*static*/ uint8 * jerry_ram_8;
154
155 //#define JERRY_CONFIG  0x4002                                          // ??? What's this ???
156
157 uint8 analog_x, analog_y;
158
159 static uint32 jerry_timer_1_prescaler;
160 static uint32 jerry_timer_2_prescaler;
161 static uint32 jerry_timer_1_divider;
162 static uint32 jerry_timer_2_divider;
163 static int32 jerry_timer_1_counter;
164 static int32 jerry_timer_2_counter;
165
166 static uint32 jerry_i2s_interrupt_divide = 8;
167 static int32 jerry_i2s_interrupt_timer = -1;
168 uint32 jerryI2SCycles;
169 uint32 jerryIntPending;
170
171 //This approach is probably wrong, since the timer is continuously counting down, though
172 //it might only be a problem if the # of interrupts generated is greater than 1--the M68K's
173 //timeslice should be running during that phase... (The DSP needs to be aware of this!)
174 void jerry_i2s_exec(uint32 cycles)
175 {
176         extern uint16 serialMode;                                               // From DAC.CPP
177         if (serialMode & 0x01)                                                  // INTERNAL flag (JERRY is master)
178         {
179
180         // Why is it called this? Instead of SCLK? Shouldn't this be read from DAC.CPP???
181 //Yes, it should. !!! FIX !!!
182                 jerry_i2s_interrupt_divide &= 0xFF;
183
184                 if (jerry_i2s_interrupt_timer == -1)
185                 {
186                 // We don't have to divide the RISC clock rate by this--the reason is a bit
187                 // convoluted. Will put explanation here later...
188 // What's needed here is to find the ratio of the frequency to the number of clock cycles
189 // in one second. For example, if the sample rate is 44100, we divide the clock rate by
190 // this: 26590906 / 44100 = 602 cycles.
191 // Which means, every 602 cycles that go by we have to generate an interrupt.
192                         jerryI2SCycles = 32 * (2 * (jerry_i2s_interrupt_divide + 1));
193                 }
194
195                 jerry_i2s_interrupt_timer -= cycles;
196                 if (jerry_i2s_interrupt_timer <= 0)
197                 {
198 //This is probably wrong as well (i.e., need to check enable lines)... !!! FIX !!!
199                         DSPSetIRQLine(DSPIRQ_SSI, ASSERT_LINE);
200                         jerry_i2s_interrupt_timer += jerryI2SCycles;
201 #ifdef JERRY_DEBUG
202                         if (jerry_i2s_interrupt_timer < 0)
203                                 WriteLog("JERRY: Missed generating an interrupt (missed %u)!\n", (-jerry_i2s_interrupt_timer / jerryI2SCycles) + 1);
204 #endif
205                 }
206         }
207         else                                                                                    // JERRY is slave to external word clock
208         {
209                 // This is just a temporary kludge to see if the CD bus mastering works
210                 // I.e., this is totally faked...!
211 // The whole interrupt system is pretty much borked and is need of an overhaul.
212 // What we need is a way of handling these interrupts when they happen instead of
213 // scanline boundaries the way it is now.
214                 jerry_i2s_interrupt_timer -= cycles;
215                 if (jerry_i2s_interrupt_timer <= 0)
216                 {
217 //This is probably wrong as well (i.e., need to check enable lines)... !!! FIX !!! [DONE]
218                         if (ButchIsReadyToSend())//Not sure this is right spot to check...
219                         {
220 //      return GetWordFromButchSSI(offset, who);
221                                 SetSSIWordsXmittedFromButch();
222                                 DSPSetIRQLine(DSPIRQ_SSI, ASSERT_LINE);
223                         }
224                         jerry_i2s_interrupt_timer += 602;
225                 }
226         }
227 }
228
229 void jerry_reset_i2s_timer(void)
230 {
231         //WriteLog("i2s: reseting\n");
232 //This is really SCLK... !!! FIX !!!
233         jerry_i2s_interrupt_divide = 8;
234         jerry_i2s_interrupt_timer = -1;
235 }
236
237 void jerry_reset_timer_1(void)
238 {
239 /*      if (!jerry_timer_1_prescaler || !jerry_timer_1_divider)
240                 jerry_timer_1_counter = 0;
241         else//*/
242 //Small problem with this approach: Overflow if both are = $FFFF. !!! FIX !!!
243                 jerry_timer_1_counter = (jerry_timer_1_prescaler + 1) * (jerry_timer_1_divider + 1);
244
245 //      if (jerry_timer_1_counter)
246 //              WriteLog("jerry: reseting timer 1 to 0x%.8x (%i)\n",jerry_timer_1_counter,jerry_timer_1_counter);
247 }
248
249 void jerry_reset_timer_2(void)
250 {
251 /*      if (!jerry_timer_2_prescaler || !jerry_timer_2_divider)
252         {
253                 jerry_timer_2_counter = 0;
254                 return;
255         }
256         else//*/
257                 jerry_timer_2_counter = (jerry_timer_2_prescaler + 1) * (jerry_timer_2_divider + 1);
258
259 //      if (jerry_timer_2_counter)
260 //              WriteLog("jerry: reseting timer 2 to 0x%.8x (%i)\n",jerry_timer_2_counter,jerry_timer_2_counter);
261 }
262
263 void JERRYExecPIT(uint32 cycles)
264 {
265 //This is wrong too: Counters are *always* spinning! !!! FIX !!! [DONE]
266 //      if (jerry_timer_1_counter)
267                 jerry_timer_1_counter -= cycles;
268
269         if (jerry_timer_1_counter <= 0)
270         {
271 //Also, it can generate a CPU interrupt as well... !!! FIX !!! or does it? Maybe it goes Timer->GPU->CPU?
272                 DSPSetIRQLine(DSPIRQ_TIMER0, ASSERT_LINE);      // This does the 'IRQ enabled' checking...
273 //              jerry_reset_timer_1();
274                 jerry_timer_1_counter += (jerry_timer_1_prescaler + 1) * (jerry_timer_1_divider + 1);
275         }
276
277 //This is wrong too: Counters are *always* spinning! !!! FIX !!! [DONE]
278 //      if (jerry_timer_2_counter)
279                 jerry_timer_2_counter -= cycles;
280
281         if (jerry_timer_2_counter <= 0)
282         {
283 //Also, it can generate a CPU interrupt as well... !!! FIX !!! or does it? Maybe it goes Timer->GPU->CPU?
284                 DSPSetIRQLine(DSPIRQ_TIMER1, ASSERT_LINE);      // This does the 'IRQ enabled' checking...
285 //              jerry_reset_timer_2();
286                 jerry_timer_2_counter += (jerry_timer_2_prescaler + 1) * (jerry_timer_2_divider + 1);
287         }
288 }
289
290 void jerry_init(void)
291 {
292 //      clock_init();
293         anajoy_init();
294         joystick_init();
295         DACInit();
296 //This should be handled with the cart initialization...
297 //      eeprom_init();
298         memory_malloc_secure((void **)&jerry_ram_8, 0x10000, "JERRY RAM/ROM");
299         memcpy(&jerry_ram_8[0xD000], wave_table, 0x1000);
300 }
301
302 void jerry_reset(void)
303 {
304 //      clock_reset();
305         anajoy_reset();
306         joystick_reset();
307         eeprom_reset();
308         jerry_reset_i2s_timer();
309         DACReset();
310
311         memset(jerry_ram_8, 0x00, 0xD000);              // Don't clear out the Wavetable ROM...!
312         jerry_timer_1_prescaler = 0xFFFF;
313         jerry_timer_2_prescaler = 0xFFFF;
314         jerry_timer_1_divider = 0xFFFF;
315         jerry_timer_2_divider = 0xFFFF;
316         jerry_timer_1_counter = 0;
317         jerry_timer_2_counter = 0;
318 }
319
320 void jerry_done(void)
321 {
322         WriteLog("JERRY: M68K Interrupt control ($F10020) = %04X\n", GET16(jerry_ram_8, 0x20));
323         memory_free(jerry_ram_8);
324 //      clock_done();
325         anajoy_done();
326         joystick_done();
327         DACDone();
328         eeprom_done();
329 }
330
331 bool JERRYIRQEnabled(int irq)
332 {
333         // Read the word @ $F10020 
334         return jerry_ram_8[0x21] & (1 << irq);
335 }
336
337 void JERRYSetPendingIRQ(int irq)
338 {
339         // This is the shadow of INT (it's a split RO/WO register)
340         jerryIntPending |= (1 << irq);
341 }
342
343 //
344 // JERRY byte access (read)
345 //
346 uint8 JERRYReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
347 {
348 #ifdef JERRY_DEBUG
349         WriteLog("JERRY: Reading byte at %06X\n", offset);
350 #endif
351         if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
352                 return DSPReadByte(offset, who);
353         else if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
354                 return DSPReadByte(offset, who);
355         // LRXD/RRXD/SSTAT $F1A148/4C/50 (really 16-bit registers...)
356         else if (offset >= 0xF1A148 && offset <= 0xF1A153)
357                 return DACReadByte(offset, who);
358 //      F10036          R     xxxxxxxx xxxxxxxx   JPIT1 - timer 1 pre-scaler
359 //      F10038          R     xxxxxxxx xxxxxxxx   JPIT2 - timer 1 divider
360 //      F1003A          R     xxxxxxxx xxxxxxxx   JPIT3 - timer 2 pre-scaler
361 //      F1003C          R     xxxxxxxx xxxxxxxx   JPIT4 - timer 2 divider
362 //This is WRONG!
363 //      else if (offset >= 0xF10000 && offset <= 0xF10007)
364 //This is still wrong. What needs to be returned here are the values being counted down
365 //in the jerry_timer_n_counter variables... !!! FIX !!! [DONE]
366         else if ((offset >= 0xF10036) && (offset <= 0xF1003D))
367         {
368 //              jerry_timer_1_counter = (jerry_timer_1_prescaler + 1) * (jerry_timer_1_divider + 1);
369                 uint32 counter1Hi = (jerry_timer_1_counter / (jerry_timer_1_divider + 1)) - 1;
370                 uint32 counter1Lo = (jerry_timer_1_counter % (jerry_timer_1_divider + 1)) - 1;
371                 uint32 counter2Hi = (jerry_timer_2_counter / (jerry_timer_2_divider + 1)) - 1;
372                 uint32 counter2Lo = (jerry_timer_2_counter % (jerry_timer_2_divider + 1)) - 1;
373
374                 switch(offset & 0x0F)
375                 {
376                 case 6:
377 //                      return jerry_timer_1_prescaler >> 8;
378                         return counter1Hi >> 8;
379                 case 7:
380 //                      return jerry_timer_1_prescaler & 0xFF;
381                         return counter1Hi & 0xFF;
382                 case 8:
383 //                      return jerry_timer_1_divider >> 8;
384                         return counter1Lo >> 8;
385                 case 9:
386 //                      return jerry_timer_1_divider & 0xFF;
387                         return counter1Lo & 0xFF;
388                 case 10:
389 //                      return jerry_timer_2_prescaler >> 8;
390                         return counter2Hi >> 8;
391                 case 11:
392 //                      return jerry_timer_2_prescaler & 0xFF;
393                         return counter2Hi & 0xFF;
394                 case 12:
395 //                      return jerry_timer_2_divider >> 8;
396                         return counter2Lo >> 8;
397                 case 13:
398 //                      return jerry_timer_2_divider & 0xFF;
399                         return counter2Lo & 0xFF;
400                 }
401         }
402 //      else if (offset >= 0xF10010 && offset <= 0xF10015)
403 //              return clock_byte_read(offset);
404         else if (offset >= 0xF17C00 && offset <= 0xF17C01)
405                 return anajoy_byte_read(offset);
406         else if (offset >= 0xF14000 && offset <= 0xF14003)
407                 return joystick_byte_read(offset) | eeprom_byte_read(offset);
408         else if (offset >= 0xF14000 && offset <= 0xF1A0FF)
409                 return eeprom_byte_read(offset);
410         
411         return jerry_ram_8[offset & 0xFFFF];
412 }
413
414 //
415 // JERRY word access (read)
416 //
417 uint16 JERRYReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
418 {
419 #ifdef JERRY_DEBUG
420         WriteLog("JERRY: Reading word at %06X\n", offset);
421 #endif
422
423         if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
424                 return DSPReadWord(offset, who);
425         else if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
426                 return DSPReadWord(offset, who);
427         // LRXD/RRXD/SSTAT $F1A148/4C/50 (really 16-bit registers...)
428         else if (offset >= 0xF1A148 && offset <= 0xF1A153)
429                 return DACReadWord(offset, who);
430 //      F10036          R     xxxxxxxx xxxxxxxx   JPIT1 - timer 1 pre-scaler
431 //      F10038          R     xxxxxxxx xxxxxxxx   JPIT2 - timer 1 divider
432 //      F1003A          R     xxxxxxxx xxxxxxxx   JPIT3 - timer 2 pre-scaler
433 //      F1003C          R     xxxxxxxx xxxxxxxx   JPIT4 - timer 2 divider
434 //This is WRONG!
435 //      else if ((offset >= 0xF10000) && (offset <= 0xF10007))
436 //This is still wrong. What needs to be returned here are the values being counted down
437 //in the jerry_timer_n_counter variables... !!! FIX !!! [DONE]
438         else if ((offset >= 0xF10036) && (offset <= 0xF1003D))
439         {
440 //              jerry_timer_1_counter = (jerry_timer_1_prescaler + 1) * (jerry_timer_1_divider + 1);
441                 uint32 counter1Hi = (jerry_timer_1_counter / (jerry_timer_1_divider + 1)) - 1;
442                 uint32 counter1Lo = (jerry_timer_1_counter % (jerry_timer_1_divider + 1)) - 1;
443                 uint32 counter2Hi = (jerry_timer_2_counter / (jerry_timer_2_divider + 1)) - 1;
444                 uint32 counter2Lo = (jerry_timer_2_counter % (jerry_timer_2_divider + 1)) - 1;
445
446                 switch(offset & 0x0F)
447                 {
448                 case 6:
449 //                      return jerry_timer_1_prescaler;
450                         return counter1Hi;
451                 case 8:
452 //                      return jerry_timer_1_divider;
453                         return counter1Lo;
454                 case 10:
455 //                      return jerry_timer_2_prescaler;
456                         return counter2Hi;
457                 case 12:
458 //                      return jerry_timer_2_divider;
459                         return counter2Lo;
460                 }
461                 // Unaligned word reads???
462         }
463 //      else if ((offset >= 0xF10010) && (offset <= 0xF10015))
464 //              return clock_word_read(offset);
465         else if (offset == 0xF10020)
466                 return jerryIntPending;
467         else if ((offset >= 0xF17C00) && (offset <= 0xF17C01))
468                 return anajoy_word_read(offset);
469         else if (offset == 0xF14000)
470                 return (joystick_word_read(offset) & 0xFFFE) | eeprom_word_read(offset);
471         else if ((offset >= 0xF14002) && (offset < 0xF14003))
472                 return joystick_word_read(offset);
473         else if ((offset >= 0xF14000) && (offset <= 0xF1A0FF))
474                 return eeprom_word_read(offset);
475
476 /*if (offset >= 0xF1D000)
477         WriteLog("JERRY: Reading word at %08X [%04X]...\n", offset, ((uint16)jerry_ram_8[(offset+0)&0xFFFF] << 8) | jerry_ram_8[(offset+1)&0xFFFF]);//*/
478
479         offset &= 0xFFFF;                               // Prevent crashing...!
480         return ((uint16)jerry_ram_8[offset+0] << 8) | jerry_ram_8[offset+1];
481 }
482
483 //
484 // JERRY byte access (write)
485 //
486 void JERRYWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
487 {
488 #ifdef JERRY_DEBUG
489         WriteLog("jerry: writing byte %.2x at 0x%.6x\n",data,offset);
490 #endif
491         if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
492         {
493                 DSPWriteByte(offset, data, who);
494                 return;
495         }
496         else if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
497         {
498                 DSPWriteByte(offset, data, who);
499                 return;
500         }
501         // SCLK ($F1A150--8 bits wide)
502         else if ((offset >= 0xF1A152) && (offset <= 0xF1A153))
503         {
504 //              WriteLog("JERRY: Writing %02X to SCLK...\n", data);
505                 if ((offset & 0x03) == 2)
506                         jerry_i2s_interrupt_divide = (jerry_i2s_interrupt_divide & 0x00FF) | ((uint32)data << 8);
507                 else
508                         jerry_i2s_interrupt_divide = (jerry_i2s_interrupt_divide & 0xFF00) | (uint32)data;
509
510                 jerry_i2s_interrupt_timer = -1;
511                 jerry_i2s_exec(0);
512 //              return;
513         }
514         // LTXD/RTXD/SCLK/SMODE $F1A148/4C/50/54 (really 16-bit registers...)
515         else if (offset >= 0xF1A148 && offset <= 0xF1A157)
516         { 
517                 DACWriteByte(offset, data, who);
518                 return; 
519         }
520         else if (offset >= 0xF10000 && offset <= 0xF10007)
521         {
522                 switch (offset & 0x07)
523                 {
524                 case 0:
525                         jerry_timer_1_prescaler = (jerry_timer_1_prescaler & 0x00FF) | (data << 8);
526                         jerry_reset_timer_1();
527                         break;
528                 case 1:
529                         jerry_timer_1_prescaler = (jerry_timer_1_prescaler & 0xFF00) | data;
530                         jerry_reset_timer_1();
531                         break;
532                 case 2:
533                         jerry_timer_1_divider = (jerry_timer_1_divider & 0x00FF) | (data << 8);
534                         jerry_reset_timer_1();
535                         break;
536                 case 3:
537                         jerry_timer_1_divider = (jerry_timer_1_divider & 0xFF00) | data;
538                         jerry_reset_timer_1();
539                         break;
540                 case 4:
541                         jerry_timer_2_prescaler = (jerry_timer_2_prescaler & 0x00FF) | (data << 8);
542                         jerry_reset_timer_2();
543                         break;
544                 case 5:
545                         jerry_timer_2_prescaler = (jerry_timer_2_prescaler & 0xFF00) | data;
546                         jerry_reset_timer_2();
547                         break;
548                 case 6:
549                         jerry_timer_2_divider = (jerry_timer_2_divider & 0x00FF) | (data << 8);
550                         jerry_reset_timer_2();
551                         break;
552                 case 7:
553                         jerry_timer_2_divider = (jerry_timer_2_divider & 0xFF00) | data;
554                         jerry_reset_timer_2();
555                 }
556                 return;
557         }
558 /*      else if ((offset >= 0xF10010) && (offset <= 0xF10015))
559         {
560                 clock_byte_write(offset, data);
561                 return;
562         }//*/
563         // JERRY -> 68K interrupt enables/latches (need to be handled!)
564         else if (offset >= 0xF10020 && offset <= 0xF10023)
565         {
566 WriteLog("JERRY: (68K int en/lat - Unhandled!) Tried to write $%02X to $%08X!\n", data, offset);
567         }
568         else if ((offset >= 0xF17C00) && (offset <= 0xF17C01))
569         {
570                 anajoy_byte_write(offset, data);
571                 return;
572         }
573         else if ((offset >= 0xF14000) && (offset <= 0xF14003))
574         {
575                 joystick_byte_write(offset, data);
576                 eeprom_byte_write(offset, data);
577                 return;
578         }
579         else if ((offset >= 0xF14000) && (offset <= 0xF1A0FF))
580         {
581                 eeprom_byte_write(offset, data);
582                 return;
583         }
584
585 //Need to protect write attempts to Wavetable ROM (F1D000-FFF)
586         if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
587                 return;
588
589         jerry_ram_8[offset & 0xFFFF] = data;
590 }
591
592 //
593 // JERRY word access (write)
594 //
595 void JERRYWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
596 {
597 #ifdef JERRY_DEBUG
598         WriteLog( "JERRY: Writing word %04X at %06X\n", data, offset);
599 #endif
600
601         if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
602         {
603                 DSPWriteWord(offset, data, who);
604                 return;
605         }
606         else if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
607         {
608                 DSPWriteWord(offset, data, who);
609                 return;
610         }
611         else if (offset == 0xF1A152)                                    // Bottom half of SCLK ($F1A150)
612         {
613                 WriteLog("JERRY: Writing %04X to SCLK (by %s)...\n", data, whoName[who]);
614 //This should *only* be enabled when SMODE has its INTERNAL bit set! !!! FIX !!!
615                 jerry_i2s_interrupt_divide = (uint8)data;
616                 jerry_i2s_interrupt_timer = -1;
617                 jerry_i2s_exec(0);
618
619                 DACWriteWord(offset, data, who);
620                 return; 
621         }
622         // LTXD/RTXD/SCLK/SMODE $F1A148/4C/50/54 (really 16-bit registers...)
623         else if (offset >= 0xF1A148 && offset <= 0xF1A156)
624         { 
625                 DACWriteWord(offset, data, who);
626                 return; 
627         }
628         else if (offset >= 0xF10000 && offset <= 0xF10007)
629         {
630                 switch(offset & 0x07)
631                 {
632                 case 0:
633                         jerry_timer_1_prescaler = data;
634                         jerry_reset_timer_1();
635                         break;
636                 case 2:
637                         jerry_timer_1_divider = data;
638                         jerry_reset_timer_1();
639                         break;
640                 case 4:
641                         jerry_timer_2_prescaler = data;
642                         jerry_reset_timer_2();
643                         break;
644                 case 6:
645                         jerry_timer_2_divider = data;
646                         jerry_reset_timer_2();
647                 }
648                 // Need to handle (unaligned) cases???
649                 return;
650         }
651 /*      else if (offset >= 0xF10010 && offset < 0xF10016)
652         {
653                 clock_word_write(offset, data);
654                 return;
655         }//*/
656         // JERRY -> 68K interrupt enables/latches (need to be handled!)
657         else if (offset >= 0xF10020 && offset <= 0xF10022)
658         {
659 WriteLog("JERRY: (68K int en/lat - Unhandled!) Tried to write $%04X to $%08X!\n", data, offset);
660         }
661         else if (offset >= 0xF17C00 && offset < 0xF17C02)
662         {
663 //I think this was removed from the Jaguar. If so, then we don't need this...!
664                 anajoy_word_write(offset, data);
665                 return;
666         }
667         else if (offset >= 0xF14000 && offset < 0xF14003)
668         {
669                 joystick_word_write(offset, data);
670                 eeprom_word_write(offset, data);
671                 return;
672         }
673         else if (offset >= 0xF14000 && offset <= 0xF1A0FF)
674         {
675                 eeprom_word_write(offset, data);
676                 return;
677         }
678
679 //Need to protect write attempts to Wavetable ROM (F1D000-FFF)
680         if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
681                 return;
682
683         jerry_ram_8[(offset+0) & 0xFFFF] = (data >> 8) & 0xFF;
684         jerry_ram_8[(offset+1) & 0xFFFF] = data & 0xFF;
685 }