]> Shamusworld >> Repos - virtualjaguar/blob - src/tom.cpp
Adding 1.0.1/2 uncompressed tarballs to tags for historical purposes.
[virtualjaguar] / src / tom.cpp
1 //\r
2 // TOM Processing\r
3 //\r
4 // by cal16\r
5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)\r
6 // Cleanups and endian wrongness amelioration by James L. Hammons\r
7 // Note: Endian wrongness probably stems from the MAME origins of this emu and\r
8 //       the braindead way in which MAME handles memory. :-)\r
9 //\r
10 // Note: TOM has only a 16K memory space\r
11 //\r
12 //      ------------------------------------------------------------\r
13 //      TOM REGISTERS (Mapped by Aaron Giles)\r
14 //      ------------------------------------------------------------\r
15 //      F00000-F0FFFF   R/W   xxxxxxxx xxxxxxxx   Internal Registers\r
16 //      F00000          R/W   -x-xx--- xxxxxxxx   MEMCON1 - memory config reg 1\r
17 //                            -x------ --------      (CPU32 - is the CPU 32bits?)\r
18 //                            ---xx--- --------      (IOSPEED - external I/O clock cycles)\r
19 //                            -------- x-------      (FASTROM - reduces ROM clock cycles)\r
20 //                            -------- -xx-----      (DRAMSPEED - sets RAM clock cycles)\r
21 //                            -------- ---xx---      (ROMSPEED - sets ROM clock cycles)\r
22 //                            -------- -----xx-      (ROMWIDTH - sets width of ROM: 8,16,32,64 bits)\r
23 //                            -------- -------x      (ROMHI - controls ROM mapping)\r
24 //      F00002          R/W   --xxxxxx xxxxxxxx   MEMCON2 - memory config reg 2\r
25 //                            --x----- --------      (HILO - image display bit order)\r
26 //                            ---x---- --------      (BIGEND - big endian addressing?)\r
27 //                            ----xxxx --------      (REFRATE - DRAM refresh rate)\r
28 //                            -------- xx------      (DWIDTH1 - DRAM1 width: 8,16,32,64 bits)\r
29 //                            -------- --xx----      (COLS1 - DRAM1 columns: 256,512,1024,2048)\r
30 //                            -------- ----xx--      (DWIDTH0 - DRAM0 width: 8,16,32,64 bits)\r
31 //                            -------- ------xx      (COLS0 - DRAM0 columns: 256,512,1024,2048)\r
32 //      F00004          R/W   -----xxx xxxxxxxx   HC - horizontal count\r
33 //                            -----x-- --------      (which half of the display)\r
34 //                            ------xx xxxxxxxx      (10-bit counter)\r
35 //      F00006          R/W   ----xxxx xxxxxxxx   VC - vertical count\r
36 //                            ----x--- --------      (which field is being generated)\r
37 //                            -----xxx xxxxxxxx      (11-bit counter)\r
38 //      F00008          R     -----xxx xxxxxxxx   LPH - light pen horizontal position\r
39 //      F0000A          R     -----xxx xxxxxxxx   LPV - light pen vertical position\r
40 //      F00010-F00017   R     xxxxxxxx xxxxxxxx   OB - current object code from the graphics processor\r
41 //      F00020-F00023     W   xxxxxxxx xxxxxxxx   OLP - start of the object list\r
42 //      F00026            W   -------- -------x   OBF - object processor flag\r
43 //      F00028            W   ----xxxx xxxxxxxx   VMODE - video mode\r
44 //                        W   ----xxx- --------      (PWIDTH1-8 - width of pixel in video clock cycles)\r
45 //                        W   -------x --------      (VARMOD - enable variable color resolution)\r
46 //                        W   -------- x-------      (BGEN - clear line buffere to BG color)\r
47 //                        W   -------- -x------      (CSYNC - enable composite sync on VSYNC)\r
48 //                        W   -------- --x-----      (BINC - local border color if INCEN)\r
49 //                        W   -------- ---x----      (INCEN - encrustation enable)\r
50 //                        W   -------- ----x---      (GENLOCK - enable genlock)\r
51 //                        W   -------- -----xx-      (MODE - CRY16,RGB24,DIRECT16,RGB16)\r
52 //                        W   -------- -------x      (VIDEN - enables video)\r
53 //      F0002A            W   xxxxxxxx xxxxxxxx   BORD1 - border color (red/green)\r
54 //      F0002C            W   -------- xxxxxxxx   BORD2 - border color (blue)\r
55 //      F0002E            W   ------xx xxxxxxxx   HP - horizontal period\r
56 //      F00030            W   -----xxx xxxxxxxx   HBB - horizontal blanking begin\r
57 //      F00032            W   -----xxx xxxxxxxx   HBE - horizontal blanking end\r
58 //      F00034            W   -----xxx xxxxxxxx   HSYNC - horizontal sync\r
59 //      F00036            W   ------xx xxxxxxxx   HVS - horizontal vertical sync\r
60 //      F00038            W   -----xxx xxxxxxxx   HDB1 - horizontal display begin 1\r
61 //      F0003A            W   -----xxx xxxxxxxx   HDB2 - horizontal display begin 2\r
62 //      F0003C            W   -----xxx xxxxxxxx   HDE - horizontal display end\r
63 //      F0003E            W   -----xxx xxxxxxxx   VP - vertical period\r
64 //      F00040            W   -----xxx xxxxxxxx   VBB - vertical blanking begin\r
65 //      F00042            W   -----xxx xxxxxxxx   VBE - vertical blanking end\r
66 //      F00044            W   -----xxx xxxxxxxx   VS - vertical sync\r
67 //      F00046            W   -----xxx xxxxxxxx   VDB - vertical display begin\r
68 //      F00048            W   -----xxx xxxxxxxx   VDE - vertical display end\r
69 //      F0004A            W   -----xxx xxxxxxxx   VEB - vertical equalization begin\r
70 //      F0004C            W   -----xxx xxxxxxxx   VEE - vertical equalization end\r
71 //      F0004E            W   -----xxx xxxxxxxx   VI - vertical interrupt\r
72 //      F00050            W   xxxxxxxx xxxxxxxx   PIT0 - programmable interrupt timer 0\r
73 //      F00052            W   xxxxxxxx xxxxxxxx   PIT1 - programmable interrupt timer 1\r
74 //      F00054            W   ------xx xxxxxxxx   HEQ - horizontal equalization end\r
75 //      F00058            W   xxxxxxxx xxxxxxxx   BG - background color\r
76 //      F000E0          R/W   ---xxxxx ---xxxxx   INT1 - CPU interrupt control register\r
77 //                            ---x---- --------      (C_JERCLR - clear pending Jerry ints)\r
78 //                            ----x--- --------      (C_PITCLR - clear pending PIT ints)\r
79 //                            -----x-- --------      (C_OPCLR - clear pending object processor ints)\r
80 //                            ------x- --------      (C_GPUCLR - clear pending graphics processor ints)\r
81 //                            -------x --------      (C_VIDCLR - clear pending video timebase ints)\r
82 //                            -------- ---x----      (C_JERENA - enable Jerry ints)\r
83 //                            -------- ----x---      (C_PITENA - enable PIT ints)\r
84 //                            -------- -----x--      (C_OPENA - enable object processor ints)\r
85 //                            -------- ------x-      (C_GPUENA - enable graphics processor ints)\r
86 //                            -------- -------x      (C_VIDENA - enable video timebase ints)\r
87 //      F000E2            W   -------- --------   INT2 - CPU interrupt resume register\r
88 //      F00400-F005FF   R/W   xxxxxxxx xxxxxxxx   CLUT - color lookup table A\r
89 //      F00600-F007FF   R/W   xxxxxxxx xxxxxxxx   CLUT - color lookup table B\r
90 //      F00800-F00D9F   R/W   xxxxxxxx xxxxxxxx   LBUF - line buffer A\r
91 //      F01000-F0159F   R/W   xxxxxxxx xxxxxxxx   LBUF - line buffer B\r
92 //      F01800-F01D9F   R/W   xxxxxxxx xxxxxxxx   LBUF - line buffer currently selected\r
93 //      ------------------------------------------------------------\r
94 //      F02000-F021FF   R/W   xxxxxxxx xxxxxxxx   GPU control registers\r
95 //      F02100          R/W   xxxxxxxx xxxxxxxx   G_FLAGS - GPU flags register\r
96 //                      R/W   x------- --------      (DMAEN - DMA enable)\r
97 //                      R/W   -x------ --------      (REGPAGE - register page)\r
98 //                        W   --x----- --------      (G_BLITCLR - clear blitter interrupt)\r
99 //                        W   ---x---- --------      (G_OPCLR - clear object processor int)\r
100 //                        W   ----x--- --------      (G_PITCLR - clear PIT interrupt)\r
101 //                        W   -----x-- --------      (G_JERCLR - clear Jerry interrupt)\r
102 //                        W   ------x- --------      (G_CPUCLR - clear CPU interrupt)\r
103 //                      R/W   -------x --------      (G_BLITENA - enable blitter interrupt)\r
104 //                      R/W   -------- x-------      (G_OPENA - enable object processor int)\r
105 //                      R/W   -------- -x------      (G_PITENA - enable PIT interrupt)\r
106 //                      R/W   -------- --x-----      (G_JERENA - enable Jerry interrupt)\r
107 //                      R/W   -------- ---x----      (G_CPUENA - enable CPU interrupt)\r
108 //                      R/W   -------- ----x---      (IMASK - interrupt mask)\r
109 //                      R/W   -------- -----x--      (NEGA_FLAG - ALU negative)\r
110 //                      R/W   -------- ------x-      (CARRY_FLAG - ALU carry)\r
111 //                      R/W   -------- -------x      (ZERO_FLAG - ALU zero)\r
112 //      F02104            W   -------- ----xxxx   G_MTXC - matrix control register\r
113 //                        W   -------- ----x---      (MATCOL - column/row major)\r
114 //                        W   -------- -----xxx      (MATRIX3-15 - matrix width)\r
115 //      F02108            W   ----xxxx xxxxxx--   G_MTXA - matrix address register\r
116 //      F0210C            W   -------- -----xxx   G_END - data organization register\r
117 //                        W   -------- -----x--      (BIG_INST - big endian instruction fetch)\r
118 //                        W   -------- ------x-      (BIG_PIX - big endian pixels)\r
119 //                        W   -------- -------x      (BIG_IO - big endian I/O)\r
120 //      F02110          R/W   xxxxxxxx xxxxxxxx   G_PC - GPU program counter\r
121 //      F02114          R/W   xxxxxxxx xx-xxxxx   G_CTRL - GPU control/status register\r
122 //                      R     xxxx---- --------      (VERSION - GPU version code)\r
123 //                      R/W   ----x--- --------      (BUS_HOG - hog the bus!)\r
124 //                      R/W   -----x-- --------      (G_BLITLAT - blitter interrupt latch)\r
125 //                      R/W   ------x- --------      (G_OPLAT - object processor int latch)\r
126 //                      R/W   -------x --------      (G_PITLAT - PIT interrupt latch)\r
127 //                      R/W   -------- x-------      (G_JERLAT - Jerry interrupt latch)\r
128 //                      R/W   -------- -x------      (G_CPULAT - CPU interrupt latch)\r
129 //                      R/W   -------- ---x----      (SINGLE_GO - single step one instruction)\r
130 //                      R/W   -------- ----x---      (SINGLE_STEP - single step mode)\r
131 //                      R/W   -------- -----x--      (FORCEINT0 - cause interrupt 0 on GPU)\r
132 //                      R/W   -------- ------x-      (CPUINT - send GPU interrupt to CPU)\r
133 //                      R/W   -------- -------x      (GPUGO - enable GPU execution)\r
134 //      F02118-F0211B   R/W   xxxxxxxx xxxxxxxx   G_HIDATA - high data register\r
135 //      F0211C-F0211F   R     xxxxxxxx xxxxxxxx   G_REMAIN - divide unit remainder\r
136 //      F0211C            W   -------- -------x   G_DIVCTRL - divide unit control\r
137 //                        W   -------- -------x      (DIV_OFFSET - 1=16.16 divide, 0=32-bit divide)\r
138 //      ------------------------------------------------------------\r
139 \r
140 #ifndef __PORT__\r
141 #include <windows.h>\r
142 #endif\r
143 #include <SDL.h>\r
144 #include "SDLptc.h"\r
145 #include "tom.h"\r
146 #include "gpu.h"\r
147 #include "objectp.h"\r
148 #include "cry2rgb.h"\r
149 \r
150 \r
151 extern uint32 jaguar_mainRom_crc32;\r
152 \r
153 //This can be defined in the makefile as well...\r
154 //#define TOM_DEBUG\r
155 \r
156 extern Console console;\r
157 extern Surface * surface;\r
158 \r
159 // This makes sense IFF it's being used in an endian friendly way. Currently, it's not.\r
160 //#define SWAP_32_ALL(A) ((SWAP_16(A>>16))|(SWAP_16(A<<16))) \r
161 //#define SWAP_32(A) ((A>>16)|(A<<16))\r
162 //#define SWAP_16(A) ((A>>8)|(A<<8))\r
163 // These are more endian friendly...\r
164 #define SET16(addr, val)        tom_ram_8[addr] = ((val) & 0xFF00) >> 8, tom_ram_8[addr+1] = (val) & 0x00FF\r
165 #define GET16(addr)                     (tom_ram_8[addr] << 8) | tom_ram_8[addr+1]\r
166 \r
167 static uint8 * tom_ram_8;\r
168 // This is just braindead and wrong!\r
169 //static uint16 * tom_ram_16;\r
170 //static uint32 * tom_ram_32;\r
171 \r
172 /*\r
173 #define MEMCON1 tom_ram_16[0]\r
174 #define MEMCON2 tom_ram_16[1]\r
175 #define VMODE   tom_ram_16[0x28>>1]\r
176 #define VBB             tom_ram_16[0x40>>1]\r
177 #define VBE             tom_ram_16[0x42>>1]\r
178 #define VDB             tom_ram_16[0x46>>1]\r
179 #define VDE             tom_ram_16[0x48>>1]\r
180 \r
181 #define BG              tom_ram_16[0x58>>1]\r
182 \r
183 #define HBB             tom_ram_16[0x30>>1]\r
184 #define HBE             tom_ram_16[0x32>>1]\r
185 #define HDB             tom_ram_16[0x38>>1]\r
186 #define HDE             tom_ram_16[0x3C>>1]\r
187 \r
188 #define HP              tom_ram_16[0x2E>>1]\r
189 #define VP              tom_ram_16[0x3E>>1]\r
190 #define VS              tom_ram_16[0x44>>1]\r
191 \r
192 #define BKGCOLOR tom_ram_16[0x58>>1]\r
193 */\r
194 #define MEMCON1         0x00\r
195 #define MEMCON2         0x02\r
196 #define VMODE           0x28\r
197 #define HP                      0x2E\r
198 #define HBB                     0x30\r
199 #define HBE                     0x32\r
200 #define HDB                     0x38\r
201 #define HDE                     0x3C\r
202 #define VP                      0x3E\r
203 #define VBB                     0x40\r
204 #define VBE                     0x42\r
205 #define VS                      0x44\r
206 #define VDB                     0x46\r
207 #define VDE                     0x48\r
208 #define BG                      0x58\r
209 \r
210 \r
211 uint32 tom_width, tom_height, tom_real_internal_width;\r
212 \r
213 static uint32 tom_timer_prescaler;\r
214 static uint32 tom_timer_divider;\r
215 static int32 tom_timer_counter;\r
216 \r
217 uint32 tom_scanline;\r
218 uint32 hblankWidthInPixels = 0;\r
219 \r
220 static char * videoMode_to_str[8] =\r
221         {"16 bpp CRY", "24 bpp RGB", "16 bpp DIRECT", "16 bpp RGB",\r
222         "Mixed mode", "24 bpp RGB", "16 bpp DIRECT", "16 bpp RGB"};\r
223 \r
224 extern uint8 objectp_running;\r
225 \r
226 typedef void (render_xxx_scanline_fn)(int16 *);\r
227 \r
228 void tom_render_16bpp_cry_scanline(int16 * backbuffer);\r
229 void tom_render_24bpp_scanline(int16 * backbuffer);\r
230 void tom_render_16bpp_direct_scanline(int16 * backbuffer);\r
231 void tom_render_16bpp_rgb_scanline(int16 * backbuffer);\r
232 void tom_render_16bpp_cry_rgb_mix_scanline(int16 * backbuffer);\r
233 \r
234 void tom_render_16bpp_cry_stretch_scanline(int16 * backbuffer);\r
235 void tom_render_24bpp_stretch_scanline(int16 * backbuffer);\r
236 void tom_render_16bpp_direct_stretch_scanline(int16 * backbuffer);\r
237 void tom_render_16bpp_rgb_stretch_scanline(int16 * backbuffer);\r
238 void tom_render_16bpp_cry_rgb_mix_stretch_scanline(int16 * backbuffer);\r
239 \r
240 render_xxx_scanline_fn * scanline_render_normal[]=\r
241 {\r
242         tom_render_16bpp_cry_scanline,\r
243         tom_render_24bpp_scanline,\r
244         tom_render_16bpp_direct_scanline,\r
245         tom_render_16bpp_rgb_scanline,\r
246         tom_render_16bpp_cry_rgb_mix_scanline,\r
247         tom_render_24bpp_scanline,\r
248         tom_render_16bpp_direct_scanline,\r
249         tom_render_16bpp_rgb_scanline,\r
250 };\r
251 render_xxx_scanline_fn * scanline_render_stretch[]=\r
252 {\r
253         tom_render_16bpp_cry_stretch_scanline,\r
254         tom_render_24bpp_stretch_scanline,\r
255         tom_render_16bpp_direct_stretch_scanline,\r
256         tom_render_16bpp_rgb_stretch_scanline,\r
257         tom_render_16bpp_cry_rgb_mix_stretch_scanline,\r
258         tom_render_24bpp_stretch_scanline,\r
259         tom_render_16bpp_direct_stretch_scanline,\r
260         tom_render_16bpp_rgb_stretch_scanline,\r
261 };\r
262 render_xxx_scanline_fn * scanline_render[8];\r
263 \r
264 uint16 tom_puck_int_pending;\r
265 uint16 tom_timer_int_pending;\r
266 uint16 tom_object_int_pending;\r
267 uint16 tom_gpu_int_pending;\r
268 uint16 tom_video_int_pending;\r
269 \r
270 uint16 * tom_cry_rgb_mix_lut;\r
271 \r
272 //////////////////////////////////////////////////////////////////////////////\r
273 //\r
274 //////////////////////////////////////////////////////////////////////////////\r
275 //\r
276 //\r
277 //\r
278 //\r
279 //\r
280 //\r
281 //////////////////////////////////////////////////////////////////////////////\r
282 void tom_calc_cry_rgb_mix_lut(void)\r
283 {\r
284         uint32 chrm, chrl, y;\r
285 \r
286         memory_malloc_secure((void **)&tom_cry_rgb_mix_lut, 0x20000, "cry/rgb mixed mode lut");\r
287 \r
288         for (uint32 i=0; i<0x10000; i++)\r
289         {\r
290                 uint16 color=i;\r
291 \r
292                 if (color & 0x01)\r
293                 {\r
294                         color >>= 1;\r
295                         color = (color & 0x007C00) | ((color & 0x00003E0) >> 5) | ((color & 0x0000001F) << 5);\r
296                 }\r
297                 else\r
298                 {\r
299                         chrm = (color & 0xF000) >> 12;    \r
300                         chrl = (color & 0x0F00) >> 8;\r
301                         y    = (color & 0x00FF);\r
302                                         \r
303                         uint16 red   = ((((uint32)redcv[chrm][chrl]) * y) >> 11);\r
304                         uint16 green = ((((uint32)greencv[chrm][chrl]) * y) >> 11);\r
305                         uint16 blue  = ((((uint32)bluecv[chrm][chrl]) * y) >> 11);\r
306                         color = (red << 10) | (green << 5) | blue;\r
307                 }\r
308                 tom_cry_rgb_mix_lut[i] = color;\r
309         }\r
310 }\r
311 \r
312 void tom_set_pending_puck_int(void)\r
313 {\r
314         tom_puck_int_pending = 1;\r
315 }\r
316 \r
317 void tom_set_pending_timer_int(void)\r
318 {\r
319         tom_timer_int_pending = 1;\r
320 }\r
321 \r
322 void tom_set_pending_object_int(void)\r
323 {\r
324         tom_object_int_pending = 1;\r
325 }\r
326 \r
327 void tom_set_pending_gpu_int(void)\r
328 {\r
329         tom_gpu_int_pending = 1;\r
330 }\r
331 \r
332 void tom_set_pending_video_int(void)\r
333 {\r
334         tom_video_int_pending = 1;\r
335 }\r
336 \r
337 uint8 * tom_get_ram_pointer(void)\r
338 {\r
339         return tom_ram_8;\r
340 }\r
341 //////////////////////////////////////////////////////////////////////////////\r
342 //\r
343 //////////////////////////////////////////////////////////////////////////////\r
344 //\r
345 //\r
346 //\r
347 //\r
348 //\r
349 //\r
350 //////////////////////////////////////////////////////////////////////////////\r
351 uint8 tom_getVideoMode(void)\r
352 {\r
353 //      uint16 vmode = SWAP_16(VMODE);\r
354         uint16 vmode = GET16(VMODE);\r
355         return ((vmode >> 1) & 0x03) | ((vmode & 0x100) >> 6);\r
356 }\r
357 \r
358 //////////////////////////////////////////////////////////////////////////////\r
359 //\r
360 //////////////////////////////////////////////////////////////////////////////\r
361 //\r
362 //\r
363 //\r
364 //\r
365 //\r
366 //\r
367 //////////////////////////////////////////////////////////////////////////////\r
368 uint16 tom_get_scanline(void)\r
369 {\r
370         return tom_scanline;\r
371 }\r
372 //////////////////////////////////////////////////////////////////////////////\r
373 //\r
374 //////////////////////////////////////////////////////////////////////////////\r
375 //\r
376 //\r
377 //\r
378 //\r
379 //\r
380 //\r
381 //////////////////////////////////////////////////////////////////////////////\r
382 uint16 tom_get_hdb(void)\r
383 {\r
384 //      return SWAP_16(HDB);\r
385         return GET16(HDB);\r
386 }\r
387 //////////////////////////////////////////////////////////////////////////////\r
388 //\r
389 //////////////////////////////////////////////////////////////////////////////\r
390 //\r
391 //\r
392 //\r
393 //\r
394 //\r
395 //\r
396 //////////////////////////////////////////////////////////////////////////////\r
397 uint16 tom_get_vdb(void)\r
398 {\r
399 //      return SWAP_16(VBE);\r
400         return GET16(VBE);\r
401 }\r
402 //////////////////////////////////////////////////////////////////////////////\r
403 //\r
404 //////////////////////////////////////////////////////////////////////////////\r
405 //\r
406 //\r
407 //\r
408 //\r
409 //\r
410 //\r
411 //////////////////////////////////////////////////////////////////////////////\r
412 void tom_render_16bpp_cry_rgb_mix_scanline(int16 * backbuffer)\r
413 {\r
414         uint32 chrm, chrl, y;\r
415 \r
416         uint16 width = tom_width;\r
417         uint8 * current_line_buffer=(uint8 *)&tom_ram_8[0x1800];\r
418         \r
419         while (width)\r
420         {\r
421                 uint16 color;\r
422                 color = *current_line_buffer++;\r
423                 color <<= 8;\r
424                 color |= *current_line_buffer++;\r
425                 *backbuffer++ = tom_cry_rgb_mix_lut[color];\r
426                 width--;\r
427         }\r
428 }\r
429 //////////////////////////////////////////////////////////////////////////////\r
430 //\r
431 //////////////////////////////////////////////////////////////////////////////\r
432 //\r
433 //\r
434 //\r
435 //\r
436 //\r
437 //\r
438 //////////////////////////////////////////////////////////////////////////////\r
439 void tom_render_16bpp_cry_scanline(int16 *backbuffer)\r
440 {\r
441         uint32 chrm, chrl, y;\r
442 \r
443         uint16 width=tom_width;\r
444         uint8 *current_line_buffer=(uint8*)&tom_ram_8[0x1800];\r
445         \r
446         while (width)\r
447         {\r
448                 uint16 color;\r
449                 color=*current_line_buffer++;\r
450                 color<<=8;\r
451                 color|=*current_line_buffer++;\r
452                 \r
453                 chrm = (color & 0xF000) >> 12;    \r
454                 chrl = (color & 0x0F00) >> 8;\r
455                 y    = (color & 0x00FF);\r
456                                 \r
457                 uint16 red   =  ((((uint32)redcv[chrm][chrl])*y)>>11);\r
458                 uint16 green =  ((((uint32)greencv[chrm][chrl])*y)>>11);\r
459                 uint16 blue  =  ((((uint32)bluecv[chrm][chrl])*y)>>11);\r
460                 \r
461                 \r
462                 *backbuffer++=(red<<10)|(green<<5)|blue;\r
463                 width--;\r
464         }\r
465 }\r
466 //////////////////////////////////////////////////////////////////////////////\r
467 //\r
468 //////////////////////////////////////////////////////////////////////////////\r
469 //\r
470 //\r
471 //\r
472 //\r
473 //\r
474 //\r
475 //////////////////////////////////////////////////////////////////////////////\r
476 void tom_render_24bpp_scanline(int16 *backbuffer)\r
477 {\r
478         uint16 width=tom_width;\r
479         uint8 *current_line_buffer=(uint8*)&tom_ram_8[0x1800];\r
480         \r
481         while (width)\r
482         {\r
483                 uint16 green=*current_line_buffer++;\r
484                 uint16 red=*current_line_buffer++;\r
485                 uint16 nc=*current_line_buffer++;\r
486                 uint16 blue=*current_line_buffer++;\r
487                 red>>=3;\r
488                 green>>=3;\r
489                 blue>>=3;\r
490                 *backbuffer++=(red<<10)|(green<<5)|blue;\r
491                 width--;\r
492         }\r
493 }\r
494 //////////////////////////////////////////////////////////////////////////////\r
495 //\r
496 //////////////////////////////////////////////////////////////////////////////\r
497 //\r
498 //\r
499 //\r
500 //\r
501 //\r
502 //\r
503 //////////////////////////////////////////////////////////////////////////////\r
504 void tom_render_16bpp_direct_scanline(int16 *backbuffer)\r
505 {\r
506         uint16 width=tom_width;\r
507         uint8 *current_line_buffer=(uint8*)&tom_ram_8[0x1800];\r
508         \r
509         while (width)\r
510         {\r
511                 uint16 color=*current_line_buffer++;\r
512                 color<<=8;\r
513                 color|=*current_line_buffer++;\r
514                 color>>=1;\r
515                 *backbuffer++=color;\r
516                 width--;\r
517         }\r
518 }\r
519 //////////////////////////////////////////////////////////////////////////////\r
520 //\r
521 //////////////////////////////////////////////////////////////////////////////\r
522 //\r
523 //\r
524 //\r
525 //\r
526 //\r
527 //\r
528 //////////////////////////////////////////////////////////////////////////////\r
529 void tom_render_16bpp_rgb_scanline(int16 *backbuffer)\r
530 {\r
531         uint16 width=tom_width;\r
532         uint8 *current_line_buffer=(uint8*)&tom_ram_8[0x1800];\r
533         \r
534         while (width)\r
535         {\r
536                 uint16 color=*current_line_buffer++;\r
537                 color<<=8;\r
538                 color|=*current_line_buffer++;\r
539                 color>>=1;\r
540                 color=(color&0x007c00)|((color&0x00003e0)>>5)|((color&0x0000001f)<<5);\r
541                 *backbuffer++=color;\r
542                 width--;\r
543         }\r
544 }\r
545 //////////////////////////////////////////////////////////////////////////////\r
546 //\r
547 //////////////////////////////////////////////////////////////////////////////\r
548 //\r
549 //\r
550 //\r
551 //\r
552 //\r
553 //\r
554 //////////////////////////////////////////////////////////////////////////////\r
555 void tom_render_16bpp_cry_rgb_mix_stretch_scanline(int16 *backbuffer)\r
556 {\r
557         uint32 chrm, chrl, y;\r
558 \r
559         uint16 width=tom_width;\r
560         uint8 *current_line_buffer=(uint8*)&tom_ram_8[0x1800];\r
561         \r
562         while (width)\r
563         {\r
564                 uint16 color;\r
565                 color=*current_line_buffer++;\r
566                 color<<=8;\r
567                 color|=*current_line_buffer++;\r
568                 *backbuffer++=tom_cry_rgb_mix_lut[color];\r
569                 current_line_buffer+=2;\r
570                 width--;\r
571         }\r
572 }\r
573 //////////////////////////////////////////////////////////////////////////////\r
574 //\r
575 //////////////////////////////////////////////////////////////////////////////\r
576 //\r
577 //\r
578 //\r
579 //\r
580 //\r
581 //\r
582 //////////////////////////////////////////////////////////////////////////////\r
583 void tom_render_16bpp_cry_stretch_scanline(int16 *backbuffer)\r
584 {\r
585         uint32 chrm, chrl, y;\r
586 \r
587         uint16 width=tom_width;\r
588         uint8 *current_line_buffer=(uint8*)&tom_ram_8[0x1800];\r
589         \r
590         while (width)\r
591         {\r
592                 uint16 color;\r
593                 color=*current_line_buffer++;\r
594                 color<<=8;\r
595                 color|=*current_line_buffer++;\r
596                 \r
597                 chrm = (color & 0xF000) >> 12;    \r
598                 chrl = (color & 0x0F00) >> 8;\r
599                 y    = (color & 0x00FF);\r
600                                 \r
601                 uint16 red   =  ((((uint32)redcv[chrm][chrl])*y)>>11);\r
602                 uint16 green =  ((((uint32)greencv[chrm][chrl])*y)>>11);\r
603                 uint16 blue  =  ((((uint32)bluecv[chrm][chrl])*y)>>11);\r
604                 \r
605                 uint16 color2;\r
606                 color2=*current_line_buffer++;\r
607                 color2<<=8;\r
608                 color2|=*current_line_buffer++;\r
609                 \r
610                 chrm = (color2 & 0xF000) >> 12;    \r
611                 chrl = (color2 & 0x0F00) >> 8;\r
612                 y    = (color2 & 0x00FF);\r
613                                 \r
614                 uint16 red2   = ((((uint32)redcv[chrm][chrl])*y)>>11);\r
615                 uint16 green2 = ((((uint32)greencv[chrm][chrl])*y)>>11);\r
616                 uint16 blue2  = ((((uint32)bluecv[chrm][chrl])*y)>>11);\r
617                 \r
618                 red=(red+red2)>>1;\r
619                 green=(green+green2)>>1;\r
620                 blue=(blue+blue2)>>1;\r
621 \r
622                 *backbuffer++=(red<<10)|(green<<5)|blue;\r
623                 width--;\r
624         }\r
625 }\r
626 //////////////////////////////////////////////////////////////////////////////\r
627 //\r
628 //////////////////////////////////////////////////////////////////////////////\r
629 //\r
630 //\r
631 //\r
632 //\r
633 //\r
634 //\r
635 //////////////////////////////////////////////////////////////////////////////\r
636 void tom_render_24bpp_stretch_scanline(int16 *backbuffer)\r
637 {\r
638         uint16 width=tom_width;\r
639         uint8 *current_line_buffer=(uint8*)&tom_ram_8[0x1800];\r
640         \r
641         while (width)\r
642         {\r
643                 uint16 green=*current_line_buffer++;\r
644                 uint16 red=*current_line_buffer++;\r
645                 uint16 nc=*current_line_buffer++;\r
646                 uint16 blue=*current_line_buffer++;\r
647                 red>>=3;\r
648                 green>>=3;\r
649                 blue>>=3;\r
650                 *backbuffer++=(red<<10)|(green<<5)|blue;\r
651                 current_line_buffer+=4;\r
652                 width--;\r
653         }\r
654 }\r
655 //////////////////////////////////////////////////////////////////////////////\r
656 //\r
657 //////////////////////////////////////////////////////////////////////////////\r
658 //\r
659 //\r
660 //\r
661 //\r
662 //\r
663 //\r
664 //////////////////////////////////////////////////////////////////////////////\r
665 void tom_render_16bpp_direct_stretch_scanline(int16 *backbuffer)\r
666 {\r
667         uint16 width=tom_width;\r
668         uint8 *current_line_buffer=(uint8*)&tom_ram_8[0x1800];\r
669         \r
670         while (width)\r
671         {\r
672                 uint16 color=*current_line_buffer++;\r
673                 color<<=8;\r
674                 color|=*current_line_buffer++;\r
675                 color>>=1;\r
676                 *backbuffer++=color;\r
677                 current_line_buffer+=2;\r
678                 width--;\r
679         }\r
680 }\r
681 //////////////////////////////////////////////////////////////////////////////\r
682 //\r
683 //////////////////////////////////////////////////////////////////////////////\r
684 //\r
685 //\r
686 //\r
687 //\r
688 //\r
689 //\r
690 //////////////////////////////////////////////////////////////////////////////\r
691 void tom_render_16bpp_rgb_stretch_scanline(int16 *backbuffer)\r
692 {\r
693         uint16 width=tom_width;\r
694         uint8 *current_line_buffer=(uint8*)&tom_ram_8[0x1800];\r
695         \r
696         while (width)\r
697         {\r
698                 uint16 color1=*current_line_buffer++;\r
699                 color1<<=8;\r
700                 color1|=*current_line_buffer++;\r
701                 color1>>=1;\r
702                 uint16 color2=*current_line_buffer++;\r
703                 color2<<=8;\r
704                 color2|=*current_line_buffer++;\r
705                 color2>>=1;\r
706                 uint16 red=(((color1&0x7c00)>>10)+((color2&0x7c00)>>10))>>1;\r
707                 uint16 green=(((color1&0x00003e0)>>5)+((color2&0x00003e0)>>5))>>1;\r
708                 uint16 blue=(((color1&0x0000001f))+((color2&0x0000001f)))>>1;\r
709 \r
710                 color1=(red<<10)|(blue<<5)|green;\r
711                 *backbuffer++=color1;\r
712                 width--;\r
713         }\r
714 }\r
715 //////////////////////////////////////////////////////////////////////////////\r
716 //\r
717 //////////////////////////////////////////////////////////////////////////////\r
718 //\r
719 //\r
720 //\r
721 //\r
722 //\r
723 //\r
724 //////////////////////////////////////////////////////////////////////////////\r
725 void tom_exec_scanline(int16 * backbuffer, int32 scanline, int8 render)\r
726 {\r
727         UINT16 bg = GET16(BG);\r
728         tom_scanline = scanline;\r
729 \r
730         jaguar_word_write(0xF00004, jaguar_word_read(0xF00004) + 1);\r
731 \r
732         if (render)\r
733         {\r
734                 uint8 * current_line_buffer = (uint8 *)&tom_ram_8[0x1800];\r
735                 uint16 * current_line_buffer_16 = (uint16 *)current_line_buffer;\r
736 \r
737                 for(int i=0; i<tom_real_internal_width; i++)\r
738                         *current_line_buffer_16++ = bg;\r
739 \r
740                 op_process_list(backbuffer, scanline, render);\r
741                 \r
742                 (scanline_render[tom_getVideoMode()])(backbuffer);\r
743         }\r
744 }\r
745 //////////////////////////////////////////////////////////////////////////////\r
746 //\r
747 //////////////////////////////////////////////////////////////////////////////\r
748 //\r
749 //\r
750 //\r
751 //\r
752 //\r
753 //\r
754 //////////////////////////////////////////////////////////////////////////////\r
755 void tom_init(void)\r
756 {\r
757         op_init();\r
758         blitter_init();\r
759         pcm_init();\r
760 //      fprintf(log_get(),"tom_init()\n");\r
761         memory_malloc_secure((void **)&tom_ram_8, 0x4000, "tom ram");\r
762 //      tom_ram_16 = (uint16 *)tom_ram_8;\r
763 //      tom_ram_32 = (uint32 *)tom_ram_8;\r
764         tom_reset();\r
765         memcpy(scanline_render, scanline_render_normal, sizeof(scanline_render));\r
766         tom_calc_cry_rgb_mix_lut();\r
767 }\r
768 //////////////////////////////////////////////////////////////////////////////\r
769 //\r
770 //////////////////////////////////////////////////////////////////////////////\r
771 //\r
772 //\r
773 //\r
774 //\r
775 //\r
776 //\r
777 //////////////////////////////////////////////////////////////////////////////\r
778 uint32 tom_getHBlankWidthInPixels(void)\r
779 {\r
780         return hblankWidthInPixels;\r
781 }\r
782 //////////////////////////////////////////////////////////////////////////////\r
783 //\r
784 //////////////////////////////////////////////////////////////////////////////\r
785 //\r
786 //\r
787 //\r
788 //\r
789 //\r
790 //\r
791 //////////////////////////////////////////////////////////////////////////////\r
792 uint32 tom_getVideoModeWidth(void)\r
793 {\r
794         static uint16 onetime = 1;\r
795 \r
796 /*      uint16 vmode = SWAP_16(VMODE);\r
797         uint16 hdb = SWAP_16(HDB);\r
798         uint16 hde = SWAP_16(HDE);\r
799         uint16 hbb = SWAP_16(HBB);\r
800         uint16 hbe = SWAP_16(HBE);*/\r
801         uint16 vmode = GET16(VMODE);\r
802         uint16 hdb = GET16(HDB);\r
803         uint16 hde = GET16(HDE);\r
804         uint16 hbb = GET16(HBB);\r
805         uint16 hbe = GET16(HBE);\r
806 \r
807         int clock_cycles_per_pixel = ((vmode >> 9) & 0x07);\r
808 \r
809         uint32 width = 640;\r
810         switch (clock_cycles_per_pixel)\r
811         {\r
812         case 0: width = 640; break;\r
813         case 1: width = 640; break;\r
814         case 2: width = 448; break;\r
815         case 3: width = 320; break;\r
816         case 4: width = 256; break;\r
817         case 5: width = 256; break;\r
818         case 6: width = 256; break;\r
819         case 7: width = 320; break;\r
820 //      default: fprintf(log_get(),"%i \n",clock_cycles_per_pixel);\r
821         }\r
822         \r
823         if (jaguar_mainRom_crc32 == 0x3c7bfda8)\r
824         {\r
825                 if (width == 320)\r
826                         width += 80;\r
827                 if (width == 448)\r
828                         width -= 16;\r
829         }\r
830         if (hdb == 123)\r
831                 hblankWidthInPixels = 16;\r
832         else\r
833                 hblankWidthInPixels = 0;\r
834 \r
835 //      fprintf(log_get(),"hdb=%i hbe=%i\n",hdb,hbe);\r
836         return width;\r
837 }\r
838 //////////////////////////////////////////////////////////////////////////////\r
839 //\r
840 //////////////////////////////////////////////////////////////////////////////\r
841 //\r
842 //\r
843 //\r
844 //\r
845 //\r
846 //\r
847 //////////////////////////////////////////////////////////////////////////////\r
848 uint32 tom_getVideoModeHeight(void)\r
849 {\r
850 /*      uint16 vmode = SWAP_16(VMODE);\r
851         uint16 vdb = SWAP_16(VDB);\r
852         uint16 vde = SWAP_16(VDE);\r
853         uint16 vbb = SWAP_16(VBB);\r
854         uint16 vbe = SWAP_16(VBE);*/\r
855         uint16 vmode = GET16(VMODE);\r
856         uint16 vdb = GET16(VDB);\r
857         uint16 vde = GET16(VDE);\r
858         uint16 vbb = GET16(VBB);\r
859         uint16 vbe = GET16(VBE);\r
860         \r
861         if (vde == 65535)\r
862                 vde = vbb;\r
863         \r
864         uint32 screen_height = (vde/*-vdb*/) >> 1;\r
865         return 227;//WAS:screen_height);\r
866 }\r
867 //////////////////////////////////////////////////////////////////////////////\r
868 //\r
869 //////////////////////////////////////////////////////////////////////////////\r
870 //      \r
871 //\r
872 //\r
873 //\r
874 //\r
875 //\r
876 //////////////////////////////////////////////////////////////////////////////\r
877 void tom_reset(void)\r
878 {\r
879 //      fprintf(log_get(),"tom_reset()\n");\r
880         op_reset();\r
881         blitter_reset();\r
882         pcm_reset();\r
883 \r
884         memset(tom_ram_8, 0x00, 0x4000);\r
885 //      tom_ram_8[MEMCON1] = 0x18, tom_ram_8[MEMCON1+1] = 0x61;\r
886         SET16(MEMCON1, 0x1861);\r
887 //      tom_ram_8[MEMCON2] = 0x00, tom_ram_8[MEMCON2+1] = 0x00;\r
888         SET16(MEMCON2, 0x0000);\r
889 //      tom_ram_8[VMODE] = 0x06, tom_ram_8[VMODE+1] = 0xC1;\r
890         SET16(VMODE, 0x06C1);\r
891 //      tom_ram_8[VP] = (523 & 0xFF00) >> 8, tom_ram_8[VP+1] = 523 & 0x00FF; // 525-2\r
892         SET16(VP, 523);\r
893 //      tom_ram_8[HP] = SWAP_16(844);\r
894         SET16(HP, 844);\r
895 //      tom_ram_8[VS] = SWAP_16(523-6);\r
896         SET16(VS, 523 - 6);\r
897 //      tom_ram_8[VBB] = SWAP_16(434);\r
898         SET16(VBB, 434);\r
899 //      tom_ram_8[VBE] = SWAP_16(24);\r
900         SET16(VBE, 24);\r
901 //      tom_ram_8[HBB] = SWAP_16(689+0x400);\r
902         SET16(HBB, 689 + 0x400);\r
903 //      tom_ram_8[HBE] = SWAP_16(125);\r
904         SET16(HBE, 125);\r
905 \r
906 //      tom_ram_8[VDE] = SWAP_16(65535);\r
907         SET16(VDE, 65535);\r
908 //      tom_ram_8[VDB] = SWAP_16(28);\r
909         SET16(VDB, 28);\r
910 //      tom_ram_8[HDB] = SWAP_16(166);\r
911         SET16(HDB, 166);\r
912 //      tom_ram_8[HDE] = SWAP_16(65535);\r
913         SET16(HDE, 65535);\r
914 \r
915         tom_width = tom_real_internal_width = 0;\r
916         tom_height = 0;\r
917         tom_scanline = 0;\r
918         \r
919 //      hblankWidthInPixels = (tom_ram_8[HDB] << 8) | tom_ram_8[HDB+1];\r
920 //      hblankWidthInPixels >>= 1;\r
921         hblankWidthInPixels = (GET16(HDB)) >> 1;\r
922 \r
923         tom_puck_int_pending = 0;\r
924         tom_timer_int_pending = 0;\r
925         tom_object_int_pending = 0;\r
926         tom_gpu_int_pending = 0;\r
927         tom_video_int_pending = 0;\r
928 \r
929         tom_timer_prescaler = 0;\r
930         tom_timer_divider = 0;\r
931         tom_timer_counter = 0;\r
932         memcpy(scanline_render, scanline_render_normal, sizeof(scanline_render));\r
933\r
934 //////////////////////////////////////////////////////////////////////////////\r
935 //\r
936 //////////////////////////////////////////////////////////////////////////////\r
937 //\r
938 //\r
939 //\r
940 //\r
941 //\r
942 //\r
943 //////////////////////////////////////////////////////////////////////////////\r
944 void tom_done(void)\r
945 {\r
946 //      fprintf(log_get(),"tom: done()\n");\r
947         op_done();\r
948         pcm_done();\r
949         blitter_done();\r
950         fprintf(log_get(), "tom: resolution %ix%i %s\n", tom_getVideoModeWidth(), tom_getVideoModeHeight(),\r
951                 videoMode_to_str[tom_getVideoMode()]);\r
952 //      fprintf(log_get(),"\ntom: object processor:\n");\r
953 //      fprintf(log_get(),"tom: pointer to object list: 0x%.8x\n",op_get_list_pointer());\r
954 //      fprintf(log_get(),"tom: INT1=0x%.2x%.2x\n",tom_byte_read(0xf000e0),tom_byte_read(0xf000e1));\r
955         gpu_done();\r
956         dsp_done();\r
957         memory_free(tom_ram_8);\r
958 }\r
959 \r
960 //\r
961 // TOM byte access (read)\r
962 //\r
963 \r
964 unsigned tom_byte_read(unsigned int offset)\r
965 {\r
966         offset &= 0xFF3FFF;\r
967 \r
968 #ifdef TOM_DEBUG\r
969         fprintf(log_get(), "TOM: Reading byte at %06X\n", offset);\r
970 #endif\r
971 \r
972         if ((offset >= gpu_control_ram_base) && (offset < gpu_control_ram_base+0x20))\r
973                 return gpu_byte_read(offset);\r
974         else if ((offset >= gpu_work_ram_base) && (offset < gpu_work_ram_base+0x1000))\r
975                 return gpu_byte_read(offset);\r
976         else if ((offset >= 0xF00010) && (offset < 0xF00028))\r
977                 return op_byte_read(offset);\r
978         else if ((offset >= 0xF02200) && (offset < 0xF022A0))\r
979                 return blitter_byte_read(offset);\r
980         else if (offset == 0xF00050)\r
981                 return tom_timer_prescaler >> 8;\r
982         else if (offset == 0xF00051)\r
983                 return tom_timer_prescaler & 0xFF;\r
984         else if (offset == 0xF00052)\r
985                 return tom_timer_divider >> 8;\r
986         else if (offset == 0xF00053)\r
987                 return tom_timer_divider & 0xFF;\r
988 \r
989         return tom_ram_8[offset & 0x3FFF];\r
990 }\r
991 \r
992 //\r
993 // TOM word access (read)\r
994 //\r
995 \r
996 unsigned tom_word_read(unsigned int offset)\r
997 {\r
998         offset &= 0xFF3FFF;\r
999 #ifdef TOM_DEBUG\r
1000         fprintf(log_get(), "TOM: Reading word at %06X\n", offset);\r
1001 #endif\r
1002         if (offset == 0xF000E0)\r
1003         {\r
1004                 uint16 data = (tom_puck_int_pending << 4) | (tom_timer_int_pending << 3)\r
1005                         | (tom_object_int_pending << 2) | (tom_gpu_int_pending << 1)\r
1006                         | (tom_video_int_pending << 0);\r
1007                 //fprintf(log_get(),"tom: interrupt status is 0x%.4x \n",data);\r
1008                 return data;\r
1009         }\r
1010         else if (offset == 0xF00006)\r
1011                 return (tom_scanline << 1) + 1;\r
1012         else if ((offset >= gpu_control_ram_base) && (offset < gpu_control_ram_base+0x20))\r
1013                 return gpu_word_read(offset);\r
1014         else if ((offset >= gpu_work_ram_base) && (offset < gpu_work_ram_base+0x1000))\r
1015                 return gpu_word_read(offset);\r
1016         else if ((offset >= 0xF00010) && (offset < 0xF00028))\r
1017                 return op_word_read(offset);\r
1018         else if ((offset >= 0xF02200) && (offset < 0xF022A0))\r
1019                 return blitter_word_read(offset);\r
1020         else if (offset == 0xF00050)\r
1021                 return tom_timer_prescaler;\r
1022         else if (offset == 0xF00052)\r
1023                 return tom_timer_divider;\r
1024 \r
1025         offset &= 0x3FFF;\r
1026 \r
1027 //      uint16 data = tom_byte_read(offset);\r
1028 //      data <<= 8;\r
1029 //      data |= tom_byte_read(offset+1);\r
1030 \r
1031 //      return data;\r
1032         return (tom_byte_read(offset) << 8) | tom_byte_read(offset+1);\r
1033 }\r
1034 \r
1035 //\r
1036 // TOM byte access (write)\r
1037 //\r
1038 \r
1039 void tom_byte_write(unsigned offset, unsigned data)\r
1040 {\r
1041         offset &= 0xFF3FFF;\r
1042 \r
1043 #ifdef TOM_DEBUG\r
1044         fprintf(log_get(), "TOM: Writing byte %02X at %06X\n", data, offset);\r
1045 #endif\r
1046 \r
1047         if ((offset >= gpu_control_ram_base) && (offset < gpu_control_ram_base+0x20))\r
1048         {\r
1049                 gpu_byte_write(offset, data);\r
1050                 return;\r
1051         }\r
1052         else if ((offset >= gpu_work_ram_base) && (offset < gpu_work_ram_base+0x1000))\r
1053         {\r
1054                 gpu_byte_write(offset, data);\r
1055                 return;\r
1056         }\r
1057         else if ((offset >= 0xF00010) && (offset < 0xF00028))\r
1058         {\r
1059                 op_byte_write(offset, data);\r
1060                 return;\r
1061         }\r
1062         else if ((offset >= 0xF02200) && (offset < 0xF022A0))\r
1063         {\r
1064                 blitter_byte_write(offset, data);\r
1065                 return;\r
1066         }\r
1067         else if (offset == 0xF00050)\r
1068         {\r
1069                 tom_timer_prescaler = (tom_timer_prescaler & 0x00FF) | (data << 8);\r
1070                 tom_reset_timer();\r
1071                 return;\r
1072         }\r
1073         else if (offset == 0xF00051)\r
1074         {\r
1075                 tom_timer_prescaler = (tom_timer_prescaler & 0xFF00) | data;\r
1076                 tom_reset_timer();\r
1077                 return;\r
1078         }\r
1079         else if (offset == 0xF00052)\r
1080         {\r
1081                 tom_timer_divider = (tom_timer_divider & 0x00FF) | (data << 8);\r
1082                 tom_reset_timer();\r
1083                 return;\r
1084         }\r
1085         else if (offset == 0xF00053)\r
1086         {\r
1087                 tom_timer_divider = (tom_timer_divider & 0xFF00) | data;\r
1088                 tom_reset_timer();\r
1089                 return;\r
1090         }\r
1091 \r
1092         tom_ram_8[offset & 0x3FFF] = data;\r
1093 }\r
1094 \r
1095 //\r
1096 // TOM word access (write)\r
1097 //\r
1098 \r
1099 void tom_word_write(unsigned offset, unsigned data)\r
1100 {\r
1101         offset &= 0xFF3FFF;\r
1102 \r
1103 #ifdef TOM_DEBUG\r
1104         fprintf(log_get(), "TOM: Writing word %04X at %06X\n", data, offset);\r
1105 #endif\r
1106 \r
1107         if ((offset >= gpu_control_ram_base) && (offset < gpu_control_ram_base+0x20))\r
1108         {\r
1109                 gpu_word_write(offset, data);\r
1110                 return;\r
1111         }\r
1112         else if ((offset >= gpu_work_ram_base) && (offset < gpu_work_ram_base+0x1000))\r
1113         {\r
1114                 gpu_word_write(offset, data);\r
1115                 return;\r
1116         }\r
1117         else if ((offset >= 0xF00000) && (offset < 0xF00002))\r
1118         {\r
1119                 tom_byte_write(offset, (data>>8));\r
1120                 tom_byte_write(offset+1, (data&0xFF));\r
1121         }\r
1122         else if ((offset >= 0xF00010) && (offset < 0xF00028))\r
1123         {\r
1124                 op_word_write(offset, data);\r
1125                 return;\r
1126         }\r
1127         else if (offset == 0xF00050)\r
1128         {\r
1129                 tom_timer_prescaler = data;\r
1130                 tom_reset_timer();\r
1131                 return;\r
1132         }\r
1133         else if (offset == 0xF00052)\r
1134         {\r
1135                 tom_timer_divider = data;\r
1136                 tom_reset_timer();\r
1137                 return;\r
1138         }\r
1139         else if (offset == 0xF000E0)\r
1140         {\r
1141                 if (data & 0x0100)\r
1142                         tom_video_int_pending = 0;\r
1143                 if (data & 0x0200)\r
1144                         tom_gpu_int_pending = 0;\r
1145                 if (data & 0x0400)\r
1146                         tom_object_int_pending = 0;\r
1147                 if (data & 0x0800)\r
1148                         tom_timer_int_pending = 0;\r
1149                 if (data & 0x1000)\r
1150                         tom_puck_int_pending = 0;\r
1151         }\r
1152         else if ((offset >= 0xF02200) && (offset < 0xF022A0))\r
1153         {\r
1154                 blitter_word_write(offset, data);\r
1155                 return;\r
1156         }\r
1157 \r
1158         offset &= 0x3FFF;\r
1159         if (offset == 0x28)\r
1160                 objectp_running = 1;\r
1161 \r
1162         tom_byte_write(offset, data >> 8);\r
1163         tom_byte_write(offset+1,  data & 0xFF);\r
1164 \r
1165         // detect screen resolution changes\r
1166         if ((offset >= 0x28) && (offset <= 0x4F))\r
1167         {\r
1168                 int width, height;\r
1169                 tom_real_internal_width = width = tom_getVideoModeWidth();\r
1170                 height = tom_getVideoModeHeight();\r
1171                 if (width == 640)\r
1172                 {\r
1173                         memcpy(scanline_render, scanline_render_stretch, sizeof(scanline_render));\r
1174                         width = 320;\r
1175                 }\r
1176                 else\r
1177                 {\r
1178                         memcpy(scanline_render, scanline_render_normal, sizeof(scanline_render));\r
1179                 }\r
1180 \r
1181                 \r
1182                 if ((width != tom_width) || (height != tom_height))\r
1183                 {\r
1184                         ws_audio_done();\r
1185                 \r
1186                         static char window_title[256];\r
1187                         delete surface;\r
1188                         \r
1189                         tom_width = width;\r
1190                         tom_height = height;\r
1191                         Format format(16, 0x007C00, 0x00003E0, 0x0000001F);\r
1192                         surface = new Surface(tom_width, tom_height, format);\r
1193                         console.close();\r
1194                         sprintf(window_title, "Virtual Jaguar (%ix%i)", tom_width, tom_height);\r
1195                         console.open(window_title, width, tom_height, format);\r
1196 \r
1197                         ws_audio_init();\r
1198                         ws_audio_reset();\r
1199                 }\r
1200         }\r
1201 }\r
1202 //////////////////////////////////////////////////////////////////////////////\r
1203 //\r
1204 //////////////////////////////////////////////////////////////////////////////\r
1205 //\r
1206 //\r
1207 //\r
1208 //\r
1209 //\r
1210 //\r
1211 //////////////////////////////////////////////////////////////////////////////\r
1212 int tom_irq_enabled(int irq)\r
1213 {\r
1214         return jaguar_byte_read(0xF000E1) & (1 << irq);\r
1215 }\r
1216 //////////////////////////////////////////////////////////////////////////////\r
1217 //\r
1218 //////////////////////////////////////////////////////////////////////////////\r
1219 //\r
1220 //\r
1221 //\r
1222 //\r
1223 //\r
1224 //\r
1225 //////////////////////////////////////////////////////////////////////////////\r
1226 void tom_set_irq_latch(int irq, int enabled)\r
1227 {\r
1228         tom_ram_8[0xE0] = (tom_ram_8[0xE0] & (~(1<<irq))) | (enabled ? (1<<irq) : 0);\r
1229 }\r
1230 //////////////////////////////////////////////////////////////////////////////\r
1231 //\r
1232 //////////////////////////////////////////////////////////////////////////////\r
1233 //\r
1234 //\r
1235 //\r
1236 //\r
1237 //\r
1238 //\r
1239 //////////////////////////////////////////////////////////////////////////////\r
1240 uint16 tom_irq_control_reg(void)\r
1241 {\r
1242         return (tom_ram_8[0xE0] << 8) | tom_ram_8[0xE1];\r
1243 }\r
1244 //////////////////////////////////////////////////////////////////////////////\r
1245 //\r
1246 //////////////////////////////////////////////////////////////////////////////\r
1247 //\r
1248 //\r
1249 //\r
1250 //\r
1251 //\r
1252 //\r
1253 //////////////////////////////////////////////////////////////////////////////\r
1254 void tom_reset_timer(void)\r
1255 {\r
1256         if ((!tom_timer_prescaler) || (!tom_timer_divider))\r
1257                 tom_timer_counter = 0;\r
1258         else\r
1259                 tom_timer_counter = (1 + tom_timer_prescaler) * (1 + tom_timer_divider);\r
1260 //      fprintf(log_get(),"tom: reseting timer to 0x%.8x (%i)\n",tom_timer_counter,tom_timer_counter);\r
1261 }\r
1262 //////////////////////////////////////////////////////////////////////////////\r
1263 //\r
1264 //////////////////////////////////////////////////////////////////////////////\r
1265 //\r
1266 //\r
1267 //\r
1268 //\r
1269 //\r
1270 //\r
1271 //////////////////////////////////////////////////////////////////////////////\r
1272 void tom_pit_exec(uint32 cycles)\r
1273 {\r
1274         if (tom_timer_counter > 0)\r
1275         {\r
1276                 tom_timer_counter -= cycles;\r
1277 \r
1278                 if (tom_timer_counter <= 0)\r
1279                 {\r
1280                         tom_set_pending_timer_int();\r
1281                         gpu_set_irq_line(2, 1);\r
1282                         if ((tom_irq_enabled(IRQ_TIMER)) && (jaguar_interrupt_handler_is_valid(64)))\r
1283                         {\r
1284 //                              s68000interrupt(7, 64);\r
1285 //                              s68000flushInterrupts();\r
1286                                 m68k_set_irq(7);                                // Cause a 68000 NMI...\r
1287                         }\r
1288                         tom_reset_timer();\r
1289                 }\r
1290         }\r
1291 }\r