]> Shamusworld >> Repos - virtualjaguar/blob - src/tom.cpp
Fixed controller profile system.
[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 & 0x003F) << 18)                                  // Green
581                         | ((i & 0x07C0) << 5);                                  // Blue
582
583         for(uint32_t i=0; i<0x10000; i++)
584         {
585                 uint32_t cyan = (i & 0xF000) >> 12,
586                         red = (i & 0x0F00) >> 8,
587                         intensity = (i & 0x00FF);
588
589                 uint32_t r = (((uint32_t)redcv[cyan][red]) * intensity) >> 8,
590                         g = (((uint32_t)greencv[cyan][red]) * intensity) >> 8,
591                         b = (((uint32_t)bluecv[cyan][red]) * intensity) >> 8;
592
593 //hm.           CRY16ToRGB32[i] = 0xFF000000 | (b << 16) | (g << 8) | r;
594                 CRY16ToRGB32[i] = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
595                 MIX16ToRGB32[i] = (i & 0x01 ? RGB16ToRGB32[i] : CRY16ToRGB32[i]);
596         }
597 }
598
599
600 void TOMSetPendingJERRYInt(void)
601 {
602         tom_jerry_int_pending = 1;
603 }
604
605
606 void TOMSetPendingTimerInt(void)
607 {
608         tom_timer_int_pending = 1;
609 }
610
611
612 void TOMSetPendingObjectInt(void)
613 {
614         tom_object_int_pending = 1;
615 }
616
617
618 void TOMSetPendingGPUInt(void)
619 {
620         tom_gpu_int_pending = 1;
621 }
622
623
624 void TOMSetPendingVideoInt(void)
625 {
626         tom_video_int_pending = 1;
627 }
628
629
630 uint8_t * TOMGetRamPointer(void)
631 {
632         return tomRam8;
633 }
634
635
636 uint8_t TOMGetVideoMode(void)
637 {
638         uint16_t vmode = GET16(tomRam8, VMODE);
639         return ((vmode & VARMOD) >> 6) | ((vmode & MODE) >> 1);
640 }
641
642
643 //Used in only one place (and for debug purposes): OBJECTP.CPP
644 #warning "Used in only one place (and for debug purposes): OBJECTP.CPP !!! FIX !!!"
645 uint16_t TOMGetVDB(void)
646 {
647         return GET16(tomRam8, VDB);
648 }
649
650
651 #define LEFT_BG_FIX
652 //
653 // 16 BPP CRY/RGB mixed mode rendering
654 //
655 void tom_render_16bpp_cry_rgb_mix_scanline(uint32_t * backbuffer)
656 {
657 //CHANGED TO 32BPP RENDERING
658         uint16_t width = tomWidth;
659         uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
660
661         //New stuff--restrict our drawing...
662         uint8_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
663         //NOTE: May have to check HDB2 as well!
664         // Get start position in HC ticks
665         int16_t startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL);
666         // Convert to pixels
667         startPos /= pwidth;
668
669         if (startPos < 0)
670                 // This is x2 because current_line_buffer is uint8_t & we're in a 16bpp mode
671                 current_line_buffer += 2 * -startPos;
672         else
673 //This case doesn't properly handle the "start on the right side of virtual screen" case
674 //Dunno why--looks Ok...
675 //What *is* for sure wrong is that it doesn't copy the linebuffer's BG pixels... [FIXED NOW]
676 //This should likely be 4 instead of 2 (?--not sure)
677 // Actually, there should be NO multiplier, as startPos is expressed in PIXELS
678 // and so is the backbuffer.
679 #ifdef LEFT_BG_FIX
680         {
681                 uint8_t g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
682                 uint32_t pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
683
684                 for(int16_t i=0; i<startPos; i++)
685                         *backbuffer++ = pixel;
686
687                 width -= startPos;
688         }
689 #else
690                 backbuffer += 2 * startPos, width -= startPos;
691 #endif
692
693         while (width)
694         {
695                 uint16_t color = (*current_line_buffer++) << 8;
696                 color |= *current_line_buffer++;
697                 *backbuffer++ = MIX16ToRGB32[color];
698                 width--;
699         }
700 }
701
702
703 //
704 // 16 BPP CRY mode rendering
705 //
706 void tom_render_16bpp_cry_scanline(uint32_t * backbuffer)
707 {
708 //CHANGED TO 32BPP RENDERING
709         uint16_t width = tomWidth;
710         uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
711
712         //New stuff--restrict our drawing...
713         uint8_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
714         //NOTE: May have to check HDB2 as well!
715         int16_t startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL);// Get start position in HC ticks
716         startPos /= pwidth;
717         if (startPos < 0)
718                 current_line_buffer += 2 * -startPos;
719         else
720 #ifdef LEFT_BG_FIX
721         {
722                 uint8_t g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
723                 uint32_t pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
724
725                 for(int16_t i=0; i<startPos; i++)
726                         *backbuffer++ = pixel;
727
728                 width -= startPos;
729         }
730 #else
731 //This should likely be 4 instead of 2 (?--not sure)
732                 backbuffer += 2 * startPos, width -= startPos;
733 #endif
734
735         while (width)
736         {
737                 uint16_t color = (*current_line_buffer++) << 8;
738                 color |= *current_line_buffer++;
739                 *backbuffer++ = CRY16ToRGB32[color];
740                 width--;
741         }
742 }
743
744
745 //
746 // 24 BPP mode rendering
747 //
748 void tom_render_24bpp_scanline(uint32_t * backbuffer)
749 {
750 //CHANGED TO 32BPP RENDERING
751         uint16_t width = tomWidth;
752         uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
753
754         //New stuff--restrict our drawing...
755         uint8_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
756         //NOTE: May have to check HDB2 as well!
757         int16_t startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL);       // Get start position in HC ticks
758         startPos /= pwidth;
759         if (startPos < 0)
760                 current_line_buffer += 4 * -startPos;
761         else
762 #ifdef LEFT_BG_FIX
763         {
764                 uint8_t g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
765                 uint32_t pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
766
767                 for(int16_t i=0; i<startPos; i++)
768                         *backbuffer++ = pixel;
769
770                 width -= startPos;
771         }
772 #else
773 //This should likely be 4 instead of 2 (?--not sure)
774                 backbuffer += 2 * startPos, width -= startPos;
775 #endif
776
777         while (width)
778         {
779                 uint32_t g = *current_line_buffer++;
780                 uint32_t r = *current_line_buffer++;
781                 current_line_buffer++;
782                 uint32_t b = *current_line_buffer++;
783 //hm.           *backbuffer++ = 0xFF000000 | (b << 16) | (g << 8) | r;
784                 *backbuffer++ = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
785                 width--;
786         }
787 }
788
789
790 //Seems to me that this is NOT a valid mode--the JTRM seems to imply that you would need
791 //extra hardware outside of the Jaguar console to support this!
792 //
793 // 16 BPP direct mode rendering
794 //
795 void tom_render_16bpp_direct_scanline(uint32_t * backbuffer)
796 {
797         uint16_t width = tomWidth;
798         uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
799
800         while (width)
801         {
802                 uint16_t color = (*current_line_buffer++) << 8;
803                 color |= *current_line_buffer++;
804                 *backbuffer++ = color >> 1;
805                 width--;
806         }
807 }
808
809
810 //
811 // 16 BPP RGB mode rendering
812 //
813 void tom_render_16bpp_rgb_scanline(uint32_t * backbuffer)
814 {
815 //CHANGED TO 32BPP RENDERING
816         // 16 BPP RGB: 0-5 green, 6-10 blue, 11-15 red
817
818         uint16_t width = tomWidth;
819         uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
820
821         //New stuff--restrict our drawing...
822         uint8_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
823         //NOTE: May have to check HDB2 as well!
824         int16_t startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL);       // Get start position in HC ticks
825         startPos /= pwidth;
826
827         if (startPos < 0)
828                 current_line_buffer += 2 * -startPos;
829         else
830 #ifdef LEFT_BG_FIX
831         {
832                 uint8_t g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
833                 uint32_t pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
834
835                 for(int16_t i=0; i<startPos; i++)
836                         *backbuffer++ = pixel;
837
838                 width -= startPos;
839         }
840 #else
841 //This should likely be 4 instead of 2 (?--not sure)
842                 backbuffer += 2 * startPos, width -= startPos;
843 #endif
844
845         while (width)
846         {
847                 uint32_t color = (*current_line_buffer++) << 8;
848                 color |= *current_line_buffer++;
849                 *backbuffer++ = RGB16ToRGB32[color];
850                 width--;
851         }
852 }
853
854
855 //
856 // Process a single scanline
857 // (this is bad terminology; each tick of the VC is actually a half-line)
858 //
859 void TOMExecHalfline(uint16_t halfline, bool render)
860 {
861 #warning "!!! Need to handle multiple fields properly !!!"
862         // We ignore the problem for now
863         halfline &= 0x7FF;
864
865         bool inActiveDisplayArea = true;
866
867 //Interlacing is still not handled correctly here... !!! FIX !!!
868         if (halfline & 0x01)                                                    // Execute OP only on even halflines (non-interlaced only!)
869                 return;
870
871 //Hm, it seems that the OP needs to execute from zero, so let's try it:
872 // And it works! But need to do some optimizations in the OP to keep it from attempting
873 // to do a scanline render in the non-display area... [DONE]
874 //this seems to cause a regression in certain games, like rayman
875 //which means I have to dig thru the asic nets to see what's wrong...
876 /*
877 No, the OP doesn't start until VDB, that much is certain. The thing is, VDB is the
878 HALF line that the OP starts on--which means that it needs to start at VDB / 2!!!
879
880 Hrm, doesn't seem to be enough, though it should be... still sticks for 20 frames.
881
882
883 What triggers this is writing $FFFF to VDE. This causes the OP start signal in VID to 
884 latch on, which in effect sets VDB to zero. So that much is correct. But the thing with
885 Rayman is that it shouldn't cause the graphical glitches seen there, so still have to
886 investigate what's going on there. By all rights, it shouldn't glitch because:
887
888 00006C00: 0000000D 82008F73 (BRANCH) YPOS=494, CC=">", link=$00006C10
889 00006C08: 000003FF 00008173 (BRANCH) YPOS=46, CC=">", link=$001FF800
890 00006C10: 00000000 0000000C (STOP)
891 001FF800: 12FC2BFF 02380000 (BITMAP)
892           00008004 8180CFF1
893
894 Even if the OP is running all the time, the link should tell it to stop at the right
895 place (which it seems to do). But we still get glitchy screen.
896
897 Seems the glitchy screen went away... Maybe the GPU alignment fixes fixed it???
898 Just need to add the proper checking here then.
899
900 Some numbers, courtesy of the Jaguar BIOS:
901 // NTSC:
902 VP, 523                 // Vertical Period (1-based; in this case VP = 524)
903 VBE, 24                 // Vertical Blank End
904 VDB, 38                 // Vertical Display Begin
905 VDE, 518                // Vertical Display End
906 VBB, 500                // Vertical Blank Begin
907 VS, 517                 // Vertical Sync
908
909 // PAL Jaguar
910 VP, 623                 // Vertical Period (1-based; in this case VP = 624)
911 VBE, 34                 // Vertical Blank End
912 VDB, 38                 // Vertical Display Begin
913 VDE, 518                // Vertical Display End
914 VBB, 600                // Vertical Blank Begin
915 VS, 618                 // Vertical Sync
916
917 Numbers for KM, NTSC:
918 KM: (Note that with VDE <= 507, the OP starts at VDB as expected)
919 TOM: Vertical Display Begin written by M68K: 41
920 TOM: Vertical Display End written by M68K: 2047
921 TOM: Vertical Interrupt written by M68K: 491
922 */
923 #if 1
924         // Initial values that "well behaved" programs use
925         uint16_t startingHalfline = GET16(tomRam8, VDB);
926         uint16_t endingHalfline = GET16(tomRam8, VDE);
927
928         // Simulate the OP start bug here!
929         // Really, this value is somewhere around 507 for an NTSC Jaguar. But this
930         // should work in a majority of cases, at least until we can figure it out properly.
931         if (endingHalfline > GET16(tomRam8, VP))
932                 startingHalfline = 0;
933
934         if (halfline >= startingHalfline && halfline < endingHalfline)
935 //      if (halfline >= 0 && halfline < (uint16_t)GET16(tomRam8, VDE))
936 // 16 isn't enough, and neither is 32 for raptgun. 32 fucks up Rayman
937 //      if (halfline >= ((uint16_t)GET16(tomRam8, VDB) / 2) && halfline < ((uint16_t)GET16(tomRam8, VDE) / 2))
938 //      if (halfline >= ((uint16_t)GET16(tomRam8, VDB) - 16) && halfline < (uint16_t)GET16(tomRam8, VDE))
939 //      if (halfline >= 20 && halfline < (uint16_t)GET16(tomRam8, VDE))
940 //      if (halfline >= (uint16_t)GET16(tomRam8, VDB) && halfline < (uint16_t)GET16(tomRam8, VDE))
941         {
942                 if (render)
943                 {
944                         uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
945                         uint8_t bgHI = tomRam8[BG], bgLO = tomRam8[BG + 1];
946
947                         // Clear line buffer with BG
948                         if (GET16(tomRam8, VMODE) & BGEN) // && (CRY or RGB16)...
949                                 for(uint32_t i=0; i<720; i++)
950                                         *current_line_buffer++ = bgHI, *current_line_buffer++ = bgLO;
951
952                         OPProcessList(halfline, render);
953                 }
954         }
955         else
956                 inActiveDisplayArea = false;
957 #else
958         inActiveDisplayArea =
959                 (halfline >= (uint16_t)GET16(tomRam8, VDB) && halfline < (uint16_t)GET16(tomRam8, VDE)
960                         ? true : false);
961
962         if (halfline < (uint16_t)GET16(tomRam8, VDE))
963         {
964                 if (render)//With JaguarExecuteNew() this is always true...
965                 {
966                         uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
967                         uint8_t bgHI = tomRam8[BG], bgLO = tomRam8[BG + 1];
968
969                         // Clear line buffer with BG
970                         if (GET16(tomRam8, VMODE) & BGEN) // && (CRY or RGB16)...
971                                 for(uint32_t i=0; i<720; i++)
972                                         *current_line_buffer++ = bgHI, *current_line_buffer++ = bgLO;
973
974 //                      OPProcessList(halfline, render);
975 //This seems to take care of it...
976                         OPProcessList(halfline, inActiveDisplayArea);
977                 }
978         }
979 #endif
980
981         // Try to take PAL into account... [We do now!]
982
983         uint16_t topVisible = (vjs.hardwareTypeNTSC ? TOP_VISIBLE_VC : TOP_VISIBLE_VC_PAL),
984                 bottomVisible = (vjs.hardwareTypeNTSC ? BOTTOM_VISIBLE_VC : BOTTOM_VISIBLE_VC_PAL);
985         uint32_t * TOMCurrentLine = &(screenBuffer[((halfline - topVisible) / 2) * screenPitch]);
986
987         // Here's our virtualized scanline code...
988
989         if (halfline >= topVisible && halfline < bottomVisible)
990         {
991                 if (inActiveDisplayArea)
992                 {
993 //NOTE: The following doesn't put BORDER color on the sides... !!! FIX !!!
994 #warning "The following doesn't put BORDER color on the sides... !!! FIX !!!"
995                         if (vjs.renderType == RT_NORMAL)
996 //                              scanline_render[TOMGetVideoMode()](TOMBackbuffer);
997                                 scanline_render[TOMGetVideoMode()](TOMCurrentLine);
998                         else//TV type render
999                         {
1000 /*
1001         tom_render_16bpp_cry_scanline,
1002         tom_render_24bpp_scanline,
1003         tom_render_16bpp_direct_scanline,
1004         tom_render_16bpp_rgb_scanline,
1005         tom_render_16bpp_cry_rgb_mix_scanline,
1006         tom_render_24bpp_scanline,
1007         tom_render_16bpp_direct_scanline,
1008         tom_render_16bpp_rgb_scanline
1009 #define VMODE           0x28
1010 #define   MODE          0x0006          // Line buffer to video generator mode
1011 #define   VARMOD        0x0100          // Mixed CRY/RGB16 mode (only works in MODE 0!)
1012 */
1013                                 uint8_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
1014                                 uint8_t mode = ((GET16(tomRam8, VMODE) & MODE) >> 1);
1015                                 bool varmod = GET16(tomRam8, VMODE) & VARMOD;
1016 //The video texture line buffer ranges from 0 to 1279, with its left edge starting at
1017 //LEFT_VISIBLE_HC. So, we need to start writing into the backbuffer at HDB1, using pwidth
1018 //as our scaling factor. The way it generates its image on a real TV!
1019
1020 //So, for example, if HDB1 is less than LEFT_VISIBLE_HC, then we have to figure out where
1021 //in the VTLB that we start writing pixels from the Jaguar line buffer (VTLB start=0,
1022 //JLB=something).
1023 #if 0
1024 //
1025 // 24 BPP mode rendering
1026 //
1027 void tom_render_24bpp_scanline(uint32_t * backbuffer)
1028 {
1029 //CHANGED TO 32BPP RENDERING
1030         uint16_t width = tomWidth;
1031         uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
1032
1033         //New stuff--restrict our drawing...
1034         uint8_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
1035         //NOTE: May have to check HDB2 as well!
1036         int16_t startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL);       // Get start position in HC ticks
1037         startPos /= pwidth;
1038         if (startPos < 0)
1039                 current_line_buffer += 4 * -startPos;
1040         else
1041 //This should likely be 4 instead of 2 (?--not sure)
1042                 backbuffer += 2 * startPos, width -= startPos;
1043
1044         while (width)
1045         {
1046                 uint32_t g = *current_line_buffer++;
1047                 uint32_t r = *current_line_buffer++;
1048                 current_line_buffer++;
1049                 uint32_t b = *current_line_buffer++;
1050                 *backbuffer++ = 0xFF000000 | (b << 16) | (g << 8) | r;
1051                 width--;
1052         }
1053 }
1054 #endif
1055
1056                         }
1057                 }
1058                 else
1059                 {
1060                         // If outside of VDB & VDE, then display the border color
1061                         uint32_t * currentLineBuffer = TOMCurrentLine;
1062                         uint8_t g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
1063 //Hm.                   uint32_t pixel = 0xFF000000 | (b << 16) | (g << 8) | r;
1064                         uint32_t pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
1065
1066                         for(uint32_t i=0; i<tomWidth; i++)
1067                                 *currentLineBuffer++ = pixel;
1068                 }
1069         }
1070 }
1071
1072
1073 //
1074 // TOM initialization
1075 //
1076 void TOMInit(void)
1077 {
1078         TOMFillLookupTables();
1079         OPInit();
1080         BlitterInit();
1081         TOMReset();
1082 }
1083
1084
1085 void TOMDone(void)
1086 {
1087         TOMDumpIORegistersToLog();
1088         OPDone();
1089         BlitterDone();
1090         WriteLog("TOM: Resolution %i x %i %s\n", TOMGetVideoModeWidth(), TOMGetVideoModeHeight(),
1091                 videoMode_to_str[TOMGetVideoMode()]);
1092 //      WriteLog("\ntom: object processor:\n");
1093 //      WriteLog("tom: pointer to object list: 0x%.8x\n",op_get_list_pointer());
1094 //      WriteLog("tom: INT1=0x%.2x%.2x\n",TOMReadByte(0xf000e0),TOMReadByte(0xf000e1));
1095 }
1096
1097
1098 uint32_t TOMGetVideoModeWidth(void)
1099 {
1100         //These widths are pretty bogus. Should use HDB1/2 & HDE/HBB & PWIDTH to calc the width...
1101 //      uint32_t width[8] = { 1330, 665, 443, 332, 266, 222, 190, 166 };
1102 //Temporary, for testing Doom...
1103 //      uint32_t width[8] = { 1330, 665, 443, 332, 266, 222, 190, 332 };
1104
1105         // Note that the following PWIDTH values have the following pixel aspect ratios:
1106         // PWIDTH = 1 -> 0.25:1 (1:4) pixels (X:Y ratio)
1107         // PWIDTH = 2 -> 0.50:1 (1:2) pixels
1108         // PWIDTH = 3 -> 0.75:1 (3:4) pixels
1109         // PWIDTH = 4 -> 1.00:1 (1:1) pixels
1110         // PWIDTH = 5 -> 1.25:1 (5:4) pixels
1111         // PWIDTH = 6 -> 1.50:1 (3:2) pixels
1112         // PWIDTH = 7 -> 1.75:1 (7:4) pixels
1113         // PWIDTH = 8 -> 2.00:1 (2:1) pixels
1114
1115         // Also note that the JTRM says that PWIDTH of 4 gives pixels that are "about" square--
1116         // this implies that the other modes have pixels that are *not* square!
1117         // Also, I seriously doubt that you will see any games that use PWIDTH = 1!
1118
1119         // NOTE: Even though the PWIDTH value is + 1, here we're using a zero-based index and
1120         //       so we don't bother to add one...
1121 //      return width[(GET16(tomRam8, VMODE) & PWIDTH) >> 9];
1122
1123         // Now, we just calculate it...
1124 /*      uint16_t hdb1 = GET16(tomRam8, HDB1), hde = GET16(tomRam8, HDE),
1125                 hbb = GET16(tomRam8, HBB), pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
1126 //      return ((hbb < hde ? hbb : hde) - hdb1) / pwidth;
1127 //Temporary, for testing Doom...
1128         return ((hbb < hde ? hbb : hde) - hdb1) / (pwidth == 8 ? 4 : pwidth);*/
1129
1130         // To make it easier to make a quasi-fixed display size, we restrict the viewing
1131         // area to an arbitrary range of the Horizontal Count.
1132         uint16_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
1133         return (vjs.hardwareTypeNTSC ? RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC : RIGHT_VISIBLE_HC_PAL - LEFT_VISIBLE_HC_PAL) / pwidth;
1134 //Temporary, for testing Doom...
1135 //      return (RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC) / (pwidth == 8 ? 4 : pwidth);
1136 ////    return (RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC) / (pwidth == 4 ? 8 : pwidth);
1137
1138 // More speculating...
1139 // According to the JTRM, the number of potential pixels across is given by the
1140 // Horizontal Period (HP - in NTSC this is 845). The Horizontal Count counts from
1141 // zero to this value twice per scanline (the high bit is set on the second count).
1142 // HBE and HBB define the absolute "black" limits of the screen, while HDB1/2 and
1143 // HDE determine the extent of the OP "on" time. I.e., when the OP is turned on by
1144 // HDB1, it starts fetching the line from position 0 in LBUF.
1145
1146 // The trick, it would seem, is to figure out how long the typical visible scanline
1147 // of a TV is in HP ticks and limit the visible area to that (divided by PWIDTH, of
1148 // course). Using that length, we can establish an "absolute left display limit" with
1149 // which to measure HBB & HDB1/2 against when rendering LBUF (i.e., if HDB1 is 20 ticks
1150 // to the right of the ALDL and PWIDTH is 4, then start writing the LBUF starting at
1151 // backbuffer + 5 pixels).
1152
1153 // That's basically what we're doing now...!
1154 }
1155
1156
1157 // *** SPECULATION ***
1158 // It might work better to virtualize the height settings, i.e., set the vertical
1159 // height at 240 lines and clip using the VDB and VDE/VP registers...
1160 // Same with the width... [Width is pretty much virtualized now.]
1161
1162 // Now that that the width is virtualized, let's virtualize the height. :-)
1163 uint32_t TOMGetVideoModeHeight(void)
1164 {
1165 //      uint16_t vmode = GET16(tomRam8, VMODE);
1166 //      uint16_t vbe = GET16(tomRam8, VBE);
1167 //      uint16_t vbb = GET16(tomRam8, VBB);
1168 //      uint16_t vdb = GET16(tomRam8, VDB);
1169 //      uint16_t vde = GET16(tomRam8, VDE);
1170 //      uint16_t vp = GET16(tomRam8, VP);
1171
1172 /*      if (vde == 0xFFFF)
1173                 vde = vbb;//*/
1174
1175 //      return 227;//WAS:(vde/*-vdb*/) >> 1;
1176         // The video mode height probably works this way:
1177         // VC counts from 0 to VP. VDB starts the OP. Either when
1178         // VDE is reached or VP, the OP is stopped. Let's try it...
1179         // Also note that we're conveniently ignoring interlaced display modes...!
1180 //      return ((vde > vp ? vp : vde) - vdb) >> 1;
1181 //      return ((vde > vbb ? vbb : vde) - vdb) >> 1;
1182 //Let's try from the Vertical Blank interval...
1183 //Seems to work OK!
1184 //      return (vbb - vbe) >> 1;        // Again, doesn't take interlacing into account...
1185 // This of course doesn't take interlacing into account. But I haven't seen any
1186 // Jaguar software that takes advantage of it either...
1187 //Also, doesn't reflect PAL Jaguar either... !!! FIX !!! [DONE]
1188 //      return 240;                                                                             // Set virtual screen height to 240 lines...
1189         return (vjs.hardwareTypeNTSC ? 240 : 256);
1190 }
1191
1192
1193 //
1194 // TOM reset code
1195 // Now PAL friendly!
1196 //
1197 /*
1198 The values in TOMReset come from the Jaguar BIOS.
1199 These values are from BJL:
1200
1201 NSTC:
1202 CLK2     181
1203 HP               844
1204 HBB              1713
1205 HBE              125
1206 HS               1741
1207 HVS              651
1208 HEQ              784
1209 HDE              1696
1210 HDB1     166
1211 HDB2     166
1212 VP               523
1213 VEE              6
1214 VBE              24
1215 VDB              46
1216 VDE              496
1217 VBB              500
1218 VEB              511
1219 VS               517
1220
1221 PAL:
1222 CLK2     226
1223 HP               850
1224 HBB              1711
1225 HBE              158
1226 HS               1749
1227 HVS              601
1228 HEQ              787
1229 HDE              1696
1230 HDB1     166
1231 HDB2     166
1232 VP               625
1233 VEE              6
1234 VBE              34
1235 VDB              46
1236 VDE              429
1237 VBB              600
1238 VEB              613
1239 VS               618
1240 */
1241 void TOMReset(void)
1242 {
1243         OPReset();
1244         BlitterReset();
1245         memset(tomRam8, 0x00, 0x4000);
1246
1247         if (vjs.hardwareTypeNTSC)
1248         {
1249                 SET16(tomRam8, MEMCON1, 0x1861);
1250 //              SET16(tomRam8, MEMCON1, 0x1865);//Bunch of BS
1251                 SET16(tomRam8, MEMCON2, 0x35CC);
1252                 SET16(tomRam8, HP, 844);                        // Horizontal Period (1-based; HP=845)
1253                 SET16(tomRam8, HBB, 1713);                      // Horizontal Blank Begin
1254                 SET16(tomRam8, HBE, 125);                       // Horizontal Blank End
1255                 SET16(tomRam8, HDE, 1665);                      // Horizontal Display End
1256                 SET16(tomRam8, HDB1, 203);                      // Horizontal Display Begin 1
1257                 SET16(tomRam8, VP, 523);                        // Vertical Period (1-based; in this case VP = 524)
1258                 SET16(tomRam8, VBE, 24);                        // Vertical Blank End
1259                 SET16(tomRam8, VDB, 38);                        // Vertical Display Begin
1260                 SET16(tomRam8, VDE, 518);                       // Vertical Display End
1261                 SET16(tomRam8, VBB, 500);                       // Vertical Blank Begin
1262                 SET16(tomRam8, VS, 517);                        // Vertical Sync
1263                 SET16(tomRam8, VMODE, 0x06C1);
1264         }
1265         else    // PAL Jaguar
1266         {
1267                 SET16(tomRam8, MEMCON1, 0x1861);
1268                 SET16(tomRam8, MEMCON2, 0x35CC);
1269                 SET16(tomRam8, HP, 850);                        // Horizontal Period
1270                 SET16(tomRam8, HBB, 1711);                      // Horizontal Blank Begin
1271                 SET16(tomRam8, HBE, 158);                       // Horizontal Blank End
1272                 SET16(tomRam8, HDE, 1665);                      // Horizontal Display End
1273                 SET16(tomRam8, HDB1, 203);                      // Horizontal Display Begin 1
1274                 SET16(tomRam8, VP, 623);                        // Vertical Period (1-based; in this case VP = 624)
1275                 SET16(tomRam8, VBE, 34);                        // Vertical Blank End
1276                 SET16(tomRam8, VDB, 38);                        // Vertical Display Begin
1277                 SET16(tomRam8, VDE, 518);                       // Vertical Display End
1278                 SET16(tomRam8, VBB, 600);                       // Vertical Blank Begin
1279                 SET16(tomRam8, VS, 618);                        // Vertical Sync
1280                 SET16(tomRam8, VMODE, 0x06C1);
1281         }
1282
1283         tomWidth = 0;
1284         tomHeight = 0;
1285
1286         tom_jerry_int_pending = 0;
1287         tom_timer_int_pending = 0;
1288         tom_object_int_pending = 0;
1289         tom_gpu_int_pending = 0;
1290         tom_video_int_pending = 0;
1291
1292         tomTimerPrescaler = 0;                                  // TOM PIT is disabled
1293         tomTimerDivider = 0;
1294         tomTimerCounter = 0;
1295 }
1296
1297
1298 //
1299 // Dump all TOM register values to the log
1300 //
1301 void TOMDumpIORegistersToLog(void)
1302 {
1303         WriteLog("\n\n---------------------------------------------------------------------\n");
1304         WriteLog("TOM I/O Registers\n");
1305         WriteLog("---------------------------------------------------------------------\n");
1306         WriteLog("F000%02X (MEMCON1): $%04X\n", MEMCON1, GET16(tomRam8, MEMCON1));
1307         WriteLog("F000%02X (MEMCON2): $%04X\n", MEMCON2, GET16(tomRam8, MEMCON2));
1308         WriteLog("F000%02X      (HC): $%04X\n", HC,      GET16(tomRam8, HC));
1309         WriteLog("F000%02X      (VC): $%04X\n", VC,      GET16(tomRam8, VC));
1310         WriteLog("F000%02X     (OLP): $%08X\n", OLP,     GET32(tomRam8, OLP));
1311         WriteLog("F000%02X     (OBF): $%04X\n", OBF,     GET16(tomRam8, OBF));
1312         WriteLog("F000%02X   (VMODE): $%04X\n", VMODE,   GET16(tomRam8, VMODE));
1313         WriteLog("F000%02X   (BORD1): $%04X\n", BORD1,   GET16(tomRam8, BORD1));
1314         WriteLog("F000%02X   (BORD2): $%04X\n", BORD2,   GET16(tomRam8, BORD2));
1315         WriteLog("F000%02X      (HP): $%04X\n", HP,      GET16(tomRam8, HP));
1316         WriteLog("F000%02X     (HBB): $%04X\n", HBB,     GET16(tomRam8, HBB));
1317         WriteLog("F000%02X     (HBE): $%04X\n", HBE,     GET16(tomRam8, HBE));
1318         WriteLog("F000%02X      (HS): $%04X\n", HS,      GET16(tomRam8, HS));
1319         WriteLog("F000%02X     (HVS): $%04X\n", HVS,     GET16(tomRam8, HVS));
1320         WriteLog("F000%02X    (HDB1): $%04X\n", HDB1,    GET16(tomRam8, HDB1));
1321         WriteLog("F000%02X    (HDB2): $%04X\n", HDB2,    GET16(tomRam8, HDB2));
1322         WriteLog("F000%02X     (HDE): $%04X\n", HDE,     GET16(tomRam8, HDE));
1323         WriteLog("F000%02X      (VP): $%04X\n", VP,      GET16(tomRam8, VP));
1324         WriteLog("F000%02X     (VBB): $%04X\n", VBB,     GET16(tomRam8, VBB));
1325         WriteLog("F000%02X     (VBE): $%04X\n", VBE,     GET16(tomRam8, VBE));
1326         WriteLog("F000%02X      (VS): $%04X\n", VS,      GET16(tomRam8, VS));
1327         WriteLog("F000%02X     (VDB): $%04X\n", VDB,     GET16(tomRam8, VDB));
1328         WriteLog("F000%02X     (VDE): $%04X\n", VDE,     GET16(tomRam8, VDE));
1329         WriteLog("F000%02X     (VEB): $%04X\n", VEB,     GET16(tomRam8, VEB));
1330         WriteLog("F000%02X     (VEE): $%04X\n", VEE,     GET16(tomRam8, VEE));
1331         WriteLog("F000%02X      (VI): $%04X\n", VI,      GET16(tomRam8, VI));
1332         WriteLog("F000%02X    (PIT0): $%04X\n", PIT0,    GET16(tomRam8, PIT0));
1333         WriteLog("F000%02X    (PIT1): $%04X\n", PIT1,    GET16(tomRam8, PIT1));
1334         WriteLog("F000%02X     (HEQ): $%04X\n", HEQ,     GET16(tomRam8, HEQ));
1335         WriteLog("F000%02X      (BG): $%04X\n", BG,      GET16(tomRam8, BG));
1336         WriteLog("F000%02X    (INT1): $%04X\n", INT1,    GET16(tomRam8, INT1));
1337         WriteLog("F000%02X    (INT2): $%04X\n", INT2,    GET16(tomRam8, INT2));
1338         WriteLog("---------------------------------------------------------------------\n\n\n");
1339 }
1340
1341
1342 //
1343 // TOM byte access (read)
1344 //
1345 uint8_t TOMReadByte(uint32_t offset, uint32_t who/*=UNKNOWN*/)
1346 {
1347 //???Is this needed???
1348 // It seems so. Perhaps it's the +$8000 offset being written to (32-bit interface)?
1349 // However, the 32-bit interface is WRITE ONLY, so that can't be it...
1350 // Also, the 68K CANNOT make use of the 32-bit interface, since its bus width is only 16-bits...
1351 //      offset &= 0xFF3FFF;
1352
1353 #ifdef TOM_DEBUG
1354         WriteLog("TOM: Reading byte at %06X for %s\n", offset, whoName[who]);
1355 #endif
1356
1357         if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
1358                 return GPUReadByte(offset, who);
1359         else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
1360                 return GPUReadByte(offset, who);
1361 /*      else if ((offset >= 0xF00010) && (offset < 0xF00028))
1362                 return OPReadByte(offset, who);*/
1363         else if ((offset >= 0xF02200) && (offset < 0xF022A0))
1364                 return BlitterReadByte(offset, who);
1365         else if (offset == 0xF00050)
1366                 return tomTimerPrescaler >> 8;
1367         else if (offset == 0xF00051)
1368                 return tomTimerPrescaler & 0xFF;
1369         else if (offset == 0xF00052)
1370                 return tomTimerDivider >> 8;
1371         else if (offset == 0xF00053)
1372                 return tomTimerDivider & 0xFF;
1373
1374         return tomRam8[offset & 0x3FFF];
1375 }
1376
1377
1378 //
1379 // TOM word access (read)
1380 //
1381 uint16_t TOMReadWord(uint32_t offset, uint32_t who/*=UNKNOWN*/)
1382 {
1383 //???Is this needed???
1384 //      offset &= 0xFF3FFF;
1385 #ifdef TOM_DEBUG
1386         WriteLog("TOM: Reading word at %06X for %s\n", offset, whoName[who]);
1387 #endif
1388 if (offset >= 0xF02000 && offset <= 0xF020FF)
1389         WriteLog("TOM: ReadWord attempted from GPU register file by %s (unimplemented)!\n", whoName[who]);
1390
1391         if (offset == 0xF000E0)
1392         {
1393                 // For reading, should only return the lower 5 bits...
1394                 uint16_t data = (tom_jerry_int_pending << 4) | (tom_timer_int_pending << 3)
1395                         | (tom_object_int_pending << 2) | (tom_gpu_int_pending << 1)
1396                         | (tom_video_int_pending << 0);
1397                 //WriteLog("tom: interrupt status is 0x%.4x \n",data);
1398                 return data;
1399         }
1400 //Shoud be handled by the jaguar main loop now... And it is! ;-)
1401 /*      else if (offset == 0xF00006)    // VC
1402         // What if we're in interlaced mode?
1403         // According to docs, in non-interlace mode VC is ALWAYS even...
1404 //              return (tom_scanline << 1);// + 1;
1405 //But it's causing Rayman to be fucked up... Why???
1406 //Because VC is even in NI mode when calling the OP! That's why!
1407                 return (tom_scanline << 1) + 1;//*/
1408 /*
1409 //      F00004          R/W   -----xxx xxxxxxxx   HC - horizontal count
1410 //                            -----x-- --------      (which half of the display)
1411 //                            ------xx xxxxxxxx      (10-bit counter)
1412 */
1413 // This is a kludge to get the HC working somewhat... What we really should do here
1414 // is check what the global time is at the time of the read and calculate the correct HC...
1415 // !!! FIX !!!
1416         else if (offset == 0xF00004)
1417                 return rand() & 0x03FF;
1418         else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE + 0x20))
1419                 return GPUReadWord(offset, who);
1420         else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
1421                 return GPUReadWord(offset, who);
1422 /*      else if ((offset >= 0xF00010) && (offset < 0xF00028))
1423                 return OPReadWord(offset, who);*/
1424         else if ((offset >= 0xF02200) && (offset < 0xF022A0))
1425                 return BlitterReadWord(offset, who);
1426         else if (offset == 0xF00050)
1427                 return tomTimerPrescaler;
1428         else if (offset == 0xF00052)
1429                 return tomTimerDivider;
1430
1431         offset &= 0x3FFF;
1432         return (TOMReadByte(offset, who) << 8) | TOMReadByte(offset + 1, who);
1433 }
1434
1435
1436 #define TOM_STRICT_MEMORY_ACCESS
1437 //
1438 // TOM byte access (write)
1439 //
1440 void TOMWriteByte(uint32_t offset, uint8_t data, uint32_t who/*=UNKNOWN*/)
1441 {
1442         // Moved here tentatively, so we can see everything written to TOM.
1443         tomRam8[offset & 0x3FFF] = data;
1444
1445 #ifdef TOM_DEBUG
1446         WriteLog("TOM: Writing byte %02X at %06X", data, offset);
1447 #endif
1448 //???Is this needed???
1449 // Perhaps on the writes--32-bit writes that is! And masked with FF7FFF...
1450 #ifndef TOM_STRICT_MEMORY_ACCESS
1451         offset &= 0xFF3FFF;
1452 #else
1453         // "Fast" (32-bit only) write access to the GPU
1454 //      if ((offset >= 0xF0A100) && (offset <= 0xF0BFFF))
1455         if ((offset >= 0xF08000) && (offset <= 0xF0BFFF))
1456                 offset &= 0xFF7FFF;
1457 #endif
1458 #ifdef TOM_DEBUG
1459         WriteLog(" -->[%06X] by %s\n", offset, whoName[who]);
1460 #endif
1461
1462 #ifdef TOM_STRICT_MEMORY_ACCESS
1463         // Sanity check ("Aww, there ain't no Sanity Clause...")
1464         if ((offset < 0xF00000) || (offset > 0xF03FFF))
1465                 return;
1466 #endif
1467
1468         if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
1469         {
1470                 GPUWriteByte(offset, data, who);
1471                 return;
1472         }
1473         else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
1474         {
1475                 GPUWriteByte(offset, data, who);
1476                 return;
1477         }
1478 /*      else if ((offset >= 0xF00010) && (offset < 0xF00028))
1479         {
1480                 OPWriteByte(offset, data, who);
1481                 return;
1482         }*/
1483         else if ((offset >= 0xF02200) && (offset < 0xF022A0))
1484         {
1485                 BlitterWriteByte(offset, data, who);
1486                 return;
1487         }
1488         else if (offset == 0xF00050)
1489         {
1490                 tomTimerPrescaler = (tomTimerPrescaler & 0x00FF) | (data << 8);
1491                 TOMResetPIT();
1492                 return;
1493         }
1494         else if (offset == 0xF00051)
1495         {
1496                 tomTimerPrescaler = (tomTimerPrescaler & 0xFF00) | data;
1497                 TOMResetPIT();
1498                 return;
1499         }
1500         else if (offset == 0xF00052)
1501         {
1502                 tomTimerDivider = (tomTimerDivider & 0x00FF) | (data << 8);
1503                 TOMResetPIT();
1504                 return;
1505         }
1506         else if (offset == 0xF00053)
1507         {
1508                 tomTimerDivider = (tomTimerDivider & 0xFF00) | data;
1509                 TOMResetPIT();
1510                 return;
1511         }
1512         else if (offset >= 0xF00400 && offset <= 0xF007FF)      // CLUT (A & B)
1513         {
1514                 // Writing to one CLUT writes to the other
1515                 offset &= 0x5FF;                // Mask out $F00600 (restrict to $F00400-5FF)
1516                 tomRam8[offset] = data, tomRam8[offset + 0x200] = data;
1517         }
1518
1519 //      tomRam8[offset & 0x3FFF] = data;
1520 }
1521
1522
1523 //
1524 // TOM word access (write)
1525 //
1526 void TOMWriteWord(uint32_t offset, uint16_t data, uint32_t who/*=UNKNOWN*/)
1527 {
1528         // Moved here tentatively, so we can see everything written to TOM.
1529         tomRam8[(offset + 0) & 0x3FFF] = data >> 8;
1530         tomRam8[(offset + 1) & 0x3FFF] = data & 0xFF;
1531
1532 #ifdef TOM_DEBUG
1533         WriteLog("TOM: Writing byte %04X at %06X", data, offset);
1534 #endif
1535 //???Is this needed??? Yes, but we need to be more vigilant than this.
1536 #ifndef TOM_STRICT_MEMORY_ACCESS
1537         offset &= 0xFF3FFF;
1538 #else
1539         // "Fast" (32-bit only) write access to the GPU
1540 //      if ((offset >= 0xF0A100) && (offset <= 0xF0BFFF))
1541         if ((offset >= 0xF08000) && (offset <= 0xF0BFFF))
1542                 offset &= 0xFF7FFF;
1543 #endif
1544 #ifdef TOM_DEBUG
1545         WriteLog(" -->[%06X] by %s\n", offset, whoName[who]);
1546 #endif
1547
1548 #ifdef TOM_STRICT_MEMORY_ACCESS
1549         // Sanity check
1550         if ((offset < 0xF00000) || (offset > 0xF03FFF))
1551                 return;
1552 #endif
1553
1554 //if (offset == 0xF00000 + MEMCON1)
1555 //      WriteLog("TOM: Memory Configuration 1 written by %s: %04X\n", whoName[who], data);
1556 //if (offset == 0xF00000 + MEMCON2)
1557 //      WriteLog("TOM: Memory Configuration 2 written by %s: %04X\n", whoName[who], data);
1558 if (offset >= 0xF02000 && offset <= 0xF020FF)
1559         WriteLog("TOM: WriteWord attempted to GPU register file by %s (unimplemented)!\n", whoName[who]);
1560
1561         if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
1562         {
1563                 GPUWriteWord(offset, data, who);
1564                 return;
1565         }
1566         else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
1567         {
1568                 GPUWriteWord(offset, data, who);
1569                 return;
1570         }
1571 //What's so special about this?
1572 /*      else if ((offset >= 0xF00000) && (offset < 0xF00002))
1573         {
1574                 TOMWriteByte(offset, data >> 8);
1575                 TOMWriteByte(offset+1, data & 0xFF);
1576         }*/
1577 /*      else if ((offset >= 0xF00010) && (offset < 0xF00028))
1578         {
1579                 OPWriteWord(offset, data, who);
1580                 return;
1581         }*/
1582         else if (offset == 0xF00050)
1583         {
1584                 tomTimerPrescaler = data;
1585                 TOMResetPIT();
1586                 return;
1587         }
1588         else if (offset == 0xF00052)
1589         {
1590                 tomTimerDivider = data;
1591                 TOMResetPIT();
1592                 return;
1593         }
1594         else if (offset == 0xF000E0)
1595         {
1596 //Check this out...
1597                 if (data & 0x0100)
1598                         tom_video_int_pending = 0;
1599                 if (data & 0x0200)
1600                         tom_gpu_int_pending = 0;
1601                 if (data & 0x0400)
1602                         tom_object_int_pending = 0;
1603                 if (data & 0x0800)
1604                         tom_timer_int_pending = 0;
1605                 if (data & 0x1000)
1606                         tom_jerry_int_pending = 0;
1607
1608 //              return;
1609         }
1610         else if ((offset >= 0xF02200) && (offset <= 0xF0229F))
1611         {
1612                 BlitterWriteWord(offset, data, who);
1613                 return;
1614         }
1615         else if (offset >= 0xF00400 && offset <= 0xF007FE)      // CLUT (A & B)
1616         {
1617                 // Writing to one CLUT writes to the other
1618                 offset &= 0x5FF;                // Mask out $F00600 (restrict to $F00400-5FF)
1619 // Watch out for unaligned writes here! (Not fixed yet)
1620 #warning "!!! Watch out for unaligned writes here !!! FIX !!!"
1621                 SET16(tomRam8, offset, data);
1622                 SET16(tomRam8, offset + 0x200, data);
1623         }
1624
1625         offset &= 0x3FFF;
1626         if (offset == 0x28)                     // VMODE (Why? Why not OBF?)
1627 //Actually, we should check to see if the Enable bit of VMODE is set before doing this... !!! FIX !!!
1628 #warning "Actually, we should check to see if the Enable bit of VMODE is set before doing this... !!! FIX !!!"
1629                 objectp_running = 1;
1630
1631         if (offset >= 0x30 && offset <= 0x4E)
1632                 data &= 0x07FF;                 // These are (mostly) 11-bit registers
1633         if (offset == 0x2E || offset == 0x36 || offset == 0x54)
1634                 data &= 0x03FF;                 // These are all 10-bit registers
1635
1636 // Fix a lockup bug... :-P
1637 //      TOMWriteByte(0xF00000 | offset, data >> 8, who);
1638 //      TOMWriteByte(0xF00000 | (offset+1), data & 0xFF, who);
1639
1640 if (offset == MEMCON1)
1641         WriteLog("TOM: Memory Config 1 written by %s: $%04X\n", whoName[who], data);
1642 if (offset == MEMCON2)
1643         WriteLog("TOM: Memory Config 2 written by %s: $%04X\n", whoName[who], data);
1644 //if (offset == OLP)
1645 //      WriteLog("TOM: Object List Pointer written by %s: $%04X\n", whoName[who], data);
1646 //if (offset == OLP + 2)
1647 //      WriteLog("TOM: Object List Pointer +2 written by %s: $%04X\n", whoName[who], data);
1648 //if (offset == OBF)
1649 //      WriteLog("TOM: Object Processor Flag written by %s: %u\n", whoName[who], data);
1650 if (offset == VMODE)
1651         WriteLog("TOM: Video Mode written by %s: %04X. PWIDTH = %u, MODE = %s, flags:%s%s (VC = %u)\n", whoName[who], data, ((data >> 9) & 0x07) + 1, videoMode_to_str[(data & MODE) >> 1], (data & BGEN ? " BGEN" : ""), (data & VARMOD ? " VARMOD" : ""), GET16(tomRam8, VC));
1652 if (offset == BORD1)
1653         WriteLog("TOM: Border 1 written by %s: $%04X\n", whoName[who], data);
1654 if (offset == BORD2)
1655         WriteLog("TOM: Border 2 written by %s: $%04X\n", whoName[who], data);
1656 if (offset == HP)
1657         WriteLog("TOM: Horizontal Period written by %s: %u (+1*2 = %u)\n", whoName[who], data, (data + 1) * 2);
1658 if (offset == HBB)
1659         WriteLog("TOM: Horizontal Blank Begin written by %s: %u\n", whoName[who], data);
1660 if (offset == HBE)
1661         WriteLog("TOM: Horizontal Blank End written by %s: %u\n", whoName[who], data);
1662 if (offset == HS)
1663         WriteLog("TOM: Horizontal Sync written by %s: %u\n", whoName[who], data);
1664 if (offset == HVS)
1665         WriteLog("TOM: Horizontal Vertical Sync written by %s: %u\n", whoName[who], data);
1666 if (offset == HDB1)
1667         WriteLog("TOM: Horizontal Display Begin 1 written by %s: %u\n", whoName[who], data);
1668 if (offset == HDB2)
1669         WriteLog("TOM: Horizontal Display Begin 2 written by %s: %u\n", whoName[who], data);
1670 if (offset == HDE)
1671         WriteLog("TOM: Horizontal Display End written by %s: %u\n", whoName[who], data);
1672 if (offset == VP)
1673         WriteLog("TOM: Vertical Period written by %s: %u (%sinterlaced)\n", whoName[who], data, (data & 0x01 ? "non-" : ""));
1674 if (offset == VBB)
1675         WriteLog("TOM: Vertical Blank Begin written by %s: %u\n", whoName[who], data);
1676 if (offset == VBE)
1677         WriteLog("TOM: Vertical Blank End written by %s: %u\n", whoName[who], data);
1678 if (offset == VS)
1679         WriteLog("TOM: Vertical Sync written by %s: %u\n", whoName[who], data);
1680 if (offset == VDB)
1681         WriteLog("TOM: Vertical Display Begin written by %s: %u\n", whoName[who], data);
1682 if (offset == VDE)
1683         WriteLog("TOM: Vertical Display End written by %s: %u\n", whoName[who], data);
1684 if (offset == VEB)
1685         WriteLog("TOM: Vertical Equalization Begin written by %s: %u\n", whoName[who], data);
1686 if (offset == VEE)
1687         WriteLog("TOM: Vertical Equalization End written by %s: %u\n", whoName[who], data);
1688 if (offset == VI)
1689         WriteLog("TOM: Vertical Interrupt written by %s: %u\n", whoName[who], data);
1690 if (offset == PIT0)
1691         WriteLog("TOM: PIT0 written by %s: %u\n", whoName[who], data);
1692 if (offset == PIT1)
1693         WriteLog("TOM: PIT1 written by %s: %u\n", whoName[who], data);
1694 if (offset == HEQ)
1695         WriteLog("TOM: Horizontal Equalization End written by %s: %u\n", whoName[who], data);
1696 //if (offset == BG)
1697 //      WriteLog("TOM: Background written by %s: %u\n", whoName[who], data);
1698 //if (offset == INT1)
1699 //      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" : ""));
1700
1701         // detect screen resolution changes
1702 //This may go away in the future, if we do the virtualized screen thing...
1703 //This may go away soon!
1704 // TOM Shouldn't be mucking around with this, it's up to the host system to properly
1705 // handle this kind of crap.
1706 // NOTE: This is needed somehow, need to get rid of the dependency on this crap.
1707 //       N.B.: It's used in the rendering functions... So...
1708 #warning "!!! Need to get rid of this dependency !!!"
1709 #if 1
1710         if ((offset >= 0x28) && (offset <= 0x4F))
1711         {
1712                 uint32_t width = TOMGetVideoModeWidth(), height = TOMGetVideoModeHeight();
1713
1714                 if ((width != tomWidth) || (height != tomHeight))
1715                 {
1716                         tomWidth = width, tomHeight = height;
1717
1718 #warning "!!! TOM: ResizeScreen commented out !!!"
1719 // No need to resize anything, since we're prepared for this...
1720 //                      if (vjs.renderType == RT_NORMAL)
1721 //                              ResizeScreen(tomWidth, tomHeight);
1722                 }
1723         }
1724 #endif
1725 }
1726
1727
1728 int TOMIRQEnabled(int irq)
1729 {
1730         // This is the correct byte in big endian... D'oh!
1731 //      return jaguar_byte_read(0xF000E1) & (1 << irq);
1732         return tomRam8[INT1 + 1/*0xE1*/] & (1 << irq);
1733 }
1734
1735
1736 // NEW:
1737 // TOM Programmable Interrupt Timer handler
1738 // NOTE: TOM's PIT is only enabled if the prescaler is != 0
1739 //       The PIT only generates an interrupt when it counts down to zero, not when loaded!
1740
1741 void TOMPITCallback(void);
1742
1743
1744 void TOMResetPIT(void)
1745 {
1746 #ifndef NEW_TIMER_SYSTEM
1747 //Probably should *add* this amount to the counter to retain cycle accuracy! !!! FIX !!! [DONE]
1748 //Also, why +1??? 'Cause that's what it says in the JTRM...!
1749 //There is a small problem with this approach: If both the prescaler and the divider are equal
1750 //to $FFFF then the counter won't be large enough to handle it. !!! FIX !!!
1751         if (tom_timer_prescaler)
1752                 tom_timer_counter += (1 + tom_timer_prescaler) * (1 + tom_timer_divider);
1753 //      WriteLog("tom: reseting timer to 0x%.8x (%i)\n",tom_timer_counter,tom_timer_counter);
1754 #else
1755         // Need to remove previous timer from the queue, if it exists...
1756         RemoveCallback(TOMPITCallback);
1757
1758         if (tomTimerPrescaler)
1759         {
1760                 double usecs = (float)(tomTimerPrescaler + 1) * (float)(tomTimerDivider + 1) * RISC_CYCLE_IN_USEC;
1761                 SetCallbackTime(TOMPITCallback, usecs);
1762         }
1763 #endif
1764 }
1765
1766
1767 //
1768 // TOM Programmable Interrupt Timer handler
1769 // NOTE: TOM's PIT is only enabled if the prescaler is != 0
1770 //
1771 //NOTE: This is only used by the old execution code... Safe to remove
1772 //      once the timer system is stable.
1773 void TOMExecPIT(uint32_t cycles)
1774 {
1775         if (tomTimerPrescaler)
1776         {
1777                 tomTimerCounter -= cycles;
1778
1779                 if (tomTimerCounter <= 0)
1780                 {
1781                         TOMSetPendingTimerInt();
1782                         GPUSetIRQLine(GPUIRQ_TIMER, ASSERT_LINE);       // GPUSetIRQLine does the 'IRQ enabled' checking
1783
1784                         if (TOMIRQEnabled(IRQ_TIMER))
1785                                 m68k_set_irq(2);                                // Cause a 68000 IPL 2...
1786
1787                         TOMResetPIT();
1788                 }
1789         }
1790 }
1791
1792
1793 void TOMPITCallback(void)
1794 {
1795 //      INT1_RREG |= 0x08;                                                      // Set TOM PIT interrupt pending
1796         TOMSetPendingTimerInt();
1797     GPUSetIRQLine(GPUIRQ_TIMER, ASSERT_LINE);   // It does the 'IRQ enabled' checking
1798
1799 //      if (INT1_WREG & 0x08)
1800         if (TOMIRQEnabled(IRQ_TIMER))
1801                 m68k_set_irq(2);                                                // Generate a 68K IPL 2...
1802
1803         TOMResetPIT();
1804 }
1805