]> Shamusworld >> Repos - virtualjaguar/blob - src/jerry.cpp
27c3cab25d8c381b43216ec87932a2e6a533bc7c
[virtualjaguar] / src / jerry.cpp
1 //
2 // JERRY Core
3 //
4 // by cal2
5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Cleanups 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 //      F10004            W   xxxxxxxx xxxxxxxx   JPIT2 - timer 1 divider
14 //      F10008            W   xxxxxxxx xxxxxxxx   JPIT3 - timer 2 pre-scaler
15 //      F1000C            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 //      ------------------------------------------------------------
56 //      F14000-F17FFF   R/W   xxxxxxxx xxxxxxxx   Joysticks and GPIO0-5
57 //      F14000          R     xxxxxxxx xxxxxxxx   JOYSTICK - read joystick state
58 //      F14000            W   x------- xxxxxxxx   JOYSTICK - latch joystick output
59 //                        W   x------- --------      (enable joystick outputs)
60 //                        W   -------- xxxxxxxx      (joystick output data)
61 //      F14002          R     xxxxxxxx xxxxxxxx   JOYBUTS - button register
62 //      F14800-F14FFF   R/W   xxxxxxxx xxxxxxxx   GPI00 - reserved
63 //      F15000-F15FFF   R/W   xxxxxxxx xxxxxxxx   GPI01 - reserved
64 //      F16000-F16FFF   R/W   xxxxxxxx xxxxxxxx   GPI02 - reserved
65 //      F17000-F177FF   R/W   xxxxxxxx xxxxxxxx   GPI03 - reserved
66 //      F17800-F17BFF   R/W   xxxxxxxx xxxxxxxx   GPI04 - reserved
67 //      F17C00-F17FFF   R/W   xxxxxxxx xxxxxxxx   GPI05 - reserved
68 //      ------------------------------------------------------------
69 //      F18000-F1FFFF   R/W   xxxxxxxx xxxxxxxx   Jerry DSP
70 //      F1A100          R/W   xxxxxxxx xxxxxxxx   D_FLAGS - DSP flags register
71 //                      R/W   x------- --------      (DMAEN - DMA enable)
72 //                      R/W   -x------ --------      (REGPAGE - register page)
73 //                        W   --x----- --------      (D_EXT0CLR - clear external interrupt 0)
74 //                        W   ---x---- --------      (D_TIM2CLR - clear timer 2 interrupt)
75 //                        W   ----x--- --------      (D_TIM1CLR - clear timer 1 interrupt)
76 //                        W   -----x-- --------      (D_I2SCLR - clear I2S interrupt)
77 //                        W   ------x- --------      (D_CPUCLR - clear CPU interrupt)
78 //                      R/W   -------x --------      (D_EXT0ENA - enable external interrupt 0)
79 //                      R/W   -------- x-------      (D_TIM2ENA - enable timer 2 interrupt)
80 //                      R/W   -------- -x------      (D_TIM1ENA - enable timer 1 interrupt)
81 //                      R/W   -------- --x-----      (D_I2SENA - enable I2S interrupt)
82 //                      R/W   -------- ---x----      (D_CPUENA - enable CPU interrupt)
83 //                      R/W   -------- ----x---      (IMASK - interrupt mask)
84 //                      R/W   -------- -----x--      (NEGA_FLAG - ALU negative)
85 //                      R/W   -------- ------x-      (CARRY_FLAG - ALU carry)
86 //                      R/W   -------- -------x      (ZERO_FLAG - ALU zero)
87 //      F1A102          R/W   -------- ------xx   D_FLAGS - upper DSP flags
88 //                      R/W   -------- ------x-      (D_EXT1ENA - enable external interrupt 1)
89 //                      R/W   -------- -------x      (D_EXT1CLR - clear external interrupt 1)
90 //      F1A104            W   -------- ----xxxx   D_MTXC - matrix control register
91 //                        W   -------- ----x---      (MATCOL - column/row major)
92 //                        W   -------- -----xxx      (MATRIX3-15 - matrix width)
93 //      F1A108            W   ----xxxx xxxxxx--   D_MTXA - matrix address register
94 //      F1A10C            W   -------- -----x-x   D_END - data organization register
95 //                        W   -------- -----x--      (BIG_INST - big endian instruction fetch)
96 //                        W   -------- -------x      (BIG_IO - big endian I/O)
97 //      F1A110          R/W   xxxxxxxx xxxxxxxx   D_PC - DSP program counter
98 //      F1A114          R/W   xxxxxxxx xx-xxxxx   D_CTRL - DSP control/status register
99 //                      R     xxxx---- --------      (VERSION - DSP version code)
100 //                      R/W   ----x--- --------      (BUS_HOG - hog the bus!)
101 //                      R/W   -----x-- --------      (D_EXT0LAT - external interrupt 0 latch)
102 //                      R/W   ------x- --------      (D_TIM2LAT - timer 2 interrupt latch)
103 //                      R/W   -------x --------      (D_TIM1LAT - timer 1 interrupt latch)
104 //                      R/W   -------- x-------      (D_I2SLAT - I2S interrupt latch)
105 //                      R/W   -------- -x------      (D_CPULAT - CPU interrupt latch)
106 //                      R/W   -------- ---x----      (SINGLE_GO - single step one instruction)
107 //                      R/W   -------- ----x---      (SINGLE_STEP - single step mode)
108 //                      R/W   -------- -----x--      (FORCEINT0 - cause interrupt 0 on GPU)
109 //                      R/W   -------- ------x-      (CPUINT - send GPU interrupt to CPU)
110 //                      R/W   -------- -------x      (DSPGO - enable DSP execution)
111 //      F1A116          R/W   -------- -------x   D_CTRL - upper DSP control/status register
112 //                      R/W   -------- -------x      (D_EXT1LAT - external interrupt 1 latch)
113 //      F1A118-F1A11B     W   xxxxxxxx xxxxxxxx   D_MOD - modulo instruction mask
114 //      F1A11C-F1A11F   R     xxxxxxxx xxxxxxxx   D_REMAIN - divide unit remainder
115 //      F1A11C            W   -------- -------x   D_DIVCTRL - divide unit control
116 //                        W   -------- -------x      (DIV_OFFSET - 1=16.16 divide, 0=32-bit divide)
117 //      F1A120-F1A123   R     xxxxxxxx xxxxxxxx   D_MACHI - multiply & accumulate high bits
118 //      F1A148            W   xxxxxxxx xxxxxxxx   R_DAC - right transmit data
119 //      F1A14C            W   xxxxxxxx xxxxxxxx   L_DAC - left transmit data
120 //      F1A150            W   -------- xxxxxxxx   SCLK - serial clock frequency
121 //      F1A150          R     -------- ------xx   SSTAT
122 //                      R     -------- ------x-      (left - no description)
123 //                      R     -------- -------x      (WS - word strobe status)
124 //      F1A154            W   -------- --xxxx-x   SMODE - serial mode
125 //                        W   -------- --x-----      (EVERYWORD - interrupt on MSB of every word)
126 //                        W   -------- ---x----      (FALLING - interrupt on falling edge)
127 //                        W   -------- ----x---      (RISING - interrupt of rising edge)
128 //                        W   -------- -----x--      (WSEN - enable word strobes)
129 //                        W   -------- -------x      (INTERNAL - enables serial clock)
130 //      ------------------------------------------------------------
131 //      F1B000-F1CFFF   R/W   xxxxxxxx xxxxxxxx   Local DSP RAM
132 //      ------------------------------------------------------------
133 //      F1D000          R     xxxxxxxx xxxxxxxx   ROM_TRI - triangle wave
134 //      F1D200          R     xxxxxxxx xxxxxxxx   ROM_SINE - full sine wave
135 //      F1D400          R     xxxxxxxx xxxxxxxx   ROM_AMSINE - amplitude modulated sine wave
136 //      F1D600          R     xxxxxxxx xxxxxxxx   ROM_12W - sine wave and second order harmonic
137 //      F1D800          R     xxxxxxxx xxxxxxxx   ROM_CHIRP16 - chirp
138 //      F1DA00          R     xxxxxxxx xxxxxxxx   ROM_NTRI - traingle wave with noise
139 //      F1DC00          R     xxxxxxxx xxxxxxxx   ROM_DELTA - spike
140 //      F1DE00          R     xxxxxxxx xxxxxxxx   ROM_NOISE - white noise
141 //      ------------------------------------------------------------
142
143 #include "jerry.h"
144 #include "wavetable.h"
145 #include <math.h>
146
147 //#define JERRY_DEBUG
148
149 static uint8 * jerry_ram_8;
150
151 #define JERRY_CONFIG    0x4002
152
153 uint8 analog_x, analog_y;
154
155 static uint32 jerry_timer_1_prescaler;
156 static uint32 jerry_timer_2_prescaler;
157 static uint32 jerry_timer_1_divider;
158 static uint32 jerry_timer_2_divider;
159 static int32 jerry_timer_1_counter;
160 static int32 jerry_timer_2_counter;
161
162 static uint32 jerry_i2s_interrupt_divide = 8;
163 static int32 jerry_i2s_interrupt_timer = -1;
164 uint32 jerryI2SCycles;
165 uint32 jerryIntPending;
166
167 //This approach is probably wrong, since the timer is continuously counting down, though
168 //it might only be a problem if the # of interrupts generated is greater than 1--the M68K's
169 //timeslice should be running during that phase... (The DSP needs to be aware of this!)
170 void jerry_i2s_exec(uint32 cycles)
171 {       
172         extern uint16 serialMode;                                               // From DAC.CPP
173         if (!(serialMode & 0x01))                                               // INTERNAL flag
174                 return;
175
176         // Why is it called this? Instead of SCLK? Shouldn't this be read from DAC.CPP???
177 //Yes, it should. !!! FIX !!!
178         jerry_i2s_interrupt_divide &= 0xFF;
179
180         if (jerry_i2s_interrupt_timer == -1)
181         {
182                 // We don't have to divide the RISC clock rate by this--the reason is a bit
183                 // convoluted. Will put explanation here later...
184 // What's needed here is to find the ratio of the frequency to the number of clock cycles
185 // in one second. For example, if the sample rate is 44100, we divide the clock rate by
186 // this: 26590906 / 44100 = 602 cycles.
187 // Which means, every 602 cycles that go by we have to generate an interrupt.
188                 jerryI2SCycles = 32 * (2 * (jerry_i2s_interrupt_divide + 1));
189         }
190
191         jerry_i2s_interrupt_timer -= cycles;
192         if (jerry_i2s_interrupt_timer <= 0)
193         {
194                 DSPSetIRQLine(DSPIRQ_SSI, ASSERT_LINE);
195                 jerry_i2s_interrupt_timer += jerryI2SCycles;
196 #ifdef JERRY_DEBUG
197                 if (jerry_i2s_interrupt_timer < 0)
198                         WriteLog("JERRY: Missed generating an interrupt (missed %u)!\n", (-jerry_i2s_interrupt_timer / jerryI2SCycles) + 1);
199 #endif
200         }
201 }
202
203 void jerry_reset_i2s_timer(void)
204 {
205         //WriteLog("i2s: reseting\n");
206 //This is really SCLK... !!! FIX !!!
207         jerry_i2s_interrupt_divide = 8;
208         jerry_i2s_interrupt_timer = -1;
209 }
210
211 void jerry_reset_timer_1(void)
212 {
213         if (!jerry_timer_1_prescaler || !jerry_timer_1_divider)
214                 jerry_timer_1_counter = 0;
215         else
216                 jerry_timer_1_counter = (1 + jerry_timer_1_prescaler) * (1 + jerry_timer_1_divider);
217
218 //      if (jerry_timer_1_counter)
219 //              WriteLog("jerry: reseting timer 1 to 0x%.8x (%i)\n",jerry_timer_1_counter,jerry_timer_1_counter);
220 }
221
222 void jerry_reset_timer_2(void)
223 {
224         if (!jerry_timer_2_prescaler || !jerry_timer_2_divider)
225         {
226                 jerry_timer_2_counter = 0;
227                 return;
228         }
229         else
230                 jerry_timer_2_counter = ((1 + jerry_timer_2_prescaler) * (1 + jerry_timer_2_divider));
231
232 //      if (jerry_timer_2_counter)
233 //              WriteLog("jerry: reseting timer 2 to 0x%.8x (%i)\n",jerry_timer_2_counter,jerry_timer_2_counter);
234 }
235
236 void JERRYExecPIT(uint32 cycles)
237 {
238         if (jerry_timer_1_counter)
239                 jerry_timer_1_counter -= cycles;
240
241         if (jerry_timer_1_counter <= 0)
242         {
243                 DSPSetIRQLine(DSPIRQ_TIMER0, ASSERT_LINE);
244                 jerry_reset_timer_1();
245         }
246
247         if (jerry_timer_2_counter)
248                 jerry_timer_2_counter -= cycles;
249
250         if (jerry_timer_2_counter <= 0)
251         {
252                 DSPSetIRQLine(DSPIRQ_TIMER1, ASSERT_LINE);
253                 jerry_reset_timer_2();
254         }
255 }
256
257 void jerry_init(void)
258 {
259         clock_init();
260         anajoy_init();
261         joystick_init();
262         DACInit();
263 //This should be handled with the cart initialization...
264 //      eeprom_init();
265         memory_malloc_secure((void **)&jerry_ram_8, 0x10000, "JERRY RAM/ROM");
266         memcpy(&jerry_ram_8[0xD000], wave_table, 0x1000);
267 }
268
269 void jerry_reset(void)
270 {
271         clock_reset();
272         anajoy_reset();
273         joystick_reset();
274         eeprom_reset();
275         jerry_reset_i2s_timer();
276         DACReset();
277
278         memset(jerry_ram_8, 0x00, 0xD000);              // Don't clear out the Wavetable ROM...!
279         jerry_timer_1_prescaler = 0xFFFF;
280         jerry_timer_2_prescaler = 0xFFFF;
281         jerry_timer_1_divider = 0xFFFF;
282         jerry_timer_2_divider = 0xFFFF;
283         jerry_timer_1_counter = 0;
284         jerry_timer_2_counter = 0;
285 }
286
287 void jerry_done(void)
288 {
289         WriteLog("JERRY: M68K Interrupt control ($F10020) = %04X\n", GET16(jerry_ram_8, 0x20));
290         memory_free(jerry_ram_8);
291         clock_done();
292         anajoy_done();
293         joystick_done();
294         DACDone();
295         eeprom_done();
296 }
297
298 bool JERRYIRQEnabled(int irq)
299 {
300         // Read the word @ $F10020 
301         return jerry_ram_8[0x21] & (1 << irq);
302 }
303
304 void JERRYSetPendingIRQ(int irq)
305 {
306         // This is the shadow of INT (it's a split RO/WO register)
307         jerryIntPending |= (1 << irq);
308 }
309
310 //
311 // JERRY byte access (read)
312 //
313 uint8 JERRYReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
314 {
315 #ifdef JERRY_DEBUG
316         WriteLog("JERRY: Reading byte at %06X\n", offset);
317 #endif
318         if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
319                 return DSPReadByte(offset, who);
320         else if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
321                 return DSPReadByte(offset, who);
322         else if (offset >= 0xF10000 && offset <= 0xF10007)
323         {
324                 switch(offset & 0x07)
325                 {
326                 case 0:
327                         return jerry_timer_1_prescaler >> 8;
328                 case 1:
329                         return jerry_timer_1_prescaler & 0xFF;
330                 case 2:
331                         return jerry_timer_1_divider >> 8;
332                 case 3:
333                         return jerry_timer_1_divider & 0xFF;
334                 case 4:
335                         return jerry_timer_2_prescaler >> 8;
336                 case 5:
337                         return jerry_timer_2_prescaler & 0xFF;
338                 case 6:
339                         return jerry_timer_2_divider >> 8;
340                 case 7:
341                         return jerry_timer_2_divider & 0xFF;
342                 }
343         }
344         else if (offset >= 0xF10010 && offset <= 0xF10015)
345                 return clock_byte_read(offset);
346         else if (offset >= 0xF17C00 && offset <= 0xF17C01)
347                 return anajoy_byte_read(offset);
348         else if (offset >= 0xF14000 && offset <= 0xF14003)
349         {
350                 return joystick_byte_read(offset) | eeprom_byte_read(offset);
351         }
352         else if (offset >= 0xF14000 && offset <= 0xF1A0FF)
353                 return eeprom_byte_read(offset);
354         
355         return jerry_ram_8[offset & 0xFFFF];
356 }
357
358 //
359 // JERRY word access (read)
360 //
361 uint16 JERRYReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
362 {
363 #ifdef JERRY_DEBUG
364         WriteLog("JERRY: Reading word at %06X\n", offset);
365 #endif
366
367         if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
368                 return DSPReadWord(offset, who);
369         else if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE + 0x1FFF)
370                 return DSPReadWord(offset, who);
371         else if ((offset >= 0xF10000) && (offset <= 0xF10007))
372         {
373                 switch(offset & 0x07)
374                 {
375                 case 0:
376                         return jerry_timer_1_prescaler;
377                 case 2:
378                         return jerry_timer_1_divider;
379                 case 4:
380                         return jerry_timer_2_prescaler;
381                 case 6:
382                         return jerry_timer_2_divider;
383                 }
384                 // Unaligned word reads???
385         }
386         else if ((offset >= 0xF10010) && (offset <= 0xF10015))
387                 return clock_word_read(offset);
388         else if (offset == 0xF10020)
389                 return jerryIntPending;
390         else if ((offset >= 0xF17C00) && (offset <= 0xF17C01))
391                 return anajoy_word_read(offset);
392         else if (offset == 0xF14000)
393         {
394                 //WriteLog("reading 0x%.4x from 0xf14000\n");
395                 return (joystick_word_read(offset) & 0xFFFE) | eeprom_word_read(offset);
396         }
397         else if ((offset >= 0xF14002) && (offset < 0xF14003))
398                 return joystick_word_read(offset);
399         else if ((offset >= 0xF14000) && (offset <= 0xF1A0FF))
400                 return eeprom_word_read(offset);
401
402 /*if (offset >= 0xF1D000)
403         WriteLog("JERRY: Reading word at %08X [%04X]...\n", offset, ((uint16)jerry_ram_8[(offset+0)&0xFFFF] << 8) | jerry_ram_8[(offset+1)&0xFFFF]);//*/
404
405         offset &= 0xFFFF;                               // Prevent crashing...!
406         return ((uint16)jerry_ram_8[offset+0] << 8) | jerry_ram_8[offset+1];
407 }
408
409 //
410 // JERRY byte access (write)
411 //
412 void JERRYWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
413 {
414 #ifdef JERRY_DEBUG
415         WriteLog("jerry: writing byte %.2x at 0x%.6x\n",data,offset);
416 #endif
417         if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
418         {
419                 DSPWriteByte(offset, data, who);
420                 return;
421         }
422         else if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
423         {
424                 DSPWriteByte(offset, data, who);
425                 return;
426         }
427         // SCLK ($F1A150--8 bits wide)
428         else if ((offset >= 0xF1A152) && (offset <= 0xF1A153))
429         {
430 //              WriteLog("JERRY: Writing %02X to SCLK...\n", data);
431                 if ((offset & 0x03) == 2)
432                         jerry_i2s_interrupt_divide = (jerry_i2s_interrupt_divide & 0x00FF) | ((uint32)data << 8);
433                 else
434                         jerry_i2s_interrupt_divide = (jerry_i2s_interrupt_divide & 0xFF00) | (uint32)data;
435
436                 jerry_i2s_interrupt_timer = -1;
437                 jerry_i2s_exec(0);
438 //              return;
439         }
440         // LTXD/RTXD/SCLK/SMODE $F1A148/4C/50/54 (really 16-bit registers...)
441         else if (offset >= 0xF1A148 && offset <= 0xF1A157)
442         { 
443                 DACWriteByte(offset, data);
444                 return; 
445         }
446         else if (offset >= 0xF10000 && offset <= 0xF10007)
447         {
448                 switch (offset & 0x07)
449                 {
450                 case 0:
451                         jerry_timer_1_prescaler = (jerry_timer_1_prescaler & 0x00FF) | (data << 8);
452                         jerry_reset_timer_1();
453                         break;
454                 case 1:
455                         jerry_timer_1_prescaler = (jerry_timer_1_prescaler & 0xFF00) | (data);
456                         jerry_reset_timer_1();
457                         break;
458                 case 2: { jerry_timer_1_divider=(jerry_timer_1_divider&0x00ff)|(data<<8);               jerry_reset_timer_1(); return; }
459                 case 3: { jerry_timer_1_divider=(jerry_timer_1_divider&0xff00)|(data);                  jerry_reset_timer_1(); return; }
460                 case 4: { jerry_timer_2_prescaler=(jerry_timer_2_prescaler&0x00ff)|(data<<8);   jerry_reset_timer_2(); return; }
461                 case 5: { jerry_timer_2_prescaler=(jerry_timer_2_prescaler&0xff00)|(data);              jerry_reset_timer_2(); return; }
462                 case 6: { jerry_timer_2_divider=(jerry_timer_2_divider&0x00ff)|(data<<8);               jerry_reset_timer_2(); return; }
463                 case 7: { jerry_timer_2_divider=(jerry_timer_2_divider&0xff00)|(data);                  jerry_reset_timer_2(); return; }
464                 }
465                 return;
466         }
467         else if ((offset >= 0xF10010) && (offset <= 0xF10015))
468         {
469                 clock_byte_write(offset, data);
470                 return;
471         }
472         else if ((offset >= 0xF17C00) && (offset <= 0xF17C01))
473         {
474                 anajoy_byte_write(offset, data);
475                 return;
476         }
477         else if ((offset >= 0xF14000) && (offset <= 0xF14003))
478         {
479                 joystick_byte_write(offset, data);
480                 eeprom_byte_write(offset, data);
481                 return;
482         }
483         else if ((offset >= 0xF14000) && (offset <= 0xF1A0FF))
484         {
485                 eeprom_byte_write(offset, data);
486                 return;
487         }
488
489 //Need to protect write attempts to Wavetable ROM (F1D000-FFF)
490         if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
491                 return;
492
493         jerry_ram_8[offset & 0xFFFF] = data;
494 }
495
496 //
497 // JERRY word access (write)
498 //
499 void JERRYWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
500 {
501 #ifdef JERRY_DEBUG
502         WriteLog( "JERRY: Writing word %04X at %06X\n", data, offset);
503 #endif
504
505         if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
506         {
507                 DSPWriteWord(offset, data, who);
508                 return;
509         }
510         else if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
511         {
512                 DSPWriteWord(offset, data, who);
513                 return;
514         }
515         else if (offset == 0xF1A152)                                    // Bottom half of SCLK ($F1A150)
516         {
517                 WriteLog("JERRY: Writing %04X to SCLK (by %s)...\n", data, whoName[who]);
518                 jerry_i2s_interrupt_divide = (uint8)data;
519                 jerry_i2s_interrupt_timer = -1;
520                 jerry_i2s_exec(0);
521
522                 DACWriteWord(offset, data);
523                 return; 
524         }
525         // LTXD/RTXD/SCLK/SMODE $F1A148/4C/50/54 (really 16-bit registers...)
526         else if (offset >= 0xF1A148 && offset <= 0xF1A156)
527         { 
528                 DACWriteWord(offset, data);
529                 return; 
530         }
531         else if ((offset >= 0xF10000) && (offset <= 0xF10007))
532         {
533                 switch(offset & 0x07)
534                 {
535                 case 0:
536                         jerry_timer_1_prescaler = data;
537                         jerry_reset_timer_1();
538                         break;
539                 case 2:
540                         jerry_timer_1_divider = data;
541                         jerry_reset_timer_1();
542                         break;
543                 case 4:
544                         jerry_timer_2_prescaler = data;
545                         jerry_reset_timer_2();
546                         break;
547                 case 6:
548                         jerry_timer_2_divider = data;
549                         jerry_reset_timer_2();
550                 }
551                 // Need to handle (unaligned) cases???
552                 return;
553         }
554         else if ((offset >= 0xF10010) && (offset < 0xF10016))
555         {
556                 clock_word_write(offset, data);
557                 return;
558         }
559         // JERRY -> 68K interrupt enables/latches (need to be handled!)
560         else if (offset >= 0xF10020 && offset <= 0xF10022)
561         {
562         }
563         else if ((offset >= 0xF17C00) && (offset < 0xF17C02))
564         {
565 //I think this was removed from the Jaguar. If so, then we don't need this...!
566                 anajoy_word_write(offset, data);
567                 return;
568         }
569         else if ((offset >= 0xF14000) && (offset < 0xF14003))
570         {
571                 joystick_word_write(offset, data);
572                 eeprom_word_write(offset, data);
573                 return;
574         }
575         else if ((offset >= 0xF14000) && (offset <= 0xF1A0FF))
576         {
577                 eeprom_word_write(offset, data);
578                 return;
579         }
580
581 //Need to protect write attempts to Wavetable ROM (F1D000-FFF)
582         if (offset >= 0xF1D000 && offset <= 0xF1DFFF)
583                 return;
584
585         jerry_ram_8[(offset+0) & 0xFFFF] = (data >> 8) & 0xFF;
586         jerry_ram_8[(offset+1) & 0xFFFF] = data & 0xFF;
587 }