]> Shamusworld >> Repos - virtualjaguar/blob - src/tom.cpp
6ce648be972e13f082f359397daa087763f76e32
[virtualjaguar] / src / tom.cpp
1 //
2 // TOM Processing
3 //
4 // Originally by David Raingeard (cal2)
5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Cleanups and endian wrongness amelioration by James Hammons
7 // (C) 2010 Underground Software
8 //
9 // JLH = James Hammons <jlhamm@acm.org>
10 //
11 // Who  When        What
12 // ---  ----------  -------------------------------------------------------------
13 // JLH  01/16/2010  Created this log ;-)
14 // JLH  01/20/2011  Change rendering to RGBA, removed unnecessary code
15 //
16 // Note: Endian wrongness probably stems from the MAME origins of this emu and
17 //       the braindead way in which MAME used to handle memory. :-}
18 //
19 // Note: TOM has only a 16K memory space
20 //
21 //      ------------------------------------------------------------
22 //      TOM REGISTERS (Mapped by Aaron Giles)
23 //      ------------------------------------------------------------
24 //      F00000-F0FFFF   R/W   xxxxxxxx xxxxxxxx   Internal Registers
25 //      F00000          R/W   -x-xx--- xxxxxxxx   MEMCON1 - memory config reg 1
26 //                            -x------ --------      (CPU32 - is the CPU 32bits?)
27 //                            ---xx--- --------      (IOSPEED - external I/O clock cycles)
28 //                            -------- x-------      (FASTROM - reduces ROM clock cycles)
29 //                            -------- -xx-----      (DRAMSPEED - sets RAM clock cycles)
30 //                            -------- ---xx---      (ROMSPEED - sets ROM clock cycles)
31 //                            -------- -----xx-      (ROMWIDTH - sets width of ROM: 8,16,32,64 bits)
32 //                            -------- -------x      (ROMHI - controls ROM mapping)
33 //      F00002          R/W   --xxxxxx xxxxxxxx   MEMCON2 - memory config reg 2
34 //                            --x----- --------      (HILO - image display bit order)
35 //                            ---x---- --------      (BIGEND - big endian addressing?)
36 //                            ----xxxx --------      (REFRATE - DRAM refresh rate)
37 //                            -------- xx------      (DWIDTH1 - DRAM1 width: 8,16,32,64 bits)
38 //                            -------- --xx----      (COLS1 - DRAM1 columns: 256,512,1024,2048)
39 //                            -------- ----xx--      (DWIDTH0 - DRAM0 width: 8,16,32,64 bits)
40 //                            -------- ------xx      (COLS0 - DRAM0 columns: 256,512,1024,2048)
41 //      F00004          R/W   -----xxx xxxxxxxx   HC - horizontal count
42 //                            -----x-- --------      (which half of the display)
43 //                            ------xx xxxxxxxx      (10-bit counter)
44 //      F00006          R/W   ----xxxx xxxxxxxx   VC - vertical count
45 //                            ----x--- --------      (which field is being generated)
46 //                            -----xxx xxxxxxxx      (11-bit counter)
47 //      F00008          R     -----xxx xxxxxxxx   LPH - light pen horizontal position
48 //      F0000A          R     -----xxx xxxxxxxx   LPV - light pen vertical position
49 //      F00010-F00017   R     xxxxxxxx xxxxxxxx   OB - current object code from the graphics processor
50 //      F00020-F00023     W   xxxxxxxx xxxxxxxx   OLP - start of the object list
51 //      F00026            W   -------- -------x   OBF - object processor flag
52 //      F00028            W   ----xxxx xxxxxxxx   VMODE - video mode
53 //                        W   ----xxx- --------      (PWIDTH1-8 - width of pixel in video clock cycles)
54 //                        W   -------x --------      (VARMOD - enable variable color resolution)
55 //                        W   -------- x-------      (BGEN - clear line buffer to BG color)
56 //                        W   -------- -x------      (CSYNC - enable composite sync on VSYNC)
57 //                        W   -------- --x-----      (BINC - local border color if INCEN)
58 //                        W   -------- ---x----      (INCEN - encrustation enable)
59 //                        W   -------- ----x---      (GENLOCK - enable genlock)
60 //                        W   -------- -----xx-      (MODE - CRY16,RGB24,DIRECT16,RGB16)
61 //                        W   -------- -------x      (VIDEN - enables video)
62 //      F0002A            W   xxxxxxxx xxxxxxxx   BORD1 - border color (red/green)
63 //      F0002C            W   -------- xxxxxxxx   BORD2 - border color (blue)
64 //      F0002E            W   ------xx xxxxxxxx   HP - horizontal period
65 //      F00030            W   -----xxx xxxxxxxx   HBB - horizontal blanking begin
66 //      F00032            W   -----xxx xxxxxxxx   HBE - horizontal blanking end
67 //      F00034            W   -----xxx xxxxxxxx   HSYNC - horizontal sync
68 //      F00036            W   ------xx xxxxxxxx   HVS - horizontal vertical sync
69 //      F00038            W   -----xxx xxxxxxxx   HDB1 - horizontal display begin 1
70 //      F0003A            W   -----xxx xxxxxxxx   HDB2 - horizontal display begin 2
71 //      F0003C            W   -----xxx xxxxxxxx   HDE - horizontal display end
72 //      F0003E            W   -----xxx xxxxxxxx   VP - vertical period
73 //      F00040            W   -----xxx xxxxxxxx   VBB - vertical blanking begin
74 //      F00042            W   -----xxx xxxxxxxx   VBE - vertical blanking end
75 //      F00044            W   -----xxx xxxxxxxx   VS - vertical sync
76 //      F00046            W   -----xxx xxxxxxxx   VDB - vertical display begin
77 //      F00048            W   -----xxx xxxxxxxx   VDE - vertical display end
78 //      F0004A            W   -----xxx xxxxxxxx   VEB - vertical equalization begin
79 //      F0004C            W   -----xxx xxxxxxxx   VEE - vertical equalization end
80 //      F0004E            W   -----xxx xxxxxxxx   VI - vertical interrupt
81 //      F00050            W   xxxxxxxx xxxxxxxx   PIT0 - programmable interrupt timer 0
82 //      F00052            W   xxxxxxxx xxxxxxxx   PIT1 - programmable interrupt timer 1
83 //      F00054            W   ------xx xxxxxxxx   HEQ - horizontal equalization end
84 //      F00058            W   xxxxxxxx xxxxxxxx   BG - background color
85 //      F000E0          R/W   ---xxxxx ---xxxxx   INT1 - CPU interrupt control register
86 //                            ---x---- --------      (C_JERCLR - clear pending Jerry ints)
87 //                            ----x--- --------      (C_PITCLR - clear pending PIT ints)
88 //                            -----x-- --------      (C_OPCLR - clear pending object processor ints)
89 //                            ------x- --------      (C_GPUCLR - clear pending graphics processor ints)
90 //                            -------x --------      (C_VIDCLR - clear pending video timebase ints)
91 //                            -------- ---x----      (C_JERENA - enable Jerry ints)
92 //                            -------- ----x---      (C_PITENA - enable PIT ints)
93 //                            -------- -----x--      (C_OPENA - enable object processor ints)
94 //                            -------- ------x-      (C_GPUENA - enable graphics processor ints)
95 //                            -------- -------x      (C_VIDENA - enable video timebase ints)
96 //      F000E2            W   -------- --------   INT2 - CPU interrupt resume register
97 //      F00400-F005FF   R/W   xxxxxxxx xxxxxxxx   CLUT - color lookup table A
98 //      F00600-F007FF   R/W   xxxxxxxx xxxxxxxx   CLUT - color lookup table B
99 //      F00800-F00D9F   R/W   xxxxxxxx xxxxxxxx   LBUF - line buffer A
100 //      F01000-F0159F   R/W   xxxxxxxx xxxxxxxx   LBUF - line buffer B
101 //      F01800-F01D9F   R/W   xxxxxxxx xxxxxxxx   LBUF - line buffer currently selected
102 //      ------------------------------------------------------------
103 //      F02000-F021FF   R/W   xxxxxxxx xxxxxxxx   GPU control registers
104 //      F02100          R/W   xxxxxxxx xxxxxxxx   G_FLAGS - GPU flags register
105 //                      R/W   x------- --------      (DMAEN - DMA enable)
106 //                      R/W   -x------ --------      (REGPAGE - register page)
107 //                        W   --x----- --------      (G_BLITCLR - clear blitter interrupt)
108 //                        W   ---x---- --------      (G_OPCLR - clear object processor int)
109 //                        W   ----x--- --------      (G_PITCLR - clear PIT interrupt)
110 //                        W   -----x-- --------      (G_JERCLR - clear Jerry interrupt)
111 //                        W   ------x- --------      (G_CPUCLR - clear CPU interrupt)
112 //                      R/W   -------x --------      (G_BLITENA - enable blitter interrupt)
113 //                      R/W   -------- x-------      (G_OPENA - enable object processor int)
114 //                      R/W   -------- -x------      (G_PITENA - enable PIT interrupt)
115 //                      R/W   -------- --x-----      (G_JERENA - enable Jerry interrupt)
116 //                      R/W   -------- ---x----      (G_CPUENA - enable CPU interrupt)
117 //                      R/W   -------- ----x---      (IMASK - interrupt mask)
118 //                      R/W   -------- -----x--      (NEGA_FLAG - ALU negative)
119 //                      R/W   -------- ------x-      (CARRY_FLAG - ALU carry)
120 //                      R/W   -------- -------x      (ZERO_FLAG - ALU zero)
121 //      F02104            W   -------- ----xxxx   G_MTXC - matrix control register
122 //                        W   -------- ----x---      (MATCOL - column/row major)
123 //                        W   -------- -----xxx      (MATRIX3-15 - matrix width)
124 //      F02108            W   ----xxxx xxxxxx--   G_MTXA - matrix address register
125 //      F0210C            W   -------- -----xxx   G_END - data organization register
126 //                        W   -------- -----x--      (BIG_INST - big endian instruction fetch)
127 //                        W   -------- ------x-      (BIG_PIX - big endian pixels)
128 //                        W   -------- -------x      (BIG_IO - big endian I/O)
129 //      F02110          R/W   xxxxxxxx xxxxxxxx   G_PC - GPU program counter
130 //      F02114          R/W   xxxxxxxx xx-xxxxx   G_CTRL - GPU control/status register
131 //                      R     xxxx---- --------      (VERSION - GPU version code)
132 //                      R/W   ----x--- --------      (BUS_HOG - hog the bus!)
133 //                      R/W   -----x-- --------      (G_BLITLAT - blitter interrupt latch)
134 //                      R/W   ------x- --------      (G_OPLAT - object processor int latch)
135 //                      R/W   -------x --------      (G_PITLAT - PIT interrupt latch)
136 //                      R/W   -------- x-------      (G_JERLAT - Jerry interrupt latch)
137 //                      R/W   -------- -x------      (G_CPULAT - CPU interrupt latch)
138 //                      R/W   -------- ---x----      (SINGLE_GO - single step one instruction)
139 //                      R/W   -------- ----x---      (SINGLE_STEP - single step mode)
140 //                      R/W   -------- -----x--      (FORCEINT0 - cause interrupt 0 on GPU)
141 //                      R/W   -------- ------x-      (CPUINT - send GPU interrupt to CPU)
142 //                      R/W   -------- -------x      (GPUGO - enable GPU execution)
143 //      F02118-F0211B   R/W   xxxxxxxx xxxxxxxx   G_HIDATA - high data register
144 //      F0211C-F0211F   R     xxxxxxxx xxxxxxxx   G_REMAIN - divide unit remainder
145 //      F0211C            W   -------- -------x   G_DIVCTRL - divide unit control
146 //                        W   -------- -------x      (DIV_OFFSET - 1=16.16 divide, 0=32-bit divide)
147 //      ------------------------------------------------------------
148 //      BLITTER REGISTERS
149 //      ------------------------------------------------------------
150 //      F02200-F022FF   R/W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   Blitter registers
151 //      F02200            W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   A1_BASE - A1 base register
152 //      F02204            W   -------- ---xxxxx -xxxxxxx xxxxx-xx   A1_FLAGS - A1 flags register
153 //                        W   -------- ---x---- -------- --------      (YSIGNSUB - invert sign of Y delta)
154 //                        W   -------- ----x--- -------- --------      (XSIGNSUB - invert sign of X delta)
155 //                        W   -------- -----x-- -------- --------      (Y add control)
156 //                        W   -------- ------xx -------- --------      (X add control)
157 //                        W   -------- -------- -xxxxxx- --------      (width in 6-bit floating point)
158 //                        W   -------- -------- -------x xx------      (ZOFFS1-6 - Z data offset)
159 //                        W   -------- -------- -------- --xxx---      (PIXEL - pixel size)
160 //                        W   -------- -------- -------- ------xx      (PITCH1-4 - data phrase pitch)
161 //      F02208            W   -xxxxxxx xxxxxxxx -xxxxxxx xxxxxxxx   A1_CLIP - A1 clipping size
162 //                        W   -xxxxxxx xxxxxxxx -------- --------      (height)
163 //                        W   -------- -------- -xxxxxxx xxxxxxxx      (width)
164 //      F0220C          R/W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   A1_PIXEL - A1 pixel pointer
165 //                      R/W   xxxxxxxx xxxxxxxx -------- --------      (Y pixel value)
166 //                      R/W   -------- -------- xxxxxxxx xxxxxxxx      (X pixel value)
167 //      F02210            W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   A1_STEP - A1 step value
168 //                        W   xxxxxxxx xxxxxxxx -------- --------      (Y step value)
169 //                        W   -------- -------- xxxxxxxx xxxxxxxx      (X step value)
170 //      F02214            W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   A1_FSTEP - A1 step fraction value
171 //                        W   xxxxxxxx xxxxxxxx -------- --------      (Y step fraction value)
172 //                        W   -------- -------- xxxxxxxx xxxxxxxx      (X step fraction value)
173 //      F02218          R/W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   A1_FPIXEL - A1 pixel pointer fraction
174 //                      R/W   xxxxxxxx xxxxxxxx -------- --------      (Y pixel fraction value)
175 //                      R/W   -------- -------- xxxxxxxx xxxxxxxx      (X pixel fraction value)
176 //      F0221C            W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   A1_INC - A1 increment
177 //                        W   xxxxxxxx xxxxxxxx -------- --------      (Y increment)
178 //                        W   -------- -------- xxxxxxxx xxxxxxxx      (X increment)
179 //      F02220            W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   A1_FINC - A1 increment fraction
180 //                        W   xxxxxxxx xxxxxxxx -------- --------      (Y increment fraction)
181 //                        W   -------- -------- xxxxxxxx xxxxxxxx      (X increment fraction)
182 //      F02224            W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   A2_BASE - A2 base register
183 //      F02228            W   -------- ---xxxxx -xxxxxxx xxxxx-xx   A2_FLAGS - A2 flags register
184 //                        W   -------- ---x---- -------- --------      (YSIGNSUB - invert sign of Y delta)
185 //                        W   -------- ----x--- -------- --------      (XSIGNSUB - invert sign of X delta)
186 //                        W   -------- -----x-- -------- --------      (Y add control)
187 //                        W   -------- ------xx -------- --------      (X add control)
188 //                        W   -------- -------- -xxxxxx- --------      (width in 6-bit floating point)
189 //                        W   -------- -------- -------x xx------      (ZOFFS1-6 - Z data offset)
190 //                        W   -------- -------- -------- --xxx---      (PIXEL - pixel size)
191 //                        W   -------- -------- -------- ------xx      (PITCH1-4 - data phrase pitch)
192 //      F0222C            W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   A2_MASK - A2 window mask
193 //      F02230          R/W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   A2_PIXEL - A2 pixel pointer
194 //                      R/W   xxxxxxxx xxxxxxxx -------- --------      (Y pixel value)
195 //                      R/W   -------- -------- xxxxxxxx xxxxxxxx      (X pixel value)
196 //      F02234            W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   A2_STEP - A2 step value
197 //                        W   xxxxxxxx xxxxxxxx -------- --------      (Y step value)
198 //                        W   -------- -------- xxxxxxxx xxxxxxxx      (X step value)
199 //      F02238            W   -xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   B_CMD - command register
200 //                        W   -x------ -------- -------- --------      (SRCSHADE - modify source intensity)
201 //                        W   --x----- -------- -------- --------      (BUSHI - hi priority bus)
202 //                        W   ---x---- -------- -------- --------      (BKGWREN - writeback destination)
203 //                        W   ----x--- -------- -------- --------      (DCOMPEN - write inhibit from data comparator)
204 //                        W   -----x-- -------- -------- --------      (BCOMPEN - write inhibit from bit coparator)
205 //                        W   ------x- -------- -------- --------      (CMPDST - compare dest instead of src)
206 //                        W   -------x xxx----- -------- --------      (logical operation)
207 //                        W   -------- ---xxx-- -------- --------      (ZMODE - Z comparator mode)
208 //                        W   -------- ------x- -------- --------      (ADDDSEL - select sum of src & dst)
209 //                        W   -------- -------x -------- --------      (PATDSEL - select pattern data)
210 //                        W   -------- -------- x------- --------      (TOPNEN - enable carry into top intensity nibble)
211 //                        W   -------- -------- -x------ --------      (TOPBEN - enable carry into top intensity byte)
212 //                        W   -------- -------- --x----- --------      (ZBUFF - enable Z updates in inner loop)
213 //                        W   -------- -------- ---x---- --------      (GOURD - enable gouraud shading in inner loop)
214 //                        W   -------- -------- ----x--- --------      (DSTA2 - reverses A2/A1 roles)
215 //                        W   -------- -------- -----x-- --------      (UPDA2 - add A2 step to A2 in outer loop)
216 //                        W   -------- -------- ------x- --------      (UPDA1 - add A1 step to A1 in outer loop)
217 //                        W   -------- -------- -------x --------      (UPDA1F - add A1 fraction step to A1 in outer loop)
218 //                        W   -------- -------- -------- x-------      (diagnostic use)
219 //                        W   -------- -------- -------- -x------      (CLIP_A1 - clip A1 to window)
220 //                        W   -------- -------- -------- --x-----      (DSTWRZ - enable dest Z write in inner loop)
221 //                        W   -------- -------- -------- ---x----      (DSTENZ - enable dest Z read in inner loop)
222 //                        W   -------- -------- -------- ----x---      (DSTEN - enables dest data read in inner loop)
223 //                        W   -------- -------- -------- -----x--      (SRCENX - enable extra src read at start of inner)
224 //                        W   -------- -------- -------- ------x-      (SRCENZ - enables source Z read in inner loop)
225 //                        W   -------- -------- -------- -------x      (SRCEN - enables source data read in inner loop)
226 //      F02238          R     xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   B_CMD - status register
227 //                      R     xxxxxxxx xxxxxxxx -------- --------      (inner count)
228 //                      R     -------- -------- xxxxxxxx xxxxxx--      (diagnostics)
229 //                      R     -------- -------- -------- ------x-      (STOPPED - when stopped in collision detect)
230 //                      R     -------- -------- -------- -------x      (IDLE - when idle)
231 //      F0223C            W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   B_COUNT - counters register
232 //                        W   xxxxxxxx xxxxxxxx -------- --------      (outer loop count)
233 //                        W   -------- -------- xxxxxxxx xxxxxxxx      (inner loop count)
234 //      F02240-F02247     W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   B_SRCD - source data register
235 //      F02248-F0224F     W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   B_DSTD - destination data register
236 //      F02250-F02257     W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   B_DSTZ - destination Z register
237 //      F02258-F0225F     W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   B_SRCZ1 - source Z register 1
238 //      F02260-F02267     W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   B_SRCZ2 - source Z register 2
239 //      F02268-F0226F     W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   B_PATD - pattern data register
240 //      F02270            W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   B_IINC - intensity increment
241 //      F02274            W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   B_ZINC - Z increment
242 //      F02278            W   -------- -------- -------- -----xxx   B_STOP - collision control
243 //                        W   -------- -------- -------- -----x--      (STOPEN - enable blitter collision stops)
244 //                        W   -------- -------- -------- ------x-      (ABORT - abort after stop)
245 //                        W   -------- -------- -------- -------x      (RESUME - resume after stop)
246 //      F0227C            W   -------- xxxxxxxx xxxxxxxx xxxxxxxx   B_I3 - intensity 3
247 //      F02280            W   -------- xxxxxxxx xxxxxxxx xxxxxxxx   B_I2 - intensity 2
248 //      F02284            W   -------- xxxxxxxx xxxxxxxx xxxxxxxx   B_I1 - intensity 1
249 //      F02288            W   -------- xxxxxxxx xxxxxxxx xxxxxxxx   B_I0 - intensity 0
250 //      F0228C            W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   B_Z3 - Z3
251 //      F02290            W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   B_Z2 - Z2
252 //      F02294            W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   B_Z1 - Z1
253 //      F02298            W   xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx   B_Z0 - Z0
254 //      ------------------------------------------------------------
255
256 #include "tom.h"
257
258 #include <string.h>                                                             // For memset()
259 #include <stdlib.h>                                                             // For rand()
260 #include "blitter.h"
261 #include "cry2rgb.h"
262 #include "event.h"
263 #include "gpu.h"
264 #include "jaguar.h"
265 #include "log.h"
266 #include "m68000/m68kinterface.h"
267 //#include "memory.h"
268 #include "op.h"
269 #include "settings.h"
270
271 #define NEW_TIMER_SYSTEM
272
273 // TOM registers (offset from $F00000)
274
275 #define MEMCON1         0x00
276 #define MEMCON2         0x02
277 #define HC                      0x04
278 #define VC                      0x06
279 #define OLP                     0x20            // Object list pointer
280 #define OBF                     0x26            // Object processor flag
281 #define VMODE           0x28
282 #define   MODE          0x0006          // Line buffer to video generator mode
283 #define   BGEN          0x0080          // Background enable (CRY & RGB16 only)
284 #define   VARMOD        0x0100          // Mixed CRY/RGB16 mode (only works in MODE 0!)
285 #define   PWIDTH        0x0E00          // Pixel width in video clock cycles (value written + 1)
286 #define BORD1           0x2A            // Border green/red values (8 BPP)
287 #define BORD2           0x2C            // Border blue value (8 BPP)
288 #define HP                      0x2E            // Values range from 1 - 1024 (value written + 1)
289 #define HBB                     0x30            // Horizontal blank begin
290 #define HBE                     0x32
291 #define HS                      0x34            // Horizontal sync
292 #define HVS                     0x36            // Horizontal vertical sync
293 #define HDB1            0x38            // Horizontal display begin 1
294 #define HDB2            0x3A
295 #define HDE                     0x3C
296 #define VP                      0x3E            // Value ranges from 1 - 2048 (value written + 1)
297 #define VBB                     0x40            // Vertical blank begin
298 #define VBE                     0x42
299 #define VS                      0x44            // Vertical sync
300 #define VDB                     0x46            // Vertical display begin
301 #define VDE                     0x48
302 #define VEB                     0x4A            // Vertical equalization begin
303 #define VEE                     0x4C            // Vertical equalization end
304 #define VI                      0x4E            // Vertical interrupt
305 #define PIT0            0x50
306 #define PIT1            0x52
307 #define HEQ                     0x54            // Horizontal equalization end
308 #define BG                      0x58            // Background color
309 #define INT1            0xE0
310 #define INT2            0xE2
311
312 //NOTE: These arbitrary cutoffs are NOT taken into account for PAL jaguar screens. !!! FIX !!! [DONE]
313
314 // Arbitrary video cutoff values (i.e., first/last visible spots on a TV, in HC ticks)
315 // Also note that VC is in *half* lines, i.e. divide by 2 to get the scanline
316 /*#define LEFT_VISIBLE_HC                       208
317 #define RIGHT_VISIBLE_HC                1528//*/
318 // These were right for Rayman, but that one is offset on a real TV too.
319 //#define LEFT_VISIBLE_HC                       208
320 //#define RIGHT_VISIBLE_HC              1488
321 // This is more like a real TV display...
322 //#define LEFT_VISIBLE_HC                       (208 - 32)
323 //#define RIGHT_VISIBLE_HC              (1488 - 32)
324 // Split the difference? (Seems to be OK for the most part...)
325
326 // (-10 +10)*4 is for opening up the display by 16 pixels (may go to 20). Need to change VIRTUAL_SCREEN_WIDTH to match this as well (went from 320 to 340; this is 4 HCs per one of those pixels).
327 //NB: Went back to 330. May shrink more. :-)
328 //#define LEFT_VISIBLE_HC                       (208 - 16 - (8 * 4))
329 //#define LEFT_VISIBLE_HC                       (208 - 16 - (3 * 4))
330 #define LEFT_VISIBLE_HC                 (208 - 16 - (1 * 4))
331 //#define RIGHT_VISIBLE_HC              (1488 - 16 + (10 * 4))
332 #define RIGHT_VISIBLE_HC                (LEFT_VISIBLE_HC + (VIRTUAL_SCREEN_WIDTH * 4))
333 //#define TOP_VISIBLE_VC                25
334 //#define BOTTOM_VISIBLE_VC             503
335 #define TOP_VISIBLE_VC                  31
336 #define BOTTOM_VISIBLE_VC               511
337
338 //Are these PAL horizontals correct?
339 //They seem to be for the most part, but there are some games that seem to be
340 //shifted over to the right from this "window".
341 //#define LEFT_VISIBLE_HC_PAL           (208 - 16 - (4 * 4))
342 //#define LEFT_VISIBLE_HC_PAL           (208 - 16 - (-1 * 4))
343 #define LEFT_VISIBLE_HC_PAL             (208 - 16 - (-3 * 4))
344 //#define RIGHT_VISIBLE_HC_PAL  (1488 - 16 + (10 * 4))
345 #define RIGHT_VISIBLE_HC_PAL    (LEFT_VISIBLE_HC_PAL + (VIRTUAL_SCREEN_WIDTH * 4))
346 #define TOP_VISIBLE_VC_PAL              67
347 #define BOTTOM_VISIBLE_VC_PAL   579
348
349 //This can be defined in the makefile as well...
350 //(It's easier to do it here, though...)
351 //#define TOM_DEBUG
352
353 uint8_t tomRam8[0x4000];
354 uint32_t tomWidth, tomHeight;
355 uint32_t tomTimerPrescaler;
356 uint32_t tomTimerDivider;
357 int32_t tomTimerCounter;
358 uint16_t tom_jerry_int_pending, tom_timer_int_pending, tom_object_int_pending,
359         tom_gpu_int_pending, tom_video_int_pending;
360
361 // These are set by the "user" of the Jaguar core lib, since these are
362 // OS/system dependent.
363 uint32_t * screenBuffer;
364 uint32_t screenPitch;
365
366 static const char * videoMode_to_str[8] =
367         { "16 BPP CRY", "24 BPP RGB", "16 BPP DIRECT", "16 BPP RGB",
368           "Mixed mode", "24 BPP RGB", "16 BPP DIRECT", "16 BPP RGB" };
369
370 typedef void (render_xxx_scanline_fn)(uint32_t *);
371
372 // Private function prototypes
373
374 void tom_render_16bpp_cry_scanline(uint32_t * backbuffer);
375 void tom_render_24bpp_scanline(uint32_t * backbuffer);
376 void tom_render_16bpp_direct_scanline(uint32_t * backbuffer);
377 void tom_render_16bpp_rgb_scanline(uint32_t * backbuffer);
378 void tom_render_16bpp_cry_rgb_mix_scanline(uint32_t * backbuffer);
379
380 //render_xxx_scanline_fn * scanline_render_normal[] =
381 render_xxx_scanline_fn * scanline_render[] =
382 {
383         tom_render_16bpp_cry_scanline,
384         tom_render_24bpp_scanline,
385         tom_render_16bpp_direct_scanline,
386         tom_render_16bpp_rgb_scanline,
387         tom_render_16bpp_cry_rgb_mix_scanline,
388         tom_render_24bpp_scanline,
389         tom_render_16bpp_direct_scanline,
390         tom_render_16bpp_rgb_scanline
391 };
392
393 // Screen info for various games [PAL]...
394 /*
395 BIOS
396 TOM: Horizontal Period written by M68K: 850 (+1*2 = 1702)
397 TOM: Horizontal Blank Begin written by M68K: 1711
398 TOM: Horizontal Blank End written by M68K: 158
399 TOM: Horizontal Display End written by M68K: 1696
400 TOM: Horizontal Display Begin 1 written by M68K: 166
401 TOM: Vertical Period written by M68K: 623 (non-interlaced)
402 TOM: Vertical Blank End written by M68K: 34
403 TOM: Vertical Display Begin written by M68K: 46
404 TOM: Vertical Display End written by M68K: 526
405 TOM: Vertical Blank Begin written by M68K: 600
406 TOM: Vertical Sync written by M68K: 618
407 TOM: Horizontal Display End written by M68K: 1665
408 TOM: Horizontal Display Begin 1 written by M68K: 203
409 TOM: Vertical Display Begin written by M68K: 38
410 TOM: Vertical Display End written by M68K: 518
411 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 151)
412 TOM: Horizontal Display End written by M68K: 1713
413 TOM: Horizontal Display Begin 1 written by M68K: 157
414 TOM: Vertical Display Begin written by M68K: 35
415 TOM: Vertical Display End written by M68K: 2047
416 Horizontal range: 157 - 1713 (width: 1557 / 4 = 389.25, / 5 = 315.4)
417
418 Asteroid
419 TOM: Horizontal Period written by M68K: 845 (+1*2 = 1692)
420 TOM: Horizontal Blank Begin written by M68K: 1700
421 TOM: Horizontal Blank End written by M68K: 122
422 TOM: Horizontal Display End written by M68K: 1600
423 TOM: Horizontal Display Begin 1 written by M68K: 268
424 TOM: Vertical Period written by M68K: 523 (non-interlaced)
425 TOM: Vertical Blank End written by M68K: 40
426 TOM: Vertical Display Begin written by M68K: 44
427 TOM: Vertical Display End written by M68K: 492
428 TOM: Vertical Blank Begin written by M68K: 532
429 TOM: Vertical Sync written by M68K: 513
430 TOM: Video Mode written by M68K: 04C7. PWIDTH = 3, MODE = 16 BPP RGB, flags: BGEN (VC = 461)
431
432 Rayman
433 TOM: Horizontal Display End written by M68K: 1713
434 TOM: Horizontal Display Begin 1 written by M68K: 157
435 TOM: Vertical Display Begin written by M68K: 35
436 TOM: Vertical Display End written by M68K: 2047
437 TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 89)
438 TOM: Horizontal Display Begin 1 written by M68K: 208
439 TOM: Horizontal Display End written by M68K: 1662
440 TOM: Vertical Display Begin written by M68K: 100
441 TOM: Vertical Display End written by M68K: 2047
442 TOM: Video Mode written by M68K: 07C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN VARMOD (VC = 205)
443 Horizontal range: 208 - 1662 (width: 1455 / 4 = 363.5)
444
445 Alien vs Predator
446 TOM: Vertical Display Begin written by M68K: 96
447 TOM: Vertical Display End written by M68K: 2047
448 TOM: Horizontal Display Begin 1 written by M68K: 239
449 TOM: Horizontal Display End written by M68K: 1692
450 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 378)
451 TOM: Vertical Display Begin written by M68K: 44
452 TOM: Vertical Display End written by M68K: 2047
453 TOM: Horizontal Display Begin 1 written by M68K: 239
454 TOM: Horizontal Display End written by M68K: 1692
455 TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 559)
456 TOM: Vertical Display Begin written by M68K: 84
457 TOM: Vertical Display End written by M68K: 2047
458 TOM: Horizontal Display Begin 1 written by M68K: 239
459 TOM: Horizontal Display End written by M68K: 1692
460 TOM: Vertical Display Begin written by M68K: 44
461 TOM: Vertical Display End written by M68K: 2047
462 TOM: Horizontal Display Begin 1 written by M68K: 239
463 TOM: Horizontal Display End written by M68K: 1692
464 Horizontal range: 239 - 1692 (width: 1454 / 4 = 363.5)
465
466 */
467
468 // Screen info for various games [NTSC]...
469 /*
470 Doom
471 TOM: Horizontal Display End written by M68K: 1727
472 TOM: Horizontal Display Begin 1 written by M68K: 123
473 TOM: Vertical Display Begin written by M68K: 25
474 TOM: Vertical Display End written by M68K: 2047
475 TOM: Video Mode written by M68K: 0EC1. PWIDTH = 8, MODE = 16 BPP CRY, flags: BGEN (VC = 5)
476 Also does PWIDTH = 4...
477 Vertical resolution: 238 lines
478
479 Rayman
480 TOM: Horizontal Display End written by M68K: 1727
481 TOM: Horizontal Display Begin 1 written by M68K: 123
482 TOM: Vertical Display Begin written by M68K: 25
483 TOM: Vertical Display End written by M68K: 2047
484 TOM: Vertical Interrupt written by M68K: 507
485 TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 92)
486 TOM: Horizontal Display Begin 1 written by M68K: 208
487 TOM: Horizontal Display End written by M68K: 1670
488 Display starts at 31, then 52!
489 Vertical resolution: 238 lines
490
491 Atari Karts
492 TOM: Horizontal Display End written by M68K: 1727
493 TOM: Horizontal Display Begin 1 written by M68K: 123
494 TOM: Vertical Display Begin written by M68K: 25
495 TOM: Vertical Display End written by M68K: 2047
496 TOM: Video Mode written by GPU: 08C7. PWIDTH = 5, MODE = 16 BPP RGB, flags: BGEN (VC = 4)
497 TOM: Video Mode written by GPU: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 508)
498 Display starts at 31 (PWIDTH = 4), 24 (PWIDTH = 5)
499
500 Iron Soldier
501 TOM: Vertical Interrupt written by M68K: 2047
502 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 0)
503 TOM: Horizontal Display End written by M68K: 1727
504 TOM: Horizontal Display Begin 1 written by M68K: 123
505 TOM: Vertical Display Begin written by M68K: 25
506 TOM: Vertical Display End written by M68K: 2047
507 TOM: Vertical Interrupt written by M68K: 507
508 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 369)
509 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 510)
510 TOM: Video Mode written by M68K: 06C3. PWIDTH = 4, MODE = 24 BPP RGB, flags: BGEN (VC = 510)
511 Display starts at 31
512 Vertical resolution: 238 lines
513 [Seems to be a problem between the horizontal positioning of the 16-bit CRY & 24-bit RGB]
514
515 JagMania
516 TOM: Horizontal Period written by M68K: 844 (+1*2 = 1690)
517 TOM: Horizontal Blank Begin written by M68K: 1713
518 TOM: Horizontal Blank End written by M68K: 125
519 TOM: Horizontal Display End written by M68K: 1696
520 TOM: Horizontal Display Begin 1 written by M68K: 166
521 TOM: Vertical Period written by M68K: 523 (non-interlaced)
522 TOM: Vertical Blank End written by M68K: 24
523 TOM: Vertical Display Begin written by M68K: 46
524 TOM: Vertical Display End written by M68K: 496
525 TOM: Vertical Blank Begin written by M68K: 500
526 TOM: Vertical Sync written by M68K: 517
527 TOM: Vertical Interrupt written by M68K: 497
528 TOM: Video Mode written by M68K: 04C1. PWIDTH = 3, MODE = 16 BPP CRY, flags: BGEN (VC = 270)
529 Display starts at 55
530
531 Double Dragon V
532 TOM: Horizontal Display End written by M68K: 1727
533 TOM: Horizontal Display Begin 1 written by M68K: 123
534 TOM: Vertical Display Begin written by M68K: 25
535 TOM: Vertical Display End written by M68K: 2047
536 TOM: Vertical Interrupt written by M68K: 507
537 TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 9)
538
539 Dino Dudes
540 TOM: Horizontal Display End written by M68K: 1823
541 TOM: Horizontal Display Begin 1 written by M68K: 45
542 TOM: Vertical Display Begin written by M68K: 40
543 TOM: Vertical Display End written by M68K: 2047
544 TOM: Vertical Interrupt written by M68K: 491
545 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 398)
546 Display starts at 11 (123 - 45 = 78, 78 / 4 = 19 pixels to skip)
547 Width is 417, so maybe width of 379 would be good (starting at 123, ending at 1639)
548 Vertical resolution: 238 lines
549
550 Flashback
551 TOM: Horizontal Display End written by M68K: 1727
552 TOM: Horizontal Display Begin 1 written by M68K: 188
553 TOM: Vertical Display Begin written by M68K: 1
554 TOM: Vertical Display End written by M68K: 2047
555 TOM: Vertical Interrupt written by M68K: 483
556 TOM: Video Mode written by M68K: 08C7. PWIDTH = 5, MODE = 16 BPP RGB, flags: BGEN (VC = 99)
557 Width would be 303 with above scheme, but border width would be 13 pixels
558
559 Trevor McFur
560 Vertical resolution: 238 lines
561 */
562
563 uint32_t RGB16ToRGB32[0x10000];
564 uint32_t CRY16ToRGB32[0x10000];
565 uint32_t MIX16ToRGB32[0x10000];
566
567
568 #warning "This is not endian-safe. !!! FIX !!!"
569 void TOMFillLookupTables(void)
570 {
571         // NOTE: Jaguar 16-bit (non-CRY) color is RBG 556 like so:
572         //       RRRR RBBB BBGG GGGG
573         for(uint32_t i=0; i<0x10000; i++)
574 //hm.           RGB16ToRGB32[i] = 0xFF000000
575 //                      | ((i & 0xF100) >> 8)  | ((i & 0xE000) >> 13)
576 //                      | ((i & 0x07C0) << 13) | ((i & 0x0700) << 8)
577 //                      | ((i & 0x003F) << 10) | ((i & 0x0030) << 4);
578                 RGB16ToRGB32[i] = 0x000000FF
579 //                      | ((i & 0xF100) << 16)                                  // Red
580                         | ((i & 0xF800) << 16)                                  // Red
581                         | ((i & 0x003F) << 18)                                  // Green
582                         | ((i & 0x07C0) << 5);                                  // Blue
583
584         for(uint32_t i=0; i<0x10000; i++)
585         {
586                 uint32_t cyan = (i & 0xF000) >> 12,
587                         red = (i & 0x0F00) >> 8,
588                         intensity = (i & 0x00FF);
589
590                 uint32_t r = (((uint32_t)redcv[cyan][red]) * intensity) >> 8,
591                         g = (((uint32_t)greencv[cyan][red]) * intensity) >> 8,
592                         b = (((uint32_t)bluecv[cyan][red]) * intensity) >> 8;
593
594 //hm.           CRY16ToRGB32[i] = 0xFF000000 | (b << 16) | (g << 8) | r;
595                 CRY16ToRGB32[i] = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
596                 MIX16ToRGB32[i] = (i & 0x01 ? RGB16ToRGB32[i] : CRY16ToRGB32[i]);
597         }
598 }
599
600
601 void TOMSetPendingJERRYInt(void)
602 {
603         tom_jerry_int_pending = 1;
604 }
605
606
607 void TOMSetPendingTimerInt(void)
608 {
609         tom_timer_int_pending = 1;
610 }
611
612
613 void TOMSetPendingObjectInt(void)
614 {
615         tom_object_int_pending = 1;
616 }
617
618
619 void TOMSetPendingGPUInt(void)
620 {
621         tom_gpu_int_pending = 1;
622 }
623
624
625 void TOMSetPendingVideoInt(void)
626 {
627         tom_video_int_pending = 1;
628 }
629
630
631 uint8_t * TOMGetRamPointer(void)
632 {
633         return tomRam8;
634 }
635
636
637 uint8_t TOMGetVideoMode(void)
638 {
639         uint16_t vmode = GET16(tomRam8, VMODE);
640         return ((vmode & VARMOD) >> 6) | ((vmode & MODE) >> 1);
641 }
642
643
644 //Used in only one place (and for debug purposes): OBJECTP.CPP
645 #warning "Used in only one place (and for debug purposes): OBJECTP.CPP !!! FIX !!!"
646 uint16_t TOMGetVDB(void)
647 {
648         return GET16(tomRam8, VDB);
649 }
650
651
652 #define LEFT_BG_FIX
653 //
654 // 16 BPP CRY/RGB mixed mode rendering
655 //
656 void tom_render_16bpp_cry_rgb_mix_scanline(uint32_t * backbuffer)
657 {
658 //CHANGED TO 32BPP RENDERING
659         uint16_t width = tomWidth;
660         uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
661
662         //New stuff--restrict our drawing...
663         uint8_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
664         //NOTE: May have to check HDB2 as well!
665         // Get start position in HC ticks
666         int16_t startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL);
667         // Convert to pixels
668         startPos /= pwidth;
669
670         if (startPos < 0)
671                 // This is x2 because current_line_buffer is uint8_t & we're in a 16bpp mode
672                 current_line_buffer += 2 * -startPos;
673         else
674 //This case doesn't properly handle the "start on the right side of virtual screen" case
675 //Dunno why--looks Ok...
676 //What *is* for sure wrong is that it doesn't copy the linebuffer's BG pixels... [FIXED NOW]
677 //This should likely be 4 instead of 2 (?--not sure)
678 // Actually, there should be NO multiplier, as startPos is expressed in PIXELS
679 // and so is the backbuffer.
680 #ifdef LEFT_BG_FIX
681         {
682                 uint8_t g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
683                 uint32_t pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
684
685                 for(int16_t i=0; i<startPos; i++)
686                         *backbuffer++ = pixel;
687
688                 width -= startPos;
689         }
690 #else
691                 backbuffer += 2 * startPos, width -= startPos;
692 #endif
693
694         while (width)
695         {
696                 uint16_t color = (*current_line_buffer++) << 8;
697                 color |= *current_line_buffer++;
698                 *backbuffer++ = MIX16ToRGB32[color];
699                 width--;
700         }
701 }
702
703
704 //
705 // 16 BPP CRY mode rendering
706 //
707 void tom_render_16bpp_cry_scanline(uint32_t * backbuffer)
708 {
709 //CHANGED TO 32BPP RENDERING
710         uint16_t width = tomWidth;
711         uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
712
713         //New stuff--restrict our drawing...
714         uint8_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
715         //NOTE: May have to check HDB2 as well!
716         int16_t startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL);// Get start position in HC ticks
717         startPos /= pwidth;
718         if (startPos < 0)
719                 current_line_buffer += 2 * -startPos;
720         else
721 #ifdef LEFT_BG_FIX
722         {
723                 uint8_t g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
724                 uint32_t pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
725
726                 for(int16_t i=0; i<startPos; i++)
727                         *backbuffer++ = pixel;
728
729                 width -= startPos;
730         }
731 #else
732 //This should likely be 4 instead of 2 (?--not sure)
733                 backbuffer += 2 * startPos, width -= startPos;
734 #endif
735
736         while (width)
737         {
738                 uint16_t color = (*current_line_buffer++) << 8;
739                 color |= *current_line_buffer++;
740                 *backbuffer++ = CRY16ToRGB32[color];
741                 width--;
742         }
743 }
744
745
746 //
747 // 24 BPP mode rendering
748 //
749 void tom_render_24bpp_scanline(uint32_t * backbuffer)
750 {
751 //CHANGED TO 32BPP RENDERING
752         uint16_t width = tomWidth;
753         uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
754
755         //New stuff--restrict our drawing...
756         uint8_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
757         //NOTE: May have to check HDB2 as well!
758         int16_t startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL);       // Get start position in HC ticks
759         startPos /= pwidth;
760         if (startPos < 0)
761                 current_line_buffer += 4 * -startPos;
762         else
763 #ifdef LEFT_BG_FIX
764         {
765                 uint8_t g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
766                 uint32_t pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
767
768                 for(int16_t i=0; i<startPos; i++)
769                         *backbuffer++ = pixel;
770
771                 width -= startPos;
772         }
773 #else
774 //This should likely be 4 instead of 2 (?--not sure)
775                 backbuffer += 2 * startPos, width -= startPos;
776 #endif
777
778         while (width)
779         {
780                 uint32_t g = *current_line_buffer++;
781                 uint32_t r = *current_line_buffer++;
782                 current_line_buffer++;
783                 uint32_t b = *current_line_buffer++;
784 //hm.           *backbuffer++ = 0xFF000000 | (b << 16) | (g << 8) | r;
785                 *backbuffer++ = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
786                 width--;
787         }
788 }
789
790
791 //Seems to me that this is NOT a valid mode--the JTRM seems to imply that you would need
792 //extra hardware outside of the Jaguar console to support this!
793 //
794 // 16 BPP direct mode rendering
795 //
796 void tom_render_16bpp_direct_scanline(uint32_t * backbuffer)
797 {
798         uint16_t width = tomWidth;
799         uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
800
801         while (width)
802         {
803                 uint16_t color = (*current_line_buffer++) << 8;
804                 color |= *current_line_buffer++;
805                 *backbuffer++ = color >> 1;
806                 width--;
807         }
808 }
809
810
811 //
812 // 16 BPP RGB mode rendering
813 //
814 void tom_render_16bpp_rgb_scanline(uint32_t * backbuffer)
815 {
816 //CHANGED TO 32BPP RENDERING
817         // 16 BPP RGB: 0-5 green, 6-10 blue, 11-15 red
818
819         uint16_t width = tomWidth;
820         uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
821
822         //New stuff--restrict our drawing...
823         uint8_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
824         //NOTE: May have to check HDB2 as well!
825         int16_t startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL);       // Get start position in HC ticks
826         startPos /= pwidth;
827
828         if (startPos < 0)
829                 current_line_buffer += 2 * -startPos;
830         else
831 #ifdef LEFT_BG_FIX
832         {
833                 uint8_t g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
834                 uint32_t pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
835
836                 for(int16_t i=0; i<startPos; i++)
837                         *backbuffer++ = pixel;
838
839                 width -= startPos;
840         }
841 #else
842 //This should likely be 4 instead of 2 (?--not sure)
843                 backbuffer += 2 * startPos, width -= startPos;
844 #endif
845
846         while (width)
847         {
848                 uint32_t color = (*current_line_buffer++) << 8;
849                 color |= *current_line_buffer++;
850                 *backbuffer++ = RGB16ToRGB32[color];
851                 width--;
852         }
853 }
854
855
856 //
857 // Process a single scanline
858 // (this is bad terminology; each tick of the VC is actually a half-line)
859 //
860 void TOMExecHalfline(uint16_t halfline, bool render)
861 {
862 #warning "!!! Need to handle multiple fields properly !!!"
863         // We ignore the problem for now
864         halfline &= 0x7FF;
865
866         bool inActiveDisplayArea = true;
867
868 //Interlacing is still not handled correctly here... !!! FIX !!!
869         if (halfline & 0x01)                                                    // Execute OP only on even halflines (non-interlaced only!)
870                 return;
871
872 //Hm, it seems that the OP needs to execute from zero, so let's try it:
873 // And it works! But need to do some optimizations in the OP to keep it from attempting
874 // to do a scanline render in the non-display area... [DONE]
875 //this seems to cause a regression in certain games, like rayman
876 //which means I have to dig thru the asic nets to see what's wrong...
877 /*
878 No, the OP doesn't start until VDB, that much is certain. The thing is, VDB is the
879 HALF line that the OP starts on--which means that it needs to start at VDB / 2!!!
880
881 Hrm, doesn't seem to be enough, though it should be... still sticks for 20 frames.
882
883
884 What triggers this is writing $FFFF to VDE. This causes the OP start signal in VID to 
885 latch on, which in effect sets VDB to zero. So that much is correct. But the thing with
886 Rayman is that it shouldn't cause the graphical glitches seen there, so still have to
887 investigate what's going on there. By all rights, it shouldn't glitch because:
888
889 00006C00: 0000000D 82008F73 (BRANCH) YPOS=494, CC=">", link=$00006C10
890 00006C08: 000003FF 00008173 (BRANCH) YPOS=46, CC=">", link=$001FF800
891 00006C10: 00000000 0000000C (STOP)
892 001FF800: 12FC2BFF 02380000 (BITMAP)
893           00008004 8180CFF1
894
895 Even if the OP is running all the time, the link should tell it to stop at the right
896 place (which it seems to do). But we still get glitchy screen.
897
898 Seems the glitchy screen went away... Maybe the GPU alignment fixes fixed it???
899 Just need to add the proper checking here then.
900
901 Some numbers, courtesy of the Jaguar BIOS:
902 // NTSC:
903 VP, 523                 // Vertical Period (1-based; in this case VP = 524)
904 VBE, 24                 // Vertical Blank End
905 VDB, 38                 // Vertical Display Begin
906 VDE, 518                // Vertical Display End
907 VBB, 500                // Vertical Blank Begin
908 VS, 517                 // Vertical Sync
909
910 // PAL Jaguar
911 VP, 623                 // Vertical Period (1-based; in this case VP = 624)
912 VBE, 34                 // Vertical Blank End
913 VDB, 38                 // Vertical Display Begin
914 VDE, 518                // Vertical Display End
915 VBB, 600                // Vertical Blank Begin
916 VS, 618                 // Vertical Sync
917
918 Numbers for KM, NTSC:
919 KM: (Note that with VDE <= 507, the OP starts at VDB as expected)
920 TOM: Vertical Display Begin written by M68K: 41
921 TOM: Vertical Display End written by M68K: 2047
922 TOM: Vertical Interrupt written by M68K: 491
923 */
924 #if 1
925         // Initial values that "well behaved" programs use
926         uint16_t startingHalfline = GET16(tomRam8, VDB);
927         uint16_t endingHalfline = GET16(tomRam8, VDE);
928
929         // Simulate the OP start bug here!
930         // Really, this value is somewhere around 507 for an NTSC Jaguar. But this
931         // should work in a majority of cases, at least until we can figure it out properly.
932         if (endingHalfline > GET16(tomRam8, VP))
933                 startingHalfline = 0;
934
935         if (halfline >= startingHalfline && halfline < endingHalfline)
936 //      if (halfline >= 0 && halfline < (uint16_t)GET16(tomRam8, VDE))
937 // 16 isn't enough, and neither is 32 for raptgun. 32 fucks up Rayman
938 //      if (halfline >= ((uint16_t)GET16(tomRam8, VDB) / 2) && halfline < ((uint16_t)GET16(tomRam8, VDE) / 2))
939 //      if (halfline >= ((uint16_t)GET16(tomRam8, VDB) - 16) && halfline < (uint16_t)GET16(tomRam8, VDE))
940 //      if (halfline >= 20 && halfline < (uint16_t)GET16(tomRam8, VDE))
941 //      if (halfline >= (uint16_t)GET16(tomRam8, VDB) && halfline < (uint16_t)GET16(tomRam8, VDE))
942         {
943                 if (render)
944                 {
945                         uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
946                         uint8_t bgHI = tomRam8[BG], bgLO = tomRam8[BG + 1];
947
948                         // Clear line buffer with BG
949                         if (GET16(tomRam8, VMODE) & BGEN) // && (CRY or RGB16)...
950                                 for(uint32_t i=0; i<720; i++)
951                                         *current_line_buffer++ = bgHI, *current_line_buffer++ = bgLO;
952
953                         OPProcessList(halfline, render);
954                 }
955         }
956         else
957                 inActiveDisplayArea = false;
958 #else
959         inActiveDisplayArea =
960                 (halfline >= (uint16_t)GET16(tomRam8, VDB) && halfline < (uint16_t)GET16(tomRam8, VDE)
961                         ? true : false);
962
963         if (halfline < (uint16_t)GET16(tomRam8, VDE))
964         {
965                 if (render)//With JaguarExecuteNew() this is always true...
966                 {
967                         uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
968                         uint8_t bgHI = tomRam8[BG], bgLO = tomRam8[BG + 1];
969
970                         // Clear line buffer with BG
971                         if (GET16(tomRam8, VMODE) & BGEN) // && (CRY or RGB16)...
972                                 for(uint32_t i=0; i<720; i++)
973                                         *current_line_buffer++ = bgHI, *current_line_buffer++ = bgLO;
974
975 //                      OPProcessList(halfline, render);
976 //This seems to take care of it...
977                         OPProcessList(halfline, inActiveDisplayArea);
978                 }
979         }
980 #endif
981
982         // Try to take PAL into account... [We do now!]
983
984         uint16_t topVisible = (vjs.hardwareTypeNTSC ? TOP_VISIBLE_VC : TOP_VISIBLE_VC_PAL),
985                 bottomVisible = (vjs.hardwareTypeNTSC ? BOTTOM_VISIBLE_VC : BOTTOM_VISIBLE_VC_PAL);
986         uint32_t * TOMCurrentLine = &(screenBuffer[((halfline - topVisible) / 2) * screenPitch]);
987
988         // Here's our virtualized scanline code...
989
990         if (halfline >= topVisible && halfline < bottomVisible)
991         {
992                 if (inActiveDisplayArea)
993                 {
994 //NOTE: The following doesn't put BORDER color on the sides... !!! FIX !!!
995 #warning "The following doesn't put BORDER color on the sides... !!! FIX !!!"
996                         if (vjs.renderType == RT_NORMAL)
997 //                              scanline_render[TOMGetVideoMode()](TOMBackbuffer);
998                                 scanline_render[TOMGetVideoMode()](TOMCurrentLine);
999                         else//TV type render
1000                         {
1001 /*
1002         tom_render_16bpp_cry_scanline,
1003         tom_render_24bpp_scanline,
1004         tom_render_16bpp_direct_scanline,
1005         tom_render_16bpp_rgb_scanline,
1006         tom_render_16bpp_cry_rgb_mix_scanline,
1007         tom_render_24bpp_scanline,
1008         tom_render_16bpp_direct_scanline,
1009         tom_render_16bpp_rgb_scanline
1010 #define VMODE           0x28
1011 #define   MODE          0x0006          // Line buffer to video generator mode
1012 #define   VARMOD        0x0100          // Mixed CRY/RGB16 mode (only works in MODE 0!)
1013 */
1014                                 uint8_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
1015                                 uint8_t mode = ((GET16(tomRam8, VMODE) & MODE) >> 1);
1016                                 bool varmod = GET16(tomRam8, VMODE) & VARMOD;
1017 //The video texture line buffer ranges from 0 to 1279, with its left edge starting at
1018 //LEFT_VISIBLE_HC. So, we need to start writing into the backbuffer at HDB1, using pwidth
1019 //as our scaling factor. The way it generates its image on a real TV!
1020
1021 //So, for example, if HDB1 is less than LEFT_VISIBLE_HC, then we have to figure out where
1022 //in the VTLB that we start writing pixels from the Jaguar line buffer (VTLB start=0,
1023 //JLB=something).
1024 #if 0
1025 //
1026 // 24 BPP mode rendering
1027 //
1028 void tom_render_24bpp_scanline(uint32_t * backbuffer)
1029 {
1030 //CHANGED TO 32BPP RENDERING
1031         uint16_t width = tomWidth;
1032         uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
1033
1034         //New stuff--restrict our drawing...
1035         uint8_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
1036         //NOTE: May have to check HDB2 as well!
1037         int16_t startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL);       // Get start position in HC ticks
1038         startPos /= pwidth;
1039         if (startPos < 0)
1040                 current_line_buffer += 4 * -startPos;
1041         else
1042 //This should likely be 4 instead of 2 (?--not sure)
1043                 backbuffer += 2 * startPos, width -= startPos;
1044
1045         while (width)
1046         {
1047                 uint32_t g = *current_line_buffer++;
1048                 uint32_t r = *current_line_buffer++;
1049                 current_line_buffer++;
1050                 uint32_t b = *current_line_buffer++;
1051                 *backbuffer++ = 0xFF000000 | (b << 16) | (g << 8) | r;
1052                 width--;
1053         }
1054 }
1055 #endif
1056
1057                         }
1058                 }
1059                 else
1060                 {
1061                         // If outside of VDB & VDE, then display the border color
1062                         uint32_t * currentLineBuffer = TOMCurrentLine;
1063                         uint8_t g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
1064 //Hm.                   uint32_t pixel = 0xFF000000 | (b << 16) | (g << 8) | r;
1065                         uint32_t pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
1066
1067                         for(uint32_t i=0; i<tomWidth; i++)
1068                                 *currentLineBuffer++ = pixel;
1069                 }
1070         }
1071 }
1072
1073
1074 //
1075 // TOM initialization
1076 //
1077 void TOMInit(void)
1078 {
1079         TOMFillLookupTables();
1080         OPInit();
1081         BlitterInit();
1082         TOMReset();
1083 }
1084
1085
1086 void TOMDone(void)
1087 {
1088         TOMDumpIORegistersToLog();
1089         OPDone();
1090         BlitterDone();
1091         WriteLog("TOM: Resolution %i x %i %s\n", TOMGetVideoModeWidth(), TOMGetVideoModeHeight(),
1092                 videoMode_to_str[TOMGetVideoMode()]);
1093 //      WriteLog("\ntom: object processor:\n");
1094 //      WriteLog("tom: pointer to object list: 0x%.8x\n",op_get_list_pointer());
1095 //      WriteLog("tom: INT1=0x%.2x%.2x\n",TOMReadByte(0xf000e0),TOMReadByte(0xf000e1));
1096 }
1097
1098
1099 uint32_t TOMGetVideoModeWidth(void)
1100 {
1101         //These widths are pretty bogus. Should use HDB1/2 & HDE/HBB & PWIDTH to calc the width...
1102 //      uint32_t width[8] = { 1330, 665, 443, 332, 266, 222, 190, 166 };
1103 //Temporary, for testing Doom...
1104 //      uint32_t width[8] = { 1330, 665, 443, 332, 266, 222, 190, 332 };
1105
1106         // Note that the following PWIDTH values have the following pixel aspect ratios:
1107         // PWIDTH = 1 -> 0.25:1 (1:4) pixels (X:Y ratio)
1108         // PWIDTH = 2 -> 0.50:1 (1:2) pixels
1109         // PWIDTH = 3 -> 0.75:1 (3:4) pixels
1110         // PWIDTH = 4 -> 1.00:1 (1:1) pixels
1111         // PWIDTH = 5 -> 1.25:1 (5:4) pixels
1112         // PWIDTH = 6 -> 1.50:1 (3:2) pixels
1113         // PWIDTH = 7 -> 1.75:1 (7:4) pixels
1114         // PWIDTH = 8 -> 2.00:1 (2:1) pixels
1115
1116         // Also note that the JTRM says that PWIDTH of 4 gives pixels that are "about" square--
1117         // this implies that the other modes have pixels that are *not* square!
1118         // Also, I seriously doubt that you will see any games that use PWIDTH = 1!
1119
1120         // NOTE: Even though the PWIDTH value is + 1, here we're using a zero-based index and
1121         //       so we don't bother to add one...
1122 //      return width[(GET16(tomRam8, VMODE) & PWIDTH) >> 9];
1123
1124         // Now, we just calculate it...
1125 /*      uint16_t hdb1 = GET16(tomRam8, HDB1), hde = GET16(tomRam8, HDE),
1126                 hbb = GET16(tomRam8, HBB), pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
1127 //      return ((hbb < hde ? hbb : hde) - hdb1) / pwidth;
1128 //Temporary, for testing Doom...
1129         return ((hbb < hde ? hbb : hde) - hdb1) / (pwidth == 8 ? 4 : pwidth);*/
1130
1131         // To make it easier to make a quasi-fixed display size, we restrict the viewing
1132         // area to an arbitrary range of the Horizontal Count.
1133         uint16_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
1134         return (vjs.hardwareTypeNTSC ? RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC : RIGHT_VISIBLE_HC_PAL - LEFT_VISIBLE_HC_PAL) / pwidth;
1135 //Temporary, for testing Doom...
1136 //      return (RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC) / (pwidth == 8 ? 4 : pwidth);
1137 ////    return (RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC) / (pwidth == 4 ? 8 : pwidth);
1138
1139 // More speculating...
1140 // According to the JTRM, the number of potential pixels across is given by the
1141 // Horizontal Period (HP - in NTSC this is 845). The Horizontal Count counts from
1142 // zero to this value twice per scanline (the high bit is set on the second count).
1143 // HBE and HBB define the absolute "black" limits of the screen, while HDB1/2 and
1144 // HDE determine the extent of the OP "on" time. I.e., when the OP is turned on by
1145 // HDB1, it starts fetching the line from position 0 in LBUF.
1146
1147 // The trick, it would seem, is to figure out how long the typical visible scanline
1148 // of a TV is in HP ticks and limit the visible area to that (divided by PWIDTH, of
1149 // course). Using that length, we can establish an "absolute left display limit" with
1150 // which to measure HBB & HDB1/2 against when rendering LBUF (i.e., if HDB1 is 20 ticks
1151 // to the right of the ALDL and PWIDTH is 4, then start writing the LBUF starting at
1152 // backbuffer + 5 pixels).
1153
1154 // That's basically what we're doing now...!
1155 }
1156
1157
1158 // *** SPECULATION ***
1159 // It might work better to virtualize the height settings, i.e., set the vertical
1160 // height at 240 lines and clip using the VDB and VDE/VP registers...
1161 // Same with the width... [Width is pretty much virtualized now.]
1162
1163 // Now that that the width is virtualized, let's virtualize the height. :-)
1164 uint32_t TOMGetVideoModeHeight(void)
1165 {
1166 //      uint16_t vmode = GET16(tomRam8, VMODE);
1167 //      uint16_t vbe = GET16(tomRam8, VBE);
1168 //      uint16_t vbb = GET16(tomRam8, VBB);
1169 //      uint16_t vdb = GET16(tomRam8, VDB);
1170 //      uint16_t vde = GET16(tomRam8, VDE);
1171 //      uint16_t vp = GET16(tomRam8, VP);
1172
1173 /*      if (vde == 0xFFFF)
1174                 vde = vbb;//*/
1175
1176 //      return 227;//WAS:(vde/*-vdb*/) >> 1;
1177         // The video mode height probably works this way:
1178         // VC counts from 0 to VP. VDB starts the OP. Either when
1179         // VDE is reached or VP, the OP is stopped. Let's try it...
1180         // Also note that we're conveniently ignoring interlaced display modes...!
1181 //      return ((vde > vp ? vp : vde) - vdb) >> 1;
1182 //      return ((vde > vbb ? vbb : vde) - vdb) >> 1;
1183 //Let's try from the Vertical Blank interval...
1184 //Seems to work OK!
1185 //      return (vbb - vbe) >> 1;        // Again, doesn't take interlacing into account...
1186 // This of course doesn't take interlacing into account. But I haven't seen any
1187 // Jaguar software that takes advantage of it either...
1188 //Also, doesn't reflect PAL Jaguar either... !!! FIX !!! [DONE]
1189 //      return 240;                                                                             // Set virtual screen height to 240 lines...
1190         return (vjs.hardwareTypeNTSC ? 240 : 256);
1191 }
1192
1193
1194 //
1195 // TOM reset code
1196 // Now PAL friendly!
1197 //
1198 /*
1199 The values in TOMReset come from the Jaguar BIOS.
1200 These values are from BJL:
1201
1202 NSTC:
1203 CLK2     181
1204 HP               844
1205 HBB              1713
1206 HBE              125
1207 HS               1741
1208 HVS              651
1209 HEQ              784
1210 HDE              1696
1211 HDB1     166
1212 HDB2     166
1213 VP               523
1214 VEE              6
1215 VBE              24
1216 VDB              46
1217 VDE              496
1218 VBB              500
1219 VEB              511
1220 VS               517
1221
1222 PAL:
1223 CLK2     226
1224 HP               850
1225 HBB              1711
1226 HBE              158
1227 HS               1749
1228 HVS              601
1229 HEQ              787
1230 HDE              1696
1231 HDB1     166
1232 HDB2     166
1233 VP               625
1234 VEE              6
1235 VBE              34
1236 VDB              46
1237 VDE              429
1238 VBB              600
1239 VEB              613
1240 VS               618
1241 */
1242 void TOMReset(void)
1243 {
1244         OPReset();
1245         BlitterReset();
1246         memset(tomRam8, 0x00, 0x4000);
1247
1248         if (vjs.hardwareTypeNTSC)
1249         {
1250                 SET16(tomRam8, MEMCON1, 0x1861);
1251 //              SET16(tomRam8, MEMCON1, 0x1865);//Bunch of BS
1252                 SET16(tomRam8, MEMCON2, 0x35CC);
1253                 SET16(tomRam8, HP, 844);                        // Horizontal Period (1-based; HP=845)
1254                 SET16(tomRam8, HBB, 1713);                      // Horizontal Blank Begin
1255                 SET16(tomRam8, HBE, 125);                       // Horizontal Blank End
1256                 SET16(tomRam8, HDE, 1665);                      // Horizontal Display End
1257                 SET16(tomRam8, HDB1, 203);                      // Horizontal Display Begin 1
1258                 SET16(tomRam8, VP, 523);                        // Vertical Period (1-based; in this case VP = 524)
1259                 SET16(tomRam8, VBE, 24);                        // Vertical Blank End
1260                 SET16(tomRam8, VDB, 38);                        // Vertical Display Begin
1261                 SET16(tomRam8, VDE, 518);                       // Vertical Display End
1262                 SET16(tomRam8, VBB, 500);                       // Vertical Blank Begin
1263                 SET16(tomRam8, VS, 517);                        // Vertical Sync
1264                 SET16(tomRam8, VMODE, 0x06C1);
1265         }
1266         else    // PAL Jaguar
1267         {
1268                 SET16(tomRam8, MEMCON1, 0x1861);
1269                 SET16(tomRam8, MEMCON2, 0x35CC);
1270                 SET16(tomRam8, HP, 850);                        // Horizontal Period
1271                 SET16(tomRam8, HBB, 1711);                      // Horizontal Blank Begin
1272                 SET16(tomRam8, HBE, 158);                       // Horizontal Blank End
1273                 SET16(tomRam8, HDE, 1665);                      // Horizontal Display End
1274                 SET16(tomRam8, HDB1, 203);                      // Horizontal Display Begin 1
1275                 SET16(tomRam8, VP, 623);                        // Vertical Period (1-based; in this case VP = 624)
1276                 SET16(tomRam8, VBE, 34);                        // Vertical Blank End
1277                 SET16(tomRam8, VDB, 38);                        // Vertical Display Begin
1278                 SET16(tomRam8, VDE, 518);                       // Vertical Display End
1279                 SET16(tomRam8, VBB, 600);                       // Vertical Blank Begin
1280                 SET16(tomRam8, VS, 618);                        // Vertical Sync
1281                 SET16(tomRam8, VMODE, 0x06C1);
1282         }
1283
1284         tomWidth = 0;
1285         tomHeight = 0;
1286
1287         tom_jerry_int_pending = 0;
1288         tom_timer_int_pending = 0;
1289         tom_object_int_pending = 0;
1290         tom_gpu_int_pending = 0;
1291         tom_video_int_pending = 0;
1292
1293         tomTimerPrescaler = 0;                                  // TOM PIT is disabled
1294         tomTimerDivider = 0;
1295         tomTimerCounter = 0;
1296 }
1297
1298
1299 //
1300 // Dump all TOM register values to the log
1301 //
1302 void TOMDumpIORegistersToLog(void)
1303 {
1304         WriteLog("\n\n---------------------------------------------------------------------\n");
1305         WriteLog("TOM I/O Registers\n");
1306         WriteLog("---------------------------------------------------------------------\n");
1307         WriteLog("F000%02X (MEMCON1): $%04X\n", MEMCON1, GET16(tomRam8, MEMCON1));
1308         WriteLog("F000%02X (MEMCON2): $%04X\n", MEMCON2, GET16(tomRam8, MEMCON2));
1309         WriteLog("F000%02X      (HC): $%04X\n", HC,      GET16(tomRam8, HC));
1310         WriteLog("F000%02X      (VC): $%04X\n", VC,      GET16(tomRam8, VC));
1311         WriteLog("F000%02X     (OLP): $%08X\n", OLP,     GET32(tomRam8, OLP));
1312         WriteLog("F000%02X     (OBF): $%04X\n", OBF,     GET16(tomRam8, OBF));
1313         WriteLog("F000%02X   (VMODE): $%04X\n", VMODE,   GET16(tomRam8, VMODE));
1314         WriteLog("F000%02X   (BORD1): $%04X\n", BORD1,   GET16(tomRam8, BORD1));
1315         WriteLog("F000%02X   (BORD2): $%04X\n", BORD2,   GET16(tomRam8, BORD2));
1316         WriteLog("F000%02X      (HP): $%04X\n", HP,      GET16(tomRam8, HP));
1317         WriteLog("F000%02X     (HBB): $%04X\n", HBB,     GET16(tomRam8, HBB));
1318         WriteLog("F000%02X     (HBE): $%04X\n", HBE,     GET16(tomRam8, HBE));
1319         WriteLog("F000%02X      (HS): $%04X\n", HS,      GET16(tomRam8, HS));
1320         WriteLog("F000%02X     (HVS): $%04X\n", HVS,     GET16(tomRam8, HVS));
1321         WriteLog("F000%02X    (HDB1): $%04X\n", HDB1,    GET16(tomRam8, HDB1));
1322         WriteLog("F000%02X    (HDB2): $%04X\n", HDB2,    GET16(tomRam8, HDB2));
1323         WriteLog("F000%02X     (HDE): $%04X\n", HDE,     GET16(tomRam8, HDE));
1324         WriteLog("F000%02X      (VP): $%04X\n", VP,      GET16(tomRam8, VP));
1325         WriteLog("F000%02X     (VBB): $%04X\n", VBB,     GET16(tomRam8, VBB));
1326         WriteLog("F000%02X     (VBE): $%04X\n", VBE,     GET16(tomRam8, VBE));
1327         WriteLog("F000%02X      (VS): $%04X\n", VS,      GET16(tomRam8, VS));
1328         WriteLog("F000%02X     (VDB): $%04X\n", VDB,     GET16(tomRam8, VDB));
1329         WriteLog("F000%02X     (VDE): $%04X\n", VDE,     GET16(tomRam8, VDE));
1330         WriteLog("F000%02X     (VEB): $%04X\n", VEB,     GET16(tomRam8, VEB));
1331         WriteLog("F000%02X     (VEE): $%04X\n", VEE,     GET16(tomRam8, VEE));
1332         WriteLog("F000%02X      (VI): $%04X\n", VI,      GET16(tomRam8, VI));
1333         WriteLog("F000%02X    (PIT0): $%04X\n", PIT0,    GET16(tomRam8, PIT0));
1334         WriteLog("F000%02X    (PIT1): $%04X\n", PIT1,    GET16(tomRam8, PIT1));
1335         WriteLog("F000%02X     (HEQ): $%04X\n", HEQ,     GET16(tomRam8, HEQ));
1336         WriteLog("F000%02X      (BG): $%04X\n", BG,      GET16(tomRam8, BG));
1337         WriteLog("F000%02X    (INT1): $%04X\n", INT1,    GET16(tomRam8, INT1));
1338         WriteLog("F000%02X    (INT2): $%04X\n", INT2,    GET16(tomRam8, INT2));
1339         WriteLog("---------------------------------------------------------------------\n\n\n");
1340 }
1341
1342
1343 //
1344 // TOM byte access (read)
1345 //
1346 uint8_t TOMReadByte(uint32_t offset, uint32_t who/*=UNKNOWN*/)
1347 {
1348 //???Is this needed???
1349 // It seems so. Perhaps it's the +$8000 offset being written to (32-bit interface)?
1350 // However, the 32-bit interface is WRITE ONLY, so that can't be it...
1351 // Also, the 68K CANNOT make use of the 32-bit interface, since its bus width is only 16-bits...
1352 //      offset &= 0xFF3FFF;
1353
1354 #ifdef TOM_DEBUG
1355         WriteLog("TOM: Reading byte at %06X for %s\n", offset, whoName[who]);
1356 #endif
1357
1358         if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
1359                 return GPUReadByte(offset, who);
1360         else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
1361                 return GPUReadByte(offset, who);
1362 /*      else if ((offset >= 0xF00010) && (offset < 0xF00028))
1363                 return OPReadByte(offset, who);*/
1364         else if ((offset >= 0xF02200) && (offset < 0xF022A0))
1365                 return BlitterReadByte(offset, who);
1366         else if (offset == 0xF00050)
1367                 return tomTimerPrescaler >> 8;
1368         else if (offset == 0xF00051)
1369                 return tomTimerPrescaler & 0xFF;
1370         else if (offset == 0xF00052)
1371                 return tomTimerDivider >> 8;
1372         else if (offset == 0xF00053)
1373                 return tomTimerDivider & 0xFF;
1374
1375         return tomRam8[offset & 0x3FFF];
1376 }
1377
1378
1379 //
1380 // TOM word access (read)
1381 //
1382 uint16_t TOMReadWord(uint32_t offset, uint32_t who/*=UNKNOWN*/)
1383 {
1384 //???Is this needed???
1385 //      offset &= 0xFF3FFF;
1386 #ifdef TOM_DEBUG
1387         WriteLog("TOM: Reading word at %06X for %s\n", offset, whoName[who]);
1388 #endif
1389 if (offset >= 0xF02000 && offset <= 0xF020FF)
1390         WriteLog("TOM: ReadWord attempted from GPU register file by %s (unimplemented)!\n", whoName[who]);
1391
1392         if (offset == 0xF000E0)
1393         {
1394                 // For reading, should only return the lower 5 bits...
1395                 uint16_t data = (tom_jerry_int_pending << 4) | (tom_timer_int_pending << 3)
1396                         | (tom_object_int_pending << 2) | (tom_gpu_int_pending << 1)
1397                         | (tom_video_int_pending << 0);
1398                 //WriteLog("tom: interrupt status is 0x%.4x \n",data);
1399                 return data;
1400         }
1401 //Shoud be handled by the jaguar main loop now... And it is! ;-)
1402 /*      else if (offset == 0xF00006)    // VC
1403         // What if we're in interlaced mode?
1404         // According to docs, in non-interlace mode VC is ALWAYS even...
1405 //              return (tom_scanline << 1);// + 1;
1406 //But it's causing Rayman to be fucked up... Why???
1407 //Because VC is even in NI mode when calling the OP! That's why!
1408                 return (tom_scanline << 1) + 1;//*/
1409 /*
1410 //      F00004          R/W   -----xxx xxxxxxxx   HC - horizontal count
1411 //                            -----x-- --------      (which half of the display)
1412 //                            ------xx xxxxxxxx      (10-bit counter)
1413 */
1414 // This is a kludge to get the HC working somewhat... What we really should do here
1415 // is check what the global time is at the time of the read and calculate the correct HC...
1416 // !!! FIX !!!
1417         else if (offset == 0xF00004)
1418                 return rand() & 0x03FF;
1419         else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE + 0x20))
1420                 return GPUReadWord(offset, who);
1421         else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
1422                 return GPUReadWord(offset, who);
1423 /*      else if ((offset >= 0xF00010) && (offset < 0xF00028))
1424                 return OPReadWord(offset, who);*/
1425         else if ((offset >= 0xF02200) && (offset < 0xF022A0))
1426                 return BlitterReadWord(offset, who);
1427         else if (offset == 0xF00050)
1428                 return tomTimerPrescaler;
1429         else if (offset == 0xF00052)
1430                 return tomTimerDivider;
1431
1432         offset &= 0x3FFF;
1433         return (TOMReadByte(offset, who) << 8) | TOMReadByte(offset + 1, who);
1434 }
1435
1436
1437 #define TOM_STRICT_MEMORY_ACCESS
1438 //
1439 // TOM byte access (write)
1440 //
1441 void TOMWriteByte(uint32_t offset, uint8_t data, uint32_t who/*=UNKNOWN*/)
1442 {
1443         // Moved here tentatively, so we can see everything written to TOM.
1444         tomRam8[offset & 0x3FFF] = data;
1445
1446 #ifdef TOM_DEBUG
1447         WriteLog("TOM: Writing byte %02X at %06X", data, offset);
1448 #endif
1449 //???Is this needed???
1450 // Perhaps on the writes--32-bit writes that is! And masked with FF7FFF...
1451 #ifndef TOM_STRICT_MEMORY_ACCESS
1452         offset &= 0xFF3FFF;
1453 #else
1454         // "Fast" (32-bit only) write access to the GPU
1455 //      if ((offset >= 0xF0A100) && (offset <= 0xF0BFFF))
1456         if ((offset >= 0xF08000) && (offset <= 0xF0BFFF))
1457                 offset &= 0xFF7FFF;
1458 #endif
1459 #ifdef TOM_DEBUG
1460         WriteLog(" -->[%06X] by %s\n", offset, whoName[who]);
1461 #endif
1462
1463 #ifdef TOM_STRICT_MEMORY_ACCESS
1464         // Sanity check ("Aww, there ain't no Sanity Clause...")
1465         if ((offset < 0xF00000) || (offset > 0xF03FFF))
1466                 return;
1467 #endif
1468
1469         if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
1470         {
1471                 GPUWriteByte(offset, data, who);
1472                 return;
1473         }
1474         else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
1475         {
1476                 GPUWriteByte(offset, data, who);
1477                 return;
1478         }
1479 /*      else if ((offset >= 0xF00010) && (offset < 0xF00028))
1480         {
1481                 OPWriteByte(offset, data, who);
1482                 return;
1483         }*/
1484         else if ((offset >= 0xF02200) && (offset < 0xF022A0))
1485         {
1486                 BlitterWriteByte(offset, data, who);
1487                 return;
1488         }
1489         else if (offset == 0xF00050)
1490         {
1491                 tomTimerPrescaler = (tomTimerPrescaler & 0x00FF) | (data << 8);
1492                 TOMResetPIT();
1493                 return;
1494         }
1495         else if (offset == 0xF00051)
1496         {
1497                 tomTimerPrescaler = (tomTimerPrescaler & 0xFF00) | data;
1498                 TOMResetPIT();
1499                 return;
1500         }
1501         else if (offset == 0xF00052)
1502         {
1503                 tomTimerDivider = (tomTimerDivider & 0x00FF) | (data << 8);
1504                 TOMResetPIT();
1505                 return;
1506         }
1507         else if (offset == 0xF00053)
1508         {
1509                 tomTimerDivider = (tomTimerDivider & 0xFF00) | data;
1510                 TOMResetPIT();
1511                 return;
1512         }
1513         else if (offset >= 0xF00400 && offset <= 0xF007FF)      // CLUT (A & B)
1514         {
1515                 // Writing to one CLUT writes to the other
1516                 offset &= 0x5FF;                // Mask out $F00600 (restrict to $F00400-5FF)
1517                 tomRam8[offset] = data, tomRam8[offset + 0x200] = data;
1518         }
1519
1520 //      tomRam8[offset & 0x3FFF] = data;
1521 }
1522
1523
1524 //
1525 // TOM word access (write)
1526 //
1527 void TOMWriteWord(uint32_t offset, uint16_t data, uint32_t who/*=UNKNOWN*/)
1528 {
1529         // Moved here tentatively, so we can see everything written to TOM.
1530         tomRam8[(offset + 0) & 0x3FFF] = data >> 8;
1531         tomRam8[(offset + 1) & 0x3FFF] = data & 0xFF;
1532
1533 #ifdef TOM_DEBUG
1534         WriteLog("TOM: Writing byte %04X at %06X", data, offset);
1535 #endif
1536 //???Is this needed??? Yes, but we need to be more vigilant than this.
1537 #ifndef TOM_STRICT_MEMORY_ACCESS
1538         offset &= 0xFF3FFF;
1539 #else
1540         // "Fast" (32-bit only) write access to the GPU
1541 //      if ((offset >= 0xF0A100) && (offset <= 0xF0BFFF))
1542         if ((offset >= 0xF08000) && (offset <= 0xF0BFFF))
1543                 offset &= 0xFF7FFF;
1544 #endif
1545 #ifdef TOM_DEBUG
1546         WriteLog(" -->[%06X] by %s\n", offset, whoName[who]);
1547 #endif
1548
1549 #ifdef TOM_STRICT_MEMORY_ACCESS
1550         // Sanity check
1551         if ((offset < 0xF00000) || (offset > 0xF03FFF))
1552                 return;
1553 #endif
1554
1555 //if (offset == 0xF00000 + MEMCON1)
1556 //      WriteLog("TOM: Memory Configuration 1 written by %s: %04X\n", whoName[who], data);
1557 //if (offset == 0xF00000 + MEMCON2)
1558 //      WriteLog("TOM: Memory Configuration 2 written by %s: %04X\n", whoName[who], data);
1559 if (offset >= 0xF02000 && offset <= 0xF020FF)
1560         WriteLog("TOM: WriteWord attempted to GPU register file by %s (unimplemented)!\n", whoName[who]);
1561
1562         if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
1563         {
1564                 GPUWriteWord(offset, data, who);
1565                 return;
1566         }
1567         else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
1568         {
1569                 GPUWriteWord(offset, data, who);
1570                 return;
1571         }
1572 //What's so special about this?
1573 /*      else if ((offset >= 0xF00000) && (offset < 0xF00002))
1574         {
1575                 TOMWriteByte(offset, data >> 8);
1576                 TOMWriteByte(offset+1, data & 0xFF);
1577         }*/
1578 /*      else if ((offset >= 0xF00010) && (offset < 0xF00028))
1579         {
1580                 OPWriteWord(offset, data, who);
1581                 return;
1582         }*/
1583         else if (offset == 0xF00050)
1584         {
1585                 tomTimerPrescaler = data;
1586                 TOMResetPIT();
1587                 return;
1588         }
1589         else if (offset == 0xF00052)
1590         {
1591                 tomTimerDivider = data;
1592                 TOMResetPIT();
1593                 return;
1594         }
1595         else if (offset == 0xF000E0)
1596         {
1597 //Check this out...
1598                 if (data & 0x0100)
1599                         tom_video_int_pending = 0;
1600                 if (data & 0x0200)
1601                         tom_gpu_int_pending = 0;
1602                 if (data & 0x0400)
1603                         tom_object_int_pending = 0;
1604                 if (data & 0x0800)
1605                         tom_timer_int_pending = 0;
1606                 if (data & 0x1000)
1607                         tom_jerry_int_pending = 0;
1608
1609 //              return;
1610         }
1611         else if ((offset >= 0xF02200) && (offset <= 0xF0229F))
1612         {
1613                 BlitterWriteWord(offset, data, who);
1614                 return;
1615         }
1616         else if (offset >= 0xF00400 && offset <= 0xF007FE)      // CLUT (A & B)
1617         {
1618                 // Writing to one CLUT writes to the other
1619                 offset &= 0x5FF;                // Mask out $F00600 (restrict to $F00400-5FF)
1620 // Watch out for unaligned writes here! (Not fixed yet)
1621 #warning "!!! Watch out for unaligned writes here !!! FIX !!!"
1622                 SET16(tomRam8, offset, data);
1623                 SET16(tomRam8, offset + 0x200, data);
1624         }
1625
1626         offset &= 0x3FFF;
1627         if (offset == 0x28)                     // VMODE (Why? Why not OBF?)
1628 //Actually, we should check to see if the Enable bit of VMODE is set before doing this... !!! FIX !!!
1629 #warning "Actually, we should check to see if the Enable bit of VMODE is set before doing this... !!! FIX !!!"
1630                 objectp_running = 1;
1631
1632         if (offset >= 0x30 && offset <= 0x4E)
1633                 data &= 0x07FF;                 // These are (mostly) 11-bit registers
1634         if (offset == 0x2E || offset == 0x36 || offset == 0x54)
1635                 data &= 0x03FF;                 // These are all 10-bit registers
1636
1637 // Fix a lockup bug... :-P
1638 //      TOMWriteByte(0xF00000 | offset, data >> 8, who);
1639 //      TOMWriteByte(0xF00000 | (offset+1), data & 0xFF, who);
1640
1641 if (offset == MEMCON1)
1642         WriteLog("TOM: Memory Config 1 written by %s: $%04X\n", whoName[who], data);
1643 if (offset == MEMCON2)
1644         WriteLog("TOM: Memory Config 2 written by %s: $%04X\n", whoName[who], data);
1645 //if (offset == OLP)
1646 //      WriteLog("TOM: Object List Pointer written by %s: $%04X\n", whoName[who], data);
1647 //if (offset == OLP + 2)
1648 //      WriteLog("TOM: Object List Pointer +2 written by %s: $%04X\n", whoName[who], data);
1649 //if (offset == OBF)
1650 //      WriteLog("TOM: Object Processor Flag written by %s: %u\n", whoName[who], data);
1651 if (offset == VMODE)
1652         WriteLog("TOM: Video Mode written by %s: %04X. PWIDTH = %u, MODE = %s, flags:%s%s (VC = %u) (M68K PC = %06X)\n", whoName[who], data, ((data >> 9) & 0x07) + 1, videoMode_to_str[(data & MODE) >> 1], (data & BGEN ? " BGEN" : ""), (data & VARMOD ? " VARMOD" : ""), GET16(tomRam8, VC), m68k_get_reg(NULL, M68K_REG_PC));
1653 if (offset == BORD1)
1654         WriteLog("TOM: Border 1 written by %s: $%04X\n", whoName[who], data);
1655 if (offset == BORD2)
1656         WriteLog("TOM: Border 2 written by %s: $%04X\n", whoName[who], data);
1657 if (offset == HP)
1658         WriteLog("TOM: Horizontal Period written by %s: %u (+1*2 = %u)\n", whoName[who], data, (data + 1) * 2);
1659 if (offset == HBB)
1660         WriteLog("TOM: Horizontal Blank Begin written by %s: %u\n", whoName[who], data);
1661 if (offset == HBE)
1662         WriteLog("TOM: Horizontal Blank End written by %s: %u\n", whoName[who], data);
1663 if (offset == HS)
1664         WriteLog("TOM: Horizontal Sync written by %s: %u\n", whoName[who], data);
1665 if (offset == HVS)
1666         WriteLog("TOM: Horizontal Vertical Sync written by %s: %u\n", whoName[who], data);
1667 if (offset == HDB1)
1668         WriteLog("TOM: Horizontal Display Begin 1 written by %s: %u\n", whoName[who], data);
1669 if (offset == HDB2)
1670         WriteLog("TOM: Horizontal Display Begin 2 written by %s: %u\n", whoName[who], data);
1671 if (offset == HDE)
1672         WriteLog("TOM: Horizontal Display End written by %s: %u\n", whoName[who], data);
1673 if (offset == VP)
1674         WriteLog("TOM: Vertical Period written by %s: %u (%sinterlaced)\n", whoName[who], data, (data & 0x01 ? "non-" : ""));
1675 if (offset == VBB)
1676         WriteLog("TOM: Vertical Blank Begin written by %s: %u\n", whoName[who], data);
1677 if (offset == VBE)
1678         WriteLog("TOM: Vertical Blank End written by %s: %u\n", whoName[who], data);
1679 if (offset == VS)
1680         WriteLog("TOM: Vertical Sync written by %s: %u\n", whoName[who], data);
1681 if (offset == VDB)
1682         WriteLog("TOM: Vertical Display Begin written by %s: %u\n", whoName[who], data);
1683 if (offset == VDE)
1684         WriteLog("TOM: Vertical Display End written by %s: %u\n", whoName[who], data);
1685 if (offset == VEB)
1686         WriteLog("TOM: Vertical Equalization Begin written by %s: %u\n", whoName[who], data);
1687 if (offset == VEE)
1688         WriteLog("TOM: Vertical Equalization End written by %s: %u\n", whoName[who], data);
1689 if (offset == VI)
1690         WriteLog("TOM: Vertical Interrupt written by %s: %u\n", whoName[who], data);
1691 if (offset == PIT0)
1692         WriteLog("TOM: PIT0 written by %s: %u\n", whoName[who], data);
1693 if (offset == PIT1)
1694         WriteLog("TOM: PIT1 written by %s: %u\n", whoName[who], data);
1695 if (offset == HEQ)
1696         WriteLog("TOM: Horizontal Equalization End written by %s: %u\n", whoName[who], data);
1697 //if (offset == BG)
1698 //      WriteLog("TOM: Background written by %s: %u\n", whoName[who], data);
1699 //if (offset == INT1)
1700 //      WriteLog("TOM: CPU Interrupt Control written by %s: $%04X (%s%s%s%s%s)\n", whoName[who], data, (data & 0x01 ? "Video" : ""), (data & 0x02 ? " GPU" : ""), (data & 0x04 ? " OP" : ""), (data & 0x08 ? " TOMPIT" : ""), (data & 0x10 ? " Jerry" : ""));
1701
1702         // detect screen resolution changes
1703 //This may go away in the future, if we do the virtualized screen thing...
1704 //This may go away soon!
1705 // TOM Shouldn't be mucking around with this, it's up to the host system to properly
1706 // handle this kind of crap.
1707 // NOTE: This is needed somehow, need to get rid of the dependency on this crap.
1708 //       N.B.: It's used in the rendering functions... So...
1709 #warning "!!! Need to get rid of this dependency !!!"
1710 #if 1
1711         if ((offset >= 0x28) && (offset <= 0x4F))
1712         {
1713                 uint32_t width = TOMGetVideoModeWidth(), height = TOMGetVideoModeHeight();
1714
1715                 if ((width != tomWidth) || (height != tomHeight))
1716                 {
1717                         tomWidth = width, tomHeight = height;
1718
1719 #warning "!!! TOM: ResizeScreen commented out !!!"
1720 // No need to resize anything, since we're prepared for this...
1721 //                      if (vjs.renderType == RT_NORMAL)
1722 //                              ResizeScreen(tomWidth, tomHeight);
1723                 }
1724         }
1725 #endif
1726 }
1727
1728
1729 int TOMIRQEnabled(int irq)
1730 {
1731         // This is the correct byte in big endian... D'oh!
1732 //      return jaguar_byte_read(0xF000E1) & (1 << irq);
1733         return tomRam8[INT1 + 1/*0xE1*/] & (1 << irq);
1734 }
1735
1736
1737 // NEW:
1738 // TOM Programmable Interrupt Timer handler
1739 // NOTE: TOM's PIT is only enabled if the prescaler is != 0
1740 //       The PIT only generates an interrupt when it counts down to zero, not when loaded!
1741
1742 void TOMPITCallback(void);
1743
1744
1745 void TOMResetPIT(void)
1746 {
1747 #ifndef NEW_TIMER_SYSTEM
1748 //Probably should *add* this amount to the counter to retain cycle accuracy! !!! FIX !!! [DONE]
1749 //Also, why +1??? 'Cause that's what it says in the JTRM...!
1750 //There is a small problem with this approach: If both the prescaler and the divider are equal
1751 //to $FFFF then the counter won't be large enough to handle it. !!! FIX !!!
1752         if (tom_timer_prescaler)
1753                 tom_timer_counter += (1 + tom_timer_prescaler) * (1 + tom_timer_divider);
1754 //      WriteLog("tom: reseting timer to 0x%.8x (%i)\n",tom_timer_counter,tom_timer_counter);
1755 #else
1756         // Need to remove previous timer from the queue, if it exists...
1757         RemoveCallback(TOMPITCallback);
1758
1759         if (tomTimerPrescaler)
1760         {
1761                 double usecs = (float)(tomTimerPrescaler + 1) * (float)(tomTimerDivider + 1) * RISC_CYCLE_IN_USEC;
1762                 SetCallbackTime(TOMPITCallback, usecs);
1763         }
1764 #endif
1765 }
1766
1767
1768 //
1769 // TOM Programmable Interrupt Timer handler
1770 // NOTE: TOM's PIT is only enabled if the prescaler is != 0
1771 //
1772 //NOTE: This is only used by the old execution code... Safe to remove
1773 //      once the timer system is stable.
1774 void TOMExecPIT(uint32_t cycles)
1775 {
1776         if (tomTimerPrescaler)
1777         {
1778                 tomTimerCounter -= cycles;
1779
1780                 if (tomTimerCounter <= 0)
1781                 {
1782                         TOMSetPendingTimerInt();
1783                         GPUSetIRQLine(GPUIRQ_TIMER, ASSERT_LINE);       // GPUSetIRQLine does the 'IRQ enabled' checking
1784
1785                         if (TOMIRQEnabled(IRQ_TIMER))
1786                                 m68k_set_irq(2);                                // Cause a 68000 IPL 2...
1787
1788                         TOMResetPIT();
1789                 }
1790         }
1791 }
1792
1793
1794 void TOMPITCallback(void)
1795 {
1796 //      INT1_RREG |= 0x08;                                                      // Set TOM PIT interrupt pending
1797         TOMSetPendingTimerInt();
1798     GPUSetIRQLine(GPUIRQ_TIMER, ASSERT_LINE);   // It does the 'IRQ enabled' checking
1799
1800 //      if (INT1_WREG & 0x08)
1801         if (TOMIRQEnabled(IRQ_TIMER))
1802                 m68k_set_irq(2);                                                // Generate a 68K IPL 2...
1803
1804         TOMResetPIT();
1805 }
1806