]> Shamusworld >> Repos - virtualjaguar/blob - src/jerry.cpp
Fixed fullscreen<-->windowed mode swith in OpenGL mode, phase one of
[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 "jerry.h"
148
149 #include <string.h>                                                             // For memcpy
150 //#include <math.h>
151 #include "jaguar.h"
152 #include "wavetable.h"
153 #include "clock.h"
154 #include "dsp.h"
155 #include "dac.h"
156 #include "joystick.h"
157 #include "eeprom.h"
158 #include "log.h"
159 #include "cdrom.h"
160
161 //Note that 44100 Hz requires samples every 22.675737 usec.
162 #define NEW_TIMER_SYSTEM
163 //#define JERRY_DEBUG
164
165 /*static*/ uint8 jerry_ram_8[0x10000];
166
167 //#define JERRY_CONFIG  0x4002                                          // ??? What's this ???
168
169 uint8 analog_x, analog_y;
170
171 static uint32 JERRYPIT1Prescaler;
172 static uint32 JERRYPIT1Divider;
173 static uint32 JERRYPIT2Prescaler;
174 static uint32 JERRYPIT2Divider;
175 static int32 jerry_timer_1_counter;
176 static int32 jerry_timer_2_counter;
177
178 static uint32 jerry_i2s_interrupt_divide = 8;
179 static int32 jerry_i2s_interrupt_timer = -1;
180 uint32 jerryI2SCycles;
181 uint32 jerryIntPending;
182
183 // Private function prototypes
184
185 void JERRYResetPIT1(void);
186 void JERRYResetPIT2(void);
187 void JERRYResetI2S(void);
188
189 void JERRYPIT1Callback(void);
190 void JERRYPIT2Callback(void);
191 void JERRYI2SCallback(void);
192
193 //This approach is probably wrong, since the timer is continuously counting down, though
194 //it might only be a problem if the # of interrupts generated is greater than 1--the M68K's
195 //timeslice should be running during that phase... (The DSP needs to be aware of this!)
196
197 //This is only used by the old system, so once the new timer system is working this
198 //should be safe to nuke.
199 void jerry_i2s_exec(uint32 cycles)
200 {
201 #ifndef NEW_TIMER_SYSTEM
202         extern uint16 serialMode;                                               // From DAC.CPP
203         if (serialMode & 0x01)                                                  // INTERNAL flag (JERRY is master)
204         {
205
206         // Why is it called this? Instead of SCLK? Shouldn't this be read from DAC.CPP???
207 //Yes, it should. !!! FIX !!!
208                 jerry_i2s_interrupt_divide &= 0xFF;
209
210                 if (jerry_i2s_interrupt_timer == -1)
211                 {
212                 // We don't have to divide the RISC clock rate by this--the reason is a bit
213                 // convoluted. Will put explanation here later...
214 // What's needed here is to find the ratio of the frequency to the number of clock cycles
215 // in one second. For example, if the sample rate is 44100, we divide the clock rate by
216 // this: 26590906 / 44100 = 602 cycles.
217 // Which means, every 602 cycles that go by we have to generate an interrupt.
218                         jerryI2SCycles = 32 * (2 * (jerry_i2s_interrupt_divide + 1));
219                 }
220
221                 jerry_i2s_interrupt_timer -= cycles;
222                 if (jerry_i2s_interrupt_timer <= 0)
223                 {
224 //This is probably wrong as well (i.e., need to check enable lines)... !!! FIX !!!
225                         DSPSetIRQLine(DSPIRQ_SSI, ASSERT_LINE);
226                         jerry_i2s_interrupt_timer += jerryI2SCycles;
227 #ifdef JERRY_DEBUG
228                         if (jerry_i2s_interrupt_timer < 0)
229                                 WriteLog("JERRY: Missed generating an interrupt (missed %u)!\n", (-jerry_i2s_interrupt_timer / jerryI2SCycles) + 1);
230 #endif
231                 }
232         }
233         else                                                                                    // JERRY is slave to external word clock
234         {
235                 // This is just a temporary kludge to see if the CD bus mastering works
236                 // I.e., this is totally faked...!
237 // The whole interrupt system is pretty much borked and is need of an overhaul.
238 // What we need is a way of handling these interrupts when they happen instead of
239 // scanline boundaries the way it is now.
240                 jerry_i2s_interrupt_timer -= cycles;
241                 if (jerry_i2s_interrupt_timer <= 0)
242                 {
243 //This is probably wrong as well (i.e., need to check enable lines)... !!! FIX !!! [DONE]
244                         if (ButchIsReadyToSend())//Not sure this is right spot to check...
245                         {
246 //      return GetWordFromButchSSI(offset, who);
247                                 SetSSIWordsXmittedFromButch();
248                                 DSPSetIRQLine(DSPIRQ_SSI, ASSERT_LINE);
249                         }
250                         jerry_i2s_interrupt_timer += 602;
251                 }
252         }
253 #else
254         RemoveCallback(JERRYI2SCallback);
255         JERRYI2SCallback();
256 #endif
257 }
258
259 //NOTE: This is only used by the old execution core. Safe to nuke once it's stable.
260 void JERRYExecPIT(uint32 cycles)
261 {
262 //This is wrong too: Counters are *always* spinning! !!! FIX !!! [DONE]
263 //      if (jerry_timer_1_counter)
264                 jerry_timer_1_counter -= cycles;
265
266         if (jerry_timer_1_counter <= 0)
267         {
268 //Also, it can generate a CPU interrupt as well... !!! FIX !!! or does it? Maybe it goes Timer->GPU->CPU?
269                 DSPSetIRQLine(DSPIRQ_TIMER0, ASSERT_LINE);      // This does the 'IRQ enabled' checking...
270 //              JERRYResetPIT1();
271                 jerry_timer_1_counter += (JERRYPIT1Prescaler + 1) * (JERRYPIT1Divider + 1);
272         }
273
274 //This is wrong too: Counters are *always* spinning! !!! FIX !!! [DONE]
275 //      if (jerry_timer_2_counter)
276                 jerry_timer_2_counter -= cycles;
277
278         if (jerry_timer_2_counter <= 0)
279         {
280 //Also, it can generate a CPU interrupt as well... !!! FIX !!! or does it? Maybe it goes Timer->GPU->CPU?
281                 DSPSetIRQLine(DSPIRQ_TIMER1, ASSERT_LINE);      // This does the 'IRQ enabled' checking...
282 //              JERRYResetPIT2();
283                 jerry_timer_2_counter += (JERRYPIT2Prescaler + 1) * (JERRYPIT2Divider + 1);
284         }
285 }
286
287 void JERRYResetI2S(void)
288 {
289         //WriteLog("i2s: reseting\n");
290 //This is really SCLK... !!! FIX !!!
291         jerry_i2s_interrupt_divide = 8;
292         jerry_i2s_interrupt_timer = -1;
293 }
294
295 void JERRYResetPIT1(void)
296 {
297 #ifndef NEW_TIMER_SYSTEM
298 /*      if (!JERRYPIT1Prescaler || !JERRYPIT1Divider)
299                 jerry_timer_1_counter = 0;
300         else//*/
301 //Small problem with this approach: Overflow if both are = $FFFF. !!! FIX !!!
302                 jerry_timer_1_counter = (JERRYPIT1Prescaler + 1) * (JERRYPIT1Divider + 1);
303
304 //      if (jerry_timer_1_counter)
305 //              WriteLog("jerry: reseting timer 1 to 0x%.8x (%i)\n",jerry_timer_1_counter,jerry_timer_1_counter);
306
307 #else
308         RemoveCallback(JERRYPIT1Callback);
309
310         if (JERRYPIT1Prescaler | JERRYPIT1Divider)
311         {
312                 double usecs = (float)(JERRYPIT1Prescaler + 1) * (float)(JERRYPIT1Divider + 1) * RISC_CYCLE_IN_USEC;
313                 SetCallbackTime(JERRYPIT1Callback, usecs);
314         }
315 #endif
316 }
317
318 void JERRYResetPIT2(void)
319 {
320 #ifndef NEW_TIMER_SYSTEM
321 /*      if (!JERRYPIT2Prescaler || !JERRYPIT2Divider)
322         {
323                 jerry_timer_2_counter = 0;
324                 return;
325         }
326         else//*/
327                 jerry_timer_2_counter = (JERRYPIT2Prescaler + 1) * (JERRYPIT2Divider + 1);
328
329 //      if (jerry_timer_2_counter)
330 //              WriteLog("jerry: reseting timer 2 to 0x%.8x (%i)\n",jerry_timer_2_counter,jerry_timer_2_counter);
331
332 #else
333         RemoveCallback(JERRYPIT2Callback);
334
335         if (JERRYPIT1Prescaler | JERRYPIT1Divider)
336         {
337                 double usecs = (float)(JERRYPIT2Prescaler + 1) * (float)(JERRYPIT2Divider + 1) * RISC_CYCLE_IN_USEC;
338                 SetCallbackTime(JERRYPIT2Callback, usecs);
339         }
340 #endif
341 }
342
343 void JERRYPIT1Callback(void)
344 {
345         DSPSetIRQLine(DSPIRQ_TIMER0, ASSERT_LINE);      // This does the 'IRQ enabled' checking...
346         JERRYResetPIT1();
347 }
348
349 void JERRYPIT2Callback(void)
350 {
351         DSPSetIRQLine(DSPIRQ_TIMER1, ASSERT_LINE);      // This does the 'IRQ enabled' checking...
352         JERRYResetPIT2();
353 }
354
355 void JERRYI2SCallback(void)
356 {
357         // Why is it called this? Instead of SCLK? Shouldn't this be read from DAC.CPP???
358 //Yes, it should. !!! FIX !!!
359 #warning Yes, it should. !!! FIX !!!
360         jerry_i2s_interrupt_divide &= 0xFF;
361         // We don't have to divide the RISC clock rate by this--the reason is a bit
362         // convoluted. Will put explanation here later...
363 // What's needed here is to find the ratio of the frequency to the number of clock cycles
364 // in one second. For example, if the sample rate is 44100, we divide the clock rate by
365 // this: 26590906 / 44100 = 602 cycles.
366 // Which means, every 602 cycles that go by we have to generate an interrupt.
367         jerryI2SCycles = 32 * (2 * (jerry_i2s_interrupt_divide + 1));
368
369 //This should be in this file with an extern reference in the header file so that
370 //DAC.CPP can see it... !!! FIX !!!
371         extern uint16 serialMode;                                               // From DAC.CPP
372
373         if (serialMode & 0x01)                                                  // INTERNAL flag (JERRY is master)
374         {
375                 DSPSetIRQLine(DSPIRQ_SSI, ASSERT_LINE);         // This does the 'IRQ enabled' checking...
376                 double usecs = (float)jerryI2SCycles * RISC_CYCLE_IN_USEC;
377                 SetCallbackTime(JERRYI2SCallback, usecs);
378         }
379         else                                                                                    // JERRY is slave to external word clock
380         {
381 //Note that 44100 Hz requires samples every 22.675737 usec.
382 //When JERRY is slave to the word clock, we need to do interrupts either at 44.1K
383 //sample rate or at a 88.2K sample rate (11.332... usec).
384 /*              // This is just a temporary kludge to see if the CD bus mastering works
385                 // I.e., this is totally faked...!
386 // The whole interrupt system is pretty much borked and is need of an overhaul.
387 // What we need is a way of handling these interrupts when they happen instead of
388 // scanline boundaries the way it is now.
389                 jerry_i2s_interrupt_timer -= cycles;
390                 if (jerry_i2s_interrupt_timer <= 0)
391                 {
392 //This is probably wrong as well (i.e., need to check enable lines)... !!! FIX !!! [DONE]
393                         if (ButchIsReadyToSend())//Not sure this is right spot to check...
394                         {
395 //      return GetWordFromButchSSI(offset, who);
396                                 SetSSIWordsXmittedFromButch();
397                                 DSPSetIRQLine(DSPIRQ_SSI, ASSERT_LINE);
398                         }
399                         jerry_i2s_interrupt_timer += 602;
400                 }*/
401
402                 if (ButchIsReadyToSend())//Not sure this is right spot to check...
403                 {
404 //      return GetWordFromButchSSI(offset, who);
405                         SetSSIWordsXmittedFromButch();
406                         DSPSetIRQLine(DSPIRQ_SSI, ASSERT_LINE);
407                 }
408
409                 SetCallbackTime(JERRYI2SCallback, 22.675737);
410         }
411 }
412
413
414 void jerry_init(void)
415 {
416 //      clock_init();
417 //      anajoy_init();
418         JoystickInit();
419         DACInit();
420 //This should be handled with the cart initialization...
421 //      eeprom_init();
422 //      memory_malloc_secure((void **)&jerry_ram_8, 0x10000, "JERRY RAM/ROM");
423         memcpy(&jerry_ram_8[0xD000], wave_table, 0x1000);
424
425         JERRYPIT1Prescaler = 0xFFFF;
426         JERRYPIT2Prescaler = 0xFFFF;
427         JERRYPIT1Divider = 0xFFFF;
428         JERRYPIT2Divider = 0xFFFF;
429 }
430
431 void jerry_reset(void)
432 {
433 //      clock_reset();
434 //      anajoy_reset();
435         JoystickReset();
436         eeprom_reset();
437         JERRYResetI2S();
438         DACReset();
439
440         memset(jerry_ram_8, 0x00, 0xD000);              // Don't clear out the Wavetable ROM...!
441         JERRYPIT1Prescaler = 0xFFFF;
442         JERRYPIT2Prescaler = 0xFFFF;
443         JERRYPIT1Divider = 0xFFFF;
444         JERRYPIT2Divider = 0xFFFF;
445         jerry_timer_1_counter = 0;
446         jerry_timer_2_counter = 0;
447 }
448
449 void jerry_done(void)
450 {
451         WriteLog("JERRY: M68K Interrupt control ($F10020) = %04X\n", GET16(jerry_ram_8, 0x20));
452 //      memory_free(jerry_ram_8);
453 //      clock_done();
454 //      anajoy_done();
455         JoystickDone();
456         DACDone();
457         eeprom_done();
458 }
459
460 bool JERRYIRQEnabled(int irq)
461 {
462         // Read the word @ $F10020
463         return jerry_ram_8[0x21] & (1 << irq);
464 }
465
466 void JERRYSetPendingIRQ(int irq)
467 {
468         // This is the shadow of INT (it's a split RO/WO register)
469         jerryIntPending |= (1 << irq);
470 }
471
472 //
473 // JERRY byte access (read)
474 //
475 uint8 JERRYReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
476 {
477 #ifdef JERRY_DEBUG
478         WriteLog("JERRY: Reading byte at %06X\n", offset);
479 #endif
480         if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
481                 return DSPReadByte(offset, who);
482         else if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
483                 return DSPReadByte(offset, who);
484         // LRXD/RRXD/SSTAT $F1A148/4C/50 (really 16-bit registers...)
485         else if (offset >= 0xF1A148 && offset <= 0xF1A153)
486                 return DACReadByte(offset, who);
487 //      F10036          R     xxxxxxxx xxxxxxxx   JPIT1 - timer 1 pre-scaler
488 //      F10038          R     xxxxxxxx xxxxxxxx   JPIT2 - timer 1 divider
489 //      F1003A          R     xxxxxxxx xxxxxxxx   JPIT3 - timer 2 pre-scaler
490 //      F1003C          R     xxxxxxxx xxxxxxxx   JPIT4 - timer 2 divider
491 //This is WRONG!
492 //      else if (offset >= 0xF10000 && offset <= 0xF10007)
493 //This is still wrong. What needs to be returned here are the values being counted down
494 //in the jerry_timer_n_counter variables... !!! FIX !!! [DONE]
495
496 //This is probably the problem with the new timer code... This is invalid
497 //under the new system... !!! FIX !!!
498         else if ((offset >= 0xF10036) && (offset <= 0xF1003D))
499         {
500 #ifndef NEW_TIMER_SYSTEM
501 //              jerry_timer_1_counter = (JERRYPIT1Prescaler + 1) * (JERRYPIT1Divider + 1);
502                 uint32 counter1Hi = (jerry_timer_1_counter / (JERRYPIT1Divider + 1)) - 1;
503                 uint32 counter1Lo = (jerry_timer_1_counter % (JERRYPIT1Divider + 1)) - 1;
504                 uint32 counter2Hi = (jerry_timer_2_counter / (JERRYPIT2Divider + 1)) - 1;
505                 uint32 counter2Lo = (jerry_timer_2_counter % (JERRYPIT2Divider + 1)) - 1;
506
507                 switch(offset & 0x0F)
508                 {
509                 case 6:
510 //                      return JERRYPIT1Prescaler >> 8;
511                         return counter1Hi >> 8;
512                 case 7:
513 //                      return JERRYPIT1Prescaler & 0xFF;
514                         return counter1Hi & 0xFF;
515                 case 8:
516 //                      return JERRYPIT1Divider >> 8;
517                         return counter1Lo >> 8;
518                 case 9:
519 //                      return JERRYPIT1Divider & 0xFF;
520                         return counter1Lo & 0xFF;
521                 case 10:
522 //                      return JERRYPIT2Prescaler >> 8;
523                         return counter2Hi >> 8;
524                 case 11:
525 //                      return JERRYPIT2Prescaler & 0xFF;
526                         return counter2Hi & 0xFF;
527                 case 12:
528 //                      return JERRYPIT2Divider >> 8;
529                         return counter2Lo >> 8;
530                 case 13:
531 //                      return JERRYPIT2Divider & 0xFF;
532                         return counter2Lo & 0xFF;
533                 }
534 #else
535 WriteLog("JERRY: Unhandled timer read (BYTE) at %08X...\n", offset);
536 #endif
537         }
538 //      else if (offset >= 0xF10010 && offset <= 0xF10015)
539 //              return clock_byte_read(offset);
540 //      else if (offset >= 0xF17C00 && offset <= 0xF17C01)
541 //              return anajoy_byte_read(offset);
542         else if (offset >= 0xF14000 && offset <= 0xF14003)
543                 return JoystickReadByte(offset) | eeprom_byte_read(offset);
544         else if (offset >= 0xF14000 && offset <= 0xF1A0FF)
545                 return eeprom_byte_read(offset);
546
547         return jerry_ram_8[offset & 0xFFFF];
548 }
549
550 //
551 // JERRY word access (read)
552 //
553 uint16 JERRYReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
554 {
555 #ifdef JERRY_DEBUG
556         WriteLog("JERRY: Reading word at %06X\n", offset);
557 #endif
558
559         if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
560                 return DSPReadWord(offset, who);
561         else if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
562                 return DSPReadWord(offset, who);
563         // LRXD/RRXD/SSTAT $F1A148/4C/50 (really 16-bit registers...)
564         else if (offset >= 0xF1A148 && offset <= 0xF1A153)
565                 return DACReadWord(offset, who);
566 //      F10036          R     xxxxxxxx xxxxxxxx   JPIT1 - timer 1 pre-scaler
567 //      F10038          R     xxxxxxxx xxxxxxxx   JPIT2 - timer 1 divider
568 //      F1003A          R     xxxxxxxx xxxxxxxx   JPIT3 - timer 2 pre-scaler
569 //      F1003C          R     xxxxxxxx xxxxxxxx   JPIT4 - timer 2 divider
570 //This is WRONG!
571 //      else if ((offset >= 0xF10000) && (offset <= 0xF10007))
572 //This is still wrong. What needs to be returned here are the values being counted down
573 //in the jerry_timer_n_counter variables... !!! FIX !!! [DONE]
574         else if ((offset >= 0xF10036) && (offset <= 0xF1003D))
575         {
576 #ifndef NEW_TIMER_SYSTEM
577 //              jerry_timer_1_counter = (JERRYPIT1Prescaler + 1) * (JERRYPIT1Divider + 1);
578                 uint32 counter1Hi = (jerry_timer_1_counter / (JERRYPIT1Divider + 1)) - 1;
579                 uint32 counter1Lo = (jerry_timer_1_counter % (JERRYPIT1Divider + 1)) - 1;
580                 uint32 counter2Hi = (jerry_timer_2_counter / (JERRYPIT2Divider + 1)) - 1;
581                 uint32 counter2Lo = (jerry_timer_2_counter % (JERRYPIT2Divider + 1)) - 1;
582
583                 switch(offset & 0x0F)
584                 {
585                 case 6:
586 //                      return JERRYPIT1Prescaler;
587                         return counter1Hi;
588                 case 8:
589 //                      return JERRYPIT1Divider;
590                         return counter1Lo;
591                 case 10:
592 //                      return JERRYPIT2Prescaler;
593                         return counter2Hi;
594                 case 12:
595 //                      return JERRYPIT2Divider;
596                         return counter2Lo;
597                 }
598                 // Unaligned word reads???
599 #else
600 WriteLog("JERRY: Unhandled timer read (WORD) at %08X...\n", offset);
601 #endif
602         }
603 //      else if ((offset >= 0xF10010) && (offset <= 0xF10015))
604 //              return clock_word_read(offset);
605         else if (offset == 0xF10020)
606                 return jerryIntPending;
607 //      else if ((offset >= 0xF17C00) && (offset <= 0xF17C01))
608 //              return anajoy_word_read(offset);
609         else if (offset == 0xF14000)
610                 return (JoystickReadWord(offset) & 0xFFFE) | eeprom_word_read(offset);
611         else if ((offset >= 0xF14002) && (offset < 0xF14003))
612                 return JoystickReadWord(offset);
613         else if ((offset >= 0xF14000) && (offset <= 0xF1A0FF))
614                 return eeprom_word_read(offset);
615
616 /*if (offset >= 0xF1D000)
617         WriteLog("JERRY: Reading word at %08X [%04X]...\n", offset, ((uint16)jerry_ram_8[(offset+0)&0xFFFF] << 8) | jerry_ram_8[(offset+1)&0xFFFF]);//*/
618
619         offset &= 0xFFFF;                               // Prevent crashing...!
620         return ((uint16)jerry_ram_8[offset+0] << 8) | jerry_ram_8[offset+1];
621 }
622
623 //
624 // JERRY byte access (write)
625 //
626 void JERRYWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
627 {
628 #ifdef JERRY_DEBUG
629         WriteLog("jerry: writing byte %.2x at 0x%.6x\n",data,offset);
630 #endif
631         if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
632         {
633                 DSPWriteByte(offset, data, who);
634                 return;
635         }
636         else if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
637         {
638                 DSPWriteByte(offset, data, who);
639                 return;
640         }
641         // SCLK ($F1A150--8 bits wide)
642 //NOTE: This should be taken care of in DAC...
643         else if ((offset >= 0xF1A152) && (offset <= 0xF1A153))
644         {
645 //              WriteLog("JERRY: Writing %02X to SCLK...\n", data);
646                 if ((offset & 0x03) == 2)
647                         jerry_i2s_interrupt_divide = (jerry_i2s_interrupt_divide & 0x00FF) | ((uint32)data << 8);
648                 else
649                         jerry_i2s_interrupt_divide = (jerry_i2s_interrupt_divide & 0xFF00) | (uint32)data;
650
651                 jerry_i2s_interrupt_timer = -1;
652 #ifndef NEW_TIMER_SYSTEM
653                 jerry_i2s_exec(0);
654 #else
655                 RemoveCallback(JERRYI2SCallback);
656                 JERRYI2SCallback();
657 #endif
658 //              return;
659         }
660         // LTXD/RTXD/SCLK/SMODE $F1A148/4C/50/54 (really 16-bit registers...)
661         else if (offset >= 0xF1A148 && offset <= 0xF1A157)
662         {
663                 DACWriteByte(offset, data, who);
664                 return;
665         }
666         else if (offset >= 0xF10000 && offset <= 0xF10007)
667         {
668 #ifndef NEW_TIMER_SYSTEM
669                 switch (offset & 0x07)
670                 {
671                 case 0:
672                         JERRYPIT1Prescaler = (JERRYPIT1Prescaler & 0x00FF) | (data << 8);
673                         JERRYResetPIT1();
674                         break;
675                 case 1:
676                         JERRYPIT1Prescaler = (JERRYPIT1Prescaler & 0xFF00) | data;
677                         JERRYResetPIT1();
678                         break;
679                 case 2:
680                         JERRYPIT1Divider = (JERRYPIT1Divider & 0x00FF) | (data << 8);
681                         JERRYResetPIT1();
682                         break;
683                 case 3:
684                         JERRYPIT1Divider = (JERRYPIT1Divider & 0xFF00) | data;
685                         JERRYResetPIT1();
686                         break;
687                 case 4:
688                         JERRYPIT2Prescaler = (JERRYPIT2Prescaler & 0x00FF) | (data << 8);
689                         JERRYResetPIT2();
690                         break;
691                 case 5:
692                         JERRYPIT2Prescaler = (JERRYPIT2Prescaler & 0xFF00) | data;
693                         JERRYResetPIT2();
694                         break;
695                 case 6:
696                         JERRYPIT2Divider = (JERRYPIT2Divider & 0x00FF) | (data << 8);
697                         JERRYResetPIT2();
698                         break;
699                 case 7:
700                         JERRYPIT2Divider = (JERRYPIT2Divider & 0xFF00) | data;
701                         JERRYResetPIT2();
702                 }
703 #else
704 WriteLog("JERRY: Unhandled timer write (BYTE) at %08X...\n", offset);
705 #endif
706                 return;
707         }
708 /*      else if ((offset >= 0xF10010) && (offset <= 0xF10015))
709         {
710                 clock_byte_write(offset, data);
711                 return;
712         }//*/
713         // JERRY -> 68K interrupt enables/latches (need to be handled!)
714         else if (offset >= 0xF10020 && offset <= 0xF10023)
715         {
716 WriteLog("JERRY: (68K int en/lat - Unhandled!) Tried to write $%02X to $%08X!\n", data, offset);
717         }
718 /*      else if ((offset >= 0xF17C00) && (offset <= 0xF17C01))
719         {
720                 anajoy_byte_write(offset, data);
721                 return;
722         }*/
723         else if ((offset >= 0xF14000) && (offset <= 0xF14003))
724         {
725                 JoystickWriteByte(offset, data);
726                 eeprom_byte_write(offset, data);
727                 return;
728         }
729         else if ((offset >= 0xF14000) && (offset <= 0xF1A0FF))
730         {
731                 eeprom_byte_write(offset, data);
732                 return;
733         }
734
735 //Need to protect write attempts to Wavetable ROM (F1D000-FFF)
736         if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
737                 return;
738
739         jerry_ram_8[offset & 0xFFFF] = data;
740 }
741
742 //
743 // JERRY word access (write)
744 //
745 void JERRYWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
746 {
747 #ifdef JERRY_DEBUG
748         WriteLog( "JERRY: Writing word %04X at %06X\n", data, offset);
749 #endif
750
751         if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
752         {
753                 DSPWriteWord(offset, data, who);
754                 return;
755         }
756         else if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
757         {
758                 DSPWriteWord(offset, data, who);
759                 return;
760         }
761 //NOTE: This should be taken care of in DAC...
762         else if (offset == 0xF1A152)                                    // Bottom half of SCLK ($F1A150)
763         {
764                 WriteLog("JERRY: Writing %04X to SCLK (by %s)...\n", data, whoName[who]);
765 //This should *only* be enabled when SMODE has its INTERNAL bit set! !!! FIX !!!
766                 jerry_i2s_interrupt_divide = (uint8)data;
767                 jerry_i2s_interrupt_timer = -1;
768 #ifndef NEW_TIMER_SYSTEM
769                 jerry_i2s_exec(0);
770 #else
771                 RemoveCallback(JERRYI2SCallback);
772                 JERRYI2SCallback();
773 #endif
774
775                 DACWriteWord(offset, data, who);
776                 return;
777         }
778         // LTXD/RTXD/SCLK/SMODE $F1A148/4C/50/54 (really 16-bit registers...)
779         else if (offset >= 0xF1A148 && offset <= 0xF1A156)
780         {
781                 DACWriteWord(offset, data, who);
782                 return;
783         }
784         else if (offset >= 0xF10000 && offset <= 0xF10007)
785         {
786 //#ifndef NEW_TIMER_SYSTEM
787 #if 1
788                 switch(offset & 0x07)
789                 {
790                 case 0:
791                         JERRYPIT1Prescaler = data;
792                         JERRYResetPIT1();
793                         break;
794                 case 2:
795                         JERRYPIT1Divider = data;
796                         JERRYResetPIT1();
797                         break;
798                 case 4:
799                         JERRYPIT2Prescaler = data;
800                         JERRYResetPIT2();
801                         break;
802                 case 6:
803                         JERRYPIT2Divider = data;
804                         JERRYResetPIT2();
805                 }
806                 // Need to handle (unaligned) cases???
807 #else
808 WriteLog("JERRY: Unhandled timer write %04X (WORD) at %08X by %s...\n", data, offset, whoName[who]);
809 #endif
810                 return;
811         }
812 /*      else if (offset >= 0xF10010 && offset < 0xF10016)
813         {
814                 clock_word_write(offset, data);
815                 return;
816         }//*/
817         // JERRY -> 68K interrupt enables/latches (need to be handled!)
818         else if (offset >= 0xF10020 && offset <= 0xF10022)
819         {
820 WriteLog("JERRY: (68K int en/lat - Unhandled!) Tried to write $%04X to $%08X!\n", data, offset);
821         }
822 /*      else if (offset >= 0xF17C00 && offset < 0xF17C02)
823         {
824 //I think this was removed from the Jaguar. If so, then we don't need this...!
825                 anajoy_word_write(offset, data);
826                 return;
827         }*/
828         else if (offset >= 0xF14000 && offset < 0xF14003)
829         {
830                 JoystickWriteWord(offset, data);
831                 eeprom_word_write(offset, data);
832                 return;
833         }
834         else if (offset >= 0xF14000 && offset <= 0xF1A0FF)
835         {
836                 eeprom_word_write(offset, data);
837                 return;
838         }
839
840 //Need to protect write attempts to Wavetable ROM (F1D000-FFF)
841         if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
842                 return;
843
844         jerry_ram_8[(offset+0) & 0xFFFF] = (data >> 8) & 0xFF;
845         jerry_ram_8[(offset+1) & 0xFFFF] = data & 0xFF;
846 }