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 L. Hammons
7 // (C) 2010 Underground Software
9 // JLH = James L. Hammons <jlhamm@acm.org>
12 // --- ---------- -------------------------------------------------------------
13 // JLH 01/16/2010 Created this log ;-)
14 // JLH 01/20/2011 Change rendering to RGBA, removed unnecessary code
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. :-}
19 // Note: TOM has only a 16K memory space
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 // ------------------------------------------------------------
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 // ------------------------------------------------------------
258 #include <string.h> // For memset()
259 #include <stdlib.h> // For rand()
267 //#include "memory.h"
269 #include "settings.h"
271 #define NEW_TIMER_SYSTEM
273 // TOM registers (offset from $F00000)
280 #define MODE 0x0006 // Line buffer to video generator mode
281 #define BGEN 0x0080 // Background enable (CRY & RGB16 only)
282 #define VARMOD 0x0100 // Mixed CRY/RGB16 mode (only works in MODE 0!)
283 #define PWIDTH 0x0E00 // Pixel width in video clock cycles (value written + 1)
284 #define BORD1 0x2A // Border green/red values (8 BPP)
285 #define BORD2 0x2C // Border blue value (8 BPP)
286 #define HP 0x2E // Values range from 1 - 1024 (value written + 1)
289 #define HDB1 0x38 // Horizontal display begin 1
292 #define VP 0x3E // Value ranges from 1 - 2048 (value written + 1)
304 //NOTE: These arbitrary cutoffs are NOT taken into account for PAL jaguar screens. !!! FIX !!!
306 // Arbitrary video cutoff values (i.e., first/last visible spots on a TV, in HC ticks)
307 /*#define LEFT_VISIBLE_HC 208
308 #define RIGHT_VISIBLE_HC 1528//*/
309 #define LEFT_VISIBLE_HC 208
310 #define RIGHT_VISIBLE_HC 1488
311 //#define TOP_VISIBLE_VC 25
312 //#define BOTTOM_VISIBLE_VC 503
313 #define TOP_VISIBLE_VC 31
314 #define BOTTOM_VISIBLE_VC 511
316 //Are these PAL horizontals correct?
317 //They seem to be for the most part, but there are some games that seem to be
318 //shifted over to the right from this "window".
319 #define LEFT_VISIBLE_HC_PAL 208
320 #define RIGHT_VISIBLE_HC_PAL 1488
321 #define TOP_VISIBLE_VC_PAL 67
322 #define BOTTOM_VISIBLE_VC_PAL 579
324 //This can be defined in the makefile as well...
325 //(It's easier to do it here, though...)
328 uint8 tomRam8[0x4000];
329 uint32 tomWidth, tomHeight;
330 uint32 tomTimerPrescaler;
331 uint32 tomTimerDivider;
332 int32 tomTimerCounter;
333 uint16 tom_jerry_int_pending, tom_timer_int_pending, tom_object_int_pending,
334 tom_gpu_int_pending, tom_video_int_pending;
336 // These are set by the "user" of the Jaguar core lib, since these are
337 // OS/system dependent.
338 uint32 * screenBuffer;
341 static const char * videoMode_to_str[8] =
342 { "16 BPP CRY", "24 BPP RGB", "16 BPP DIRECT", "16 BPP RGB",
343 "Mixed mode", "24 BPP RGB", "16 BPP DIRECT", "16 BPP RGB" };
345 typedef void (render_xxx_scanline_fn)(uint32 *);
347 // Private function prototypes
349 void tom_render_16bpp_cry_scanline(uint32 * backbuffer);
350 void tom_render_24bpp_scanline(uint32 * backbuffer);
351 void tom_render_16bpp_direct_scanline(uint32 * backbuffer);
352 void tom_render_16bpp_rgb_scanline(uint32 * backbuffer);
353 void tom_render_16bpp_cry_rgb_mix_scanline(uint32 * backbuffer);
355 //render_xxx_scanline_fn * scanline_render_normal[] =
356 render_xxx_scanline_fn * scanline_render[] =
358 tom_render_16bpp_cry_scanline,
359 tom_render_24bpp_scanline,
360 tom_render_16bpp_direct_scanline,
361 tom_render_16bpp_rgb_scanline,
362 tom_render_16bpp_cry_rgb_mix_scanline,
363 tom_render_24bpp_scanline,
364 tom_render_16bpp_direct_scanline,
365 tom_render_16bpp_rgb_scanline
368 // Screen info for various games [PAL]...
371 TOM: Horizontal Period written by M68K: 850 (+1*2 = 1702)
372 TOM: Horizontal Blank Begin written by M68K: 1711
373 TOM: Horizontal Blank End written by M68K: 158
374 TOM: Horizontal Display End written by M68K: 1696
375 TOM: Horizontal Display Begin 1 written by M68K: 166
376 TOM: Vertical Period written by M68K: 623 (non-interlaced)
377 TOM: Vertical Blank End written by M68K: 34
378 TOM: Vertical Display Begin written by M68K: 46
379 TOM: Vertical Display End written by M68K: 526
380 TOM: Vertical Blank Begin written by M68K: 600
381 TOM: Vertical Sync written by M68K: 618
382 TOM: Horizontal Display End written by M68K: 1665
383 TOM: Horizontal Display Begin 1 written by M68K: 203
384 TOM: Vertical Display Begin written by M68K: 38
385 TOM: Vertical Display End written by M68K: 518
386 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 151)
387 TOM: Horizontal Display End written by M68K: 1713
388 TOM: Horizontal Display Begin 1 written by M68K: 157
389 TOM: Vertical Display Begin written by M68K: 35
390 TOM: Vertical Display End written by M68K: 2047
391 Horizontal range: 157 - 1713 (width: 1557 / 4 = 389.25, / 5 = 315.4)
394 TOM: Horizontal Period written by M68K: 845 (+1*2 = 1692)
395 TOM: Horizontal Blank Begin written by M68K: 1700
396 TOM: Horizontal Blank End written by M68K: 122
397 TOM: Horizontal Display End written by M68K: 1600
398 TOM: Horizontal Display Begin 1 written by M68K: 268
399 TOM: Vertical Period written by M68K: 523 (non-interlaced)
400 TOM: Vertical Blank End written by M68K: 40
401 TOM: Vertical Display Begin written by M68K: 44
402 TOM: Vertical Display End written by M68K: 492
403 TOM: Vertical Blank Begin written by M68K: 532
404 TOM: Vertical Sync written by M68K: 513
405 TOM: Video Mode written by M68K: 04C7. PWIDTH = 3, MODE = 16 BPP RGB, flags: BGEN (VC = 461)
408 TOM: Horizontal Display End written by M68K: 1713
409 TOM: Horizontal Display Begin 1 written by M68K: 157
410 TOM: Vertical Display Begin written by M68K: 35
411 TOM: Vertical Display End written by M68K: 2047
412 TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 89)
413 TOM: Horizontal Display Begin 1 written by M68K: 208
414 TOM: Horizontal Display End written by M68K: 1662
415 TOM: Vertical Display Begin written by M68K: 100
416 TOM: Vertical Display End written by M68K: 2047
417 TOM: Video Mode written by M68K: 07C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN VARMOD (VC = 205)
418 Horizontal range: 208 - 1662 (width: 1455 / 4 = 363.5)
421 TOM: Vertical Display Begin written by M68K: 96
422 TOM: Vertical Display End written by M68K: 2047
423 TOM: Horizontal Display Begin 1 written by M68K: 239
424 TOM: Horizontal Display End written by M68K: 1692
425 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 378)
426 TOM: Vertical Display Begin written by M68K: 44
427 TOM: Vertical Display End written by M68K: 2047
428 TOM: Horizontal Display Begin 1 written by M68K: 239
429 TOM: Horizontal Display End written by M68K: 1692
430 TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 559)
431 TOM: Vertical Display Begin written by M68K: 84
432 TOM: Vertical Display End written by M68K: 2047
433 TOM: Horizontal Display Begin 1 written by M68K: 239
434 TOM: Horizontal Display End written by M68K: 1692
435 TOM: Vertical Display Begin written by M68K: 44
436 TOM: Vertical Display End written by M68K: 2047
437 TOM: Horizontal Display Begin 1 written by M68K: 239
438 TOM: Horizontal Display End written by M68K: 1692
439 Horizontal range: 239 - 1692 (width: 1454 / 4 = 363.5)
443 // Screen info for various games [NTSC]...
446 TOM: Horizontal Display End written by M68K: 1727
447 TOM: Horizontal Display Begin 1 written by M68K: 123
448 TOM: Vertical Display Begin written by M68K: 25
449 TOM: Vertical Display End written by M68K: 2047
450 TOM: Video Mode written by M68K: 0EC1. PWIDTH = 8, MODE = 16 BPP CRY, flags: BGEN (VC = 5)
451 Also does PWIDTH = 4...
452 Vertical resolution: 238 lines
455 TOM: Horizontal Display End written by M68K: 1727
456 TOM: Horizontal Display Begin 1 written by M68K: 123
457 TOM: Vertical Display Begin written by M68K: 25
458 TOM: Vertical Display End written by M68K: 2047
459 TOM: Vertical Interrupt written by M68K: 507
460 TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 92)
461 TOM: Horizontal Display Begin 1 written by M68K: 208
462 TOM: Horizontal Display End written by M68K: 1670
463 Display starts at 31, then 52!
464 Vertical resolution: 238 lines
467 TOM: Horizontal Display End written by M68K: 1727
468 TOM: Horizontal Display Begin 1 written by M68K: 123
469 TOM: Vertical Display Begin written by M68K: 25
470 TOM: Vertical Display End written by M68K: 2047
471 TOM: Video Mode written by GPU: 08C7. PWIDTH = 5, MODE = 16 BPP RGB, flags: BGEN (VC = 4)
472 TOM: Video Mode written by GPU: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 508)
473 Display starts at 31 (PWIDTH = 4), 24 (PWIDTH = 5)
476 TOM: Vertical Interrupt written by M68K: 2047
477 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 0)
478 TOM: Horizontal Display End written by M68K: 1727
479 TOM: Horizontal Display Begin 1 written by M68K: 123
480 TOM: Vertical Display Begin written by M68K: 25
481 TOM: Vertical Display End written by M68K: 2047
482 TOM: Vertical Interrupt written by M68K: 507
483 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 369)
484 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 510)
485 TOM: Video Mode written by M68K: 06C3. PWIDTH = 4, MODE = 24 BPP RGB, flags: BGEN (VC = 510)
487 Vertical resolution: 238 lines
488 [Seems to be a problem between the horizontal positioning of the 16-bit CRY & 24-bit RGB]
491 TOM: Horizontal Period written by M68K: 844 (+1*2 = 1690)
492 TOM: Horizontal Blank Begin written by M68K: 1713
493 TOM: Horizontal Blank End written by M68K: 125
494 TOM: Horizontal Display End written by M68K: 1696
495 TOM: Horizontal Display Begin 1 written by M68K: 166
496 TOM: Vertical Period written by M68K: 523 (non-interlaced)
497 TOM: Vertical Blank End written by M68K: 24
498 TOM: Vertical Display Begin written by M68K: 46
499 TOM: Vertical Display End written by M68K: 496
500 TOM: Vertical Blank Begin written by M68K: 500
501 TOM: Vertical Sync written by M68K: 517
502 TOM: Vertical Interrupt written by M68K: 497
503 TOM: Video Mode written by M68K: 04C1. PWIDTH = 3, MODE = 16 BPP CRY, flags: BGEN (VC = 270)
507 TOM: Horizontal Display End written by M68K: 1727
508 TOM: Horizontal Display Begin 1 written by M68K: 123
509 TOM: Vertical Display Begin written by M68K: 25
510 TOM: Vertical Display End written by M68K: 2047
511 TOM: Vertical Interrupt written by M68K: 507
512 TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 9)
515 TOM: Horizontal Display End written by M68K: 1823
516 TOM: Horizontal Display Begin 1 written by M68K: 45
517 TOM: Vertical Display Begin written by M68K: 40
518 TOM: Vertical Display End written by M68K: 2047
519 TOM: Vertical Interrupt written by M68K: 491
520 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 398)
521 Display starts at 11 (123 - 45 = 78, 78 / 4 = 19 pixels to skip)
522 Width is 417, so maybe width of 379 would be good (starting at 123, ending at 1639)
523 Vertical resolution: 238 lines
526 TOM: Horizontal Display End written by M68K: 1727
527 TOM: Horizontal Display Begin 1 written by M68K: 188
528 TOM: Vertical Display Begin written by M68K: 1
529 TOM: Vertical Display End written by M68K: 2047
530 TOM: Vertical Interrupt written by M68K: 483
531 TOM: Video Mode written by M68K: 08C7. PWIDTH = 5, MODE = 16 BPP RGB, flags: BGEN (VC = 99)
532 Width would be 303 with above scheme, but border width would be 13 pixels
535 Vertical resolution: 238 lines
538 uint32 RGB16ToRGB32[0x10000];
539 uint32 CRY16ToRGB32[0x10000];
540 uint32 MIX16ToRGB32[0x10000];
542 #warning "This is not endian-safe. !!! FIX !!!"
543 void TOMFillLookupTables(void)
545 // NOTE: Jaguar 16-bit (non-CRY) color is RBG 556 like so:
546 // RRRR RBBB BBGG GGGG
547 for(uint32 i=0; i<0x10000; i++)
548 //hm. RGB16ToRGB32[i] = 0xFF000000
549 // | ((i & 0xF100) >> 8) | ((i & 0xE000) >> 13)
550 // | ((i & 0x07C0) << 13) | ((i & 0x0700) << 8)
551 // | ((i & 0x003F) << 10) | ((i & 0x0030) << 4);
552 RGB16ToRGB32[i] = 0x000000FF
553 | ((i & 0xF100) << 16) // Red
554 | ((i & 0x003F) << 18) // Green
555 | ((i & 0x07C0) << 5); // Blue
557 for(uint32 i=0; i<0x10000; i++)
559 uint32 cyan = (i & 0xF000) >> 12,
560 red = (i & 0x0F00) >> 8,
561 intensity = (i & 0x00FF);
563 uint32 r = (((uint32)redcv[cyan][red]) * intensity) >> 8,
564 g = (((uint32)greencv[cyan][red]) * intensity) >> 8,
565 b = (((uint32)bluecv[cyan][red]) * intensity) >> 8;
567 //hm. CRY16ToRGB32[i] = 0xFF000000 | (b << 16) | (g << 8) | r;
568 CRY16ToRGB32[i] = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
569 MIX16ToRGB32[i] = (i & 0x01 ? RGB16ToRGB32[i] : CRY16ToRGB32[i]);
573 void TOMSetPendingJERRYInt(void)
575 tom_jerry_int_pending = 1;
578 void TOMSetPendingTimerInt(void)
580 tom_timer_int_pending = 1;
583 void TOMSetPendingObjectInt(void)
585 tom_object_int_pending = 1;
588 void TOMSetPendingGPUInt(void)
590 tom_gpu_int_pending = 1;
593 void TOMSetPendingVideoInt(void)
595 tom_video_int_pending = 1;
598 uint8 * TOMGetRamPointer(void)
603 uint8 TOMGetVideoMode(void)
605 uint16 vmode = GET16(tomRam8, VMODE);
606 return ((vmode & VARMOD) >> 6) | ((vmode & MODE) >> 1);
609 //Used in only one place (and for debug purposes): OBJECTP.CPP
610 #warning "Used in only one place (and for debug purposes): OBJECTP.CPP !!! FIX !!!"
611 uint16 TOMGetVDB(void)
613 return GET16(tomRam8, VDB);
617 // 16 BPP CRY/RGB mixed mode rendering
619 void tom_render_16bpp_cry_rgb_mix_scanline(uint32 * backbuffer)
621 //CHANGED TO 32BPP RENDERING
622 uint16 width = tomWidth;
623 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
625 //New stuff--restrict our drawing...
626 uint8 pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
627 //NOTE: May have to check HDB2 as well!
628 // Get start position in HC ticks
629 int16 startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL);
632 current_line_buffer += 2 * -startPos;
634 //This case doesn't properly handle the "start on the right side of virtual screen" case
635 //Dunno why--looks Ok...
636 //What *is* for sure wrong is that it doesn't copy the linebuffer's BG pixels...
637 //This should likely be 4 instead of 2 (?--not sure)
638 backbuffer += 2 * startPos, width -= startPos;
642 uint16 color = (*current_line_buffer++) << 8;
643 color |= *current_line_buffer++;
644 *backbuffer++ = MIX16ToRGB32[color];
650 // 16 BPP CRY mode rendering
652 void tom_render_16bpp_cry_scanline(uint32 * backbuffer)
654 //CHANGED TO 32BPP RENDERING
655 uint16 width = tomWidth;
656 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
658 //New stuff--restrict our drawing...
659 uint8 pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
660 //NOTE: May have to check HDB2 as well!
661 int16 startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL);// Get start position in HC ticks
664 current_line_buffer += 2 * -startPos;
666 //This should likely be 4 instead of 2 (?--not sure)
667 backbuffer += 2 * startPos, width -= startPos;
671 uint16 color = (*current_line_buffer++) << 8;
672 color |= *current_line_buffer++;
673 *backbuffer++ = CRY16ToRGB32[color];
679 // 24 BPP mode rendering
681 void tom_render_24bpp_scanline(uint32 * backbuffer)
683 //CHANGED TO 32BPP RENDERING
684 uint16 width = tomWidth;
685 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
687 //New stuff--restrict our drawing...
688 uint8 pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
689 //NOTE: May have to check HDB2 as well!
690 int16 startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL); // Get start position in HC ticks
693 current_line_buffer += 4 * -startPos;
695 //This should likely be 4 instead of 2 (?--not sure)
696 backbuffer += 2 * startPos, width -= startPos;
700 uint32 g = *current_line_buffer++;
701 uint32 r = *current_line_buffer++;
702 current_line_buffer++;
703 uint32 b = *current_line_buffer++;
704 //hm. *backbuffer++ = 0xFF000000 | (b << 16) | (g << 8) | r;
705 *backbuffer++ = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
710 //Seems to me that this is NOT a valid mode--the JTRM seems to imply that you would need
711 //extra hardware outside of the Jaguar console to support this!
713 // 16 BPP direct mode rendering
715 void tom_render_16bpp_direct_scanline(uint32 * backbuffer)
717 uint16 width = tomWidth;
718 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
722 uint16 color = (*current_line_buffer++) << 8;
723 color |= *current_line_buffer++;
724 *backbuffer++ = color >> 1;
730 // 16 BPP RGB mode rendering
732 void tom_render_16bpp_rgb_scanline(uint32 * backbuffer)
734 //CHANGED TO 32BPP RENDERING
735 // 16 BPP RGB: 0-5 green, 6-10 blue, 11-15 red
737 uint16 width = tomWidth;
738 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
740 //New stuff--restrict our drawing...
741 uint8 pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
742 //NOTE: May have to check HDB2 as well!
743 int16 startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL); // Get start position in HC ticks
747 current_line_buffer += 2 * -startPos;
749 //This should likely be 4 instead of 2 (?--not sure)
750 backbuffer += 2 * startPos, width -= startPos;
754 uint32 color = (*current_line_buffer++) << 8;
755 color |= *current_line_buffer++;
756 *backbuffer++ = RGB16ToRGB32[color];
762 /*void TOMResetBackbuffer(uint32 * backbuffer)
764 TOMBackbuffer = backbuffer;
768 // Process a single scanline
769 // (this is bad terminology; each tick of the VC is actually a half-line)
771 void TOMExecHalfline(uint16 halfline, bool render)
773 bool inActiveDisplayArea = true;
775 //Interlacing is still not handled correctly here... !!! FIX !!!
776 if (halfline & 0x01) // Execute OP only on even lines (non-interlaced only!)
779 //Hm, it seems that the OP needs to execute from zero, so let's try it:
780 // And it works! But need to do some optimizations in the OP to keep it from attempting
781 // to do a scanline render in the non-display area... [DONE]
782 //this seems to cause a regression in certain games, like rayman
783 //which means I have to dig thru the asic nets to see what's wrong...
785 No, the OP doesn't start until VDB, that much is certain. The thing is, VDB is the
786 HALF line that the OP starts on--which means that it needs to start at VDB / 2!!!
788 Hrm, doesn't seem to be enough, though it should be... still sticks for 20 frames.
791 // 16 isn't enough, and neither is 32 for raptgun. 32 fucks up Rayman
792 // if (halfline >= ((uint16)GET16(tomRam8, VDB) / 2) && halfline < ((uint16)GET16(tomRam8, VDE) / 2))
793 if (halfline >= (uint16)GET16(tomRam8, VDB) && halfline < (uint16)GET16(tomRam8, VDE))
794 // if (halfline >= ((uint16)GET16(tomRam8, VDB) - 16) && halfline < (uint16)GET16(tomRam8, VDE))
795 // if (halfline >= 20 && halfline < (uint16)GET16(tomRam8, VDE))
799 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
800 uint8 bgHI = tomRam8[BG], bgLO = tomRam8[BG + 1];
802 // Clear line buffer with BG
803 if (GET16(tomRam8, VMODE) & BGEN) // && (CRY or RGB16)...
804 for(uint32 i=0; i<720; i++)
805 *current_line_buffer++ = bgHI, *current_line_buffer++ = bgLO;
807 OPProcessList(halfline, render);
811 inActiveDisplayArea = false;
813 inActiveDisplayArea =
814 (halfline >= (uint16)GET16(tomRam8, VDB) && halfline < (uint16)GET16(tomRam8, VDE)
817 if (halfline < (uint16)GET16(tomRam8, VDE))
819 if (render)//With JaguarExecuteNew() this is always true...
821 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
822 uint8 bgHI = tomRam8[BG], bgLO = tomRam8[BG + 1];
824 // Clear line buffer with BG
825 if (GET16(tomRam8, VMODE) & BGEN) // && (CRY or RGB16)...
826 for(uint32 i=0; i<720; i++)
827 *current_line_buffer++ = bgHI, *current_line_buffer++ = bgLO;
829 // OPProcessList(halfline, render);
830 //This seems to take care of it...
831 OPProcessList(halfline, inActiveDisplayArea);
836 // Try to take PAL into account... [We do now!]
838 uint16 topVisible = (vjs.hardwareTypeNTSC ? TOP_VISIBLE_VC : TOP_VISIBLE_VC_PAL),
839 bottomVisible = (vjs.hardwareTypeNTSC ? BOTTOM_VISIBLE_VC : BOTTOM_VISIBLE_VC_PAL);
840 uint32 * TOMCurrentLine = &(screenBuffer[((halfline - topVisible) / 2) * screenPitch]);
842 // Here's our virtualized scanline code...
844 if (halfline >= topVisible && halfline < bottomVisible)
846 if (inActiveDisplayArea)
848 //NOTE: The following doesn't put BORDER color on the sides... !!! FIX !!!
849 #warning "The following doesn't put BORDER color on the sides... !!! FIX !!!"
850 if (vjs.renderType == RT_NORMAL)
851 // scanline_render[TOMGetVideoMode()](TOMBackbuffer);
852 scanline_render[TOMGetVideoMode()](TOMCurrentLine);
856 tom_render_16bpp_cry_scanline,
857 tom_render_24bpp_scanline,
858 tom_render_16bpp_direct_scanline,
859 tom_render_16bpp_rgb_scanline,
860 tom_render_16bpp_cry_rgb_mix_scanline,
861 tom_render_24bpp_scanline,
862 tom_render_16bpp_direct_scanline,
863 tom_render_16bpp_rgb_scanline
865 #define MODE 0x0006 // Line buffer to video generator mode
866 #define VARMOD 0x0100 // Mixed CRY/RGB16 mode (only works in MODE 0!)
868 uint8 pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
869 uint8 mode = ((GET16(tomRam8, VMODE) & MODE) >> 1);
870 bool varmod = GET16(tomRam8, VMODE) & VARMOD;
871 //The video texture line buffer ranges from 0 to 1279, with its left edge starting at
872 //LEFT_VISIBLE_HC. So, we need to start writing into the backbuffer at HDB1, using pwidth
873 //as our scaling factor. The way it generates its image on a real TV!
875 //So, for example, if HDB1 is less than LEFT_VISIBLE_HC, then we have to figure out where
876 //in the VTLB that we start writing pixels from the Jaguar line buffer (VTLB start=0,
880 // 24 BPP mode rendering
882 void tom_render_24bpp_scanline(uint32 * backbuffer)
884 //CHANGED TO 32BPP RENDERING
885 uint16 width = tomWidth;
886 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
888 //New stuff--restrict our drawing...
889 uint8 pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
890 //NOTE: May have to check HDB2 as well!
891 int16 startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL); // Get start position in HC ticks
894 current_line_buffer += 4 * -startPos;
896 //This should likely be 4 instead of 2 (?--not sure)
897 backbuffer += 2 * startPos, width -= startPos;
901 uint32 g = *current_line_buffer++;
902 uint32 r = *current_line_buffer++;
903 current_line_buffer++;
904 uint32 b = *current_line_buffer++;
905 *backbuffer++ = 0xFF000000 | (b << 16) | (g << 8) | r;
915 // If outside of VDB & VDE, then display the border color
916 uint32 * currentLineBuffer = TOMCurrentLine;
917 uint8 g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
918 //Hm. uint32 pixel = 0xFF000000 | (b << 16) | (g << 8) | r;
919 uint32 pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
921 for(uint32 i=0; i<tomWidth; i++)
922 *currentLineBuffer++ = pixel;
928 // TOM initialization
932 TOMFillLookupTables();
942 WriteLog("TOM: Resolution %i x %i %s\n", TOMGetVideoModeWidth(), TOMGetVideoModeHeight(),
943 videoMode_to_str[TOMGetVideoMode()]);
944 // WriteLog("\ntom: object processor:\n");
945 // WriteLog("tom: pointer to object list: 0x%.8x\n",op_get_list_pointer());
946 // WriteLog("tom: INT1=0x%.2x%.2x\n",TOMReadByte(0xf000e0),TOMReadByte(0xf000e1));
949 // memory_free(tomRam8);
950 // memory_free(tom_cry_rgb_mix_lut);
953 uint32 TOMGetVideoModeWidth(void)
955 //These widths are pretty bogus. Should use HDB1/2 & HDE/HBB & PWIDTH to calc the width...
956 // uint32 width[8] = { 1330, 665, 443, 332, 266, 222, 190, 166 };
957 //Temporary, for testing Doom...
958 // uint32 width[8] = { 1330, 665, 443, 332, 266, 222, 190, 332 };
960 // Note that the following PWIDTH values have the following pixel aspect ratios:
961 // PWIDTH = 1 -> 0.25:1 (1:4) pixels (X:Y ratio)
962 // PWIDTH = 2 -> 0.50:1 (1:2) pixels
963 // PWIDTH = 3 -> 0.75:1 (3:4) pixels
964 // PWIDTH = 4 -> 1.00:1 (1:1) pixels
965 // PWIDTH = 5 -> 1.25:1 (5:4) pixels
966 // PWIDTH = 6 -> 1.50:1 (3:2) pixels
967 // PWIDTH = 7 -> 1.75:1 (7:4) pixels
968 // PWIDTH = 8 -> 2.00:1 (2:1) pixels
970 // Also note that the JTRM says that PWIDTH of 4 gives pixels that are "about" square--
971 // this implies that the other modes have pixels that are *not* square!
972 // Also, I seriously doubt that you will see any games that use PWIDTH = 1!
974 // NOTE: Even though the PWIDTH value is + 1, here we're using a zero-based index and
975 // so we don't bother to add one...
976 // return width[(GET16(tomRam8, VMODE) & PWIDTH) >> 9];
978 // Now, we just calculate it...
979 /* uint16 hdb1 = GET16(tomRam8, HDB1), hde = GET16(tomRam8, HDE),
980 hbb = GET16(tomRam8, HBB), pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
981 // return ((hbb < hde ? hbb : hde) - hdb1) / pwidth;
982 //Temporary, for testing Doom...
983 return ((hbb < hde ? hbb : hde) - hdb1) / (pwidth == 8 ? 4 : pwidth);*/
985 // To make it easier to make a quasi-fixed display size, we restrict the viewing
986 // area to an arbitrary range of the Horizontal Count.
987 uint16 pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
988 return (vjs.hardwareTypeNTSC ? RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC : RIGHT_VISIBLE_HC_PAL - LEFT_VISIBLE_HC_PAL) / pwidth;
989 //Temporary, for testing Doom...
990 // return (RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC) / (pwidth == 8 ? 4 : pwidth);
991 //// return (RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC) / (pwidth == 4 ? 8 : pwidth);
993 // More speculating...
994 // According to the JTRM, the number of potential pixels across is given by the
995 // Horizontal Period (HP - in NTSC this is 845). The Horizontal Count counts from
996 // zero to this value twice per scanline (the high bit is set on the second count).
997 // HBE and HBB define the absolute "black" limits of the screen, while HDB1/2 and
998 // HDE determine the extent of the OP "on" time. I.e., when the OP is turned on by
999 // HDB1, it starts fetching the line from position 0 in LBUF.
1001 // The trick, it would seem, is to figure out how long the typical visible scanline
1002 // of a TV is in HP ticks and limit the visible area to that (divided by PWIDTH, of
1003 // course). Using that length, we can establish an "absolute left display limit" with
1004 // which to measure HBB & HDB1/2 against when rendering LBUF (i.e., if HDB1 is 20 ticks
1005 // to the right of the ALDL and PWIDTH is 4, then start writing the LBUF starting at
1006 // backbuffer + 5 pixels).
1008 // That's basically what we're doing now...!
1011 // *** SPECULATION ***
1012 // It might work better to virtualize the height settings, i.e., set the vertical
1013 // height at 240 lines and clip using the VDB and VDE/VP registers...
1014 // Same with the width... [Width is pretty much virtualized now.]
1016 // Now that that the width is virtualized, let's virtualize the height. :-)
1017 uint32 TOMGetVideoModeHeight(void)
1019 // uint16 vmode = GET16(tomRam8, VMODE);
1020 // uint16 vbe = GET16(tomRam8, VBE);
1021 // uint16 vbb = GET16(tomRam8, VBB);
1022 // uint16 vdb = GET16(tomRam8, VDB);
1023 // uint16 vde = GET16(tomRam8, VDE);
1024 // uint16 vp = GET16(tomRam8, VP);
1026 /* if (vde == 0xFFFF)
1029 // return 227;//WAS:(vde/*-vdb*/) >> 1;
1030 // The video mode height probably works this way:
1031 // VC counts from 0 to VP. VDB starts the OP. Either when
1032 // VDE is reached or VP, the OP is stopped. Let's try it...
1033 // Also note that we're conveniently ignoring interlaced display modes...!
1034 // return ((vde > vp ? vp : vde) - vdb) >> 1;
1035 // return ((vde > vbb ? vbb : vde) - vdb) >> 1;
1036 //Let's try from the Vertical Blank interval...
1038 // return (vbb - vbe) >> 1; // Again, doesn't take interlacing into account...
1039 // This of course doesn't take interlacing into account. But I haven't seen any
1040 // Jaguar software that takes advantage of it either...
1041 //Also, doesn't reflect PAL Jaguar either... !!! FIX !!! [DONE]
1042 // return 240; // Set virtual screen height to 240 lines...
1043 return (vjs.hardwareTypeNTSC ? 240 : 256);
1048 // Now PAL friendly!
1054 memset(tomRam8, 0x00, 0x4000);
1056 if (vjs.hardwareTypeNTSC)
1058 SET16(tomRam8, MEMCON1, 0x1861);
1059 SET16(tomRam8, MEMCON2, 0x35CC);
1060 SET16(tomRam8, HP, 844); // Horizontal Period (1-based; HP=845)
1061 SET16(tomRam8, HBB, 1713); // Horizontal Blank Begin
1062 SET16(tomRam8, HBE, 125); // Horizontal Blank End
1063 SET16(tomRam8, HDE, 1665); // Horizontal Display End
1064 SET16(tomRam8, HDB1, 203); // Horizontal Display Begin 1
1065 SET16(tomRam8, VP, 523); // Vertical Period (1-based; in this case VP = 524)
1066 SET16(tomRam8, VBE, 24); // Vertical Blank End
1067 SET16(tomRam8, VDB, 38); // Vertical Display Begin
1068 SET16(tomRam8, VDE, 518); // Vertical Display End
1069 SET16(tomRam8, VBB, 500); // Vertical Blank Begin
1070 SET16(tomRam8, VS, 517); // Vertical Sync
1071 SET16(tomRam8, VMODE, 0x06C1);
1075 SET16(tomRam8, MEMCON1, 0x1861);
1076 SET16(tomRam8, MEMCON2, 0x35CC);
1077 SET16(tomRam8, HP, 850); // Horizontal Period
1078 SET16(tomRam8, HBB, 1711); // Horizontal Blank Begin
1079 SET16(tomRam8, HBE, 158); // Horizontal Blank End
1080 SET16(tomRam8, HDE, 1665); // Horizontal Display End
1081 SET16(tomRam8, HDB1, 203); // Horizontal Display Begin 1
1082 SET16(tomRam8, VP, 623); // Vertical Period (1-based; in this case VP = 624)
1083 SET16(tomRam8, VBE, 34); // Vertical Blank End
1084 SET16(tomRam8, VDB, 38); // Vertical Display Begin
1085 SET16(tomRam8, VDE, 518); // Vertical Display End
1086 SET16(tomRam8, VBB, 600); // Vertical Blank Begin
1087 SET16(tomRam8, VS, 618); // Vertical Sync
1088 SET16(tomRam8, VMODE, 0x06C1);
1094 tom_jerry_int_pending = 0;
1095 tom_timer_int_pending = 0;
1096 tom_object_int_pending = 0;
1097 tom_gpu_int_pending = 0;
1098 tom_video_int_pending = 0;
1100 tomTimerPrescaler = 0; // TOM PIT is disabled
1101 tomTimerDivider = 0;
1102 tomTimerCounter = 0;
1106 // TOM byte access (read)
1108 uint8 TOMReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
1110 //???Is this needed???
1111 // It seems so. Perhaps it's the +$8000 offset being written to (32-bit interface)?
1112 // However, the 32-bit interface is WRITE ONLY, so that can't be it...
1113 // Also, the 68K CANNOT make use of the 32-bit interface, since its bus width is only 16-bits...
1114 // offset &= 0xFF3FFF;
1117 WriteLog("TOM: Reading byte at %06X for %s\n", offset, whoName[who]);
1120 if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
1121 return GPUReadByte(offset, who);
1122 else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
1123 return GPUReadByte(offset, who);
1124 /* else if ((offset >= 0xF00010) && (offset < 0xF00028))
1125 return OPReadByte(offset, who);*/
1126 else if ((offset >= 0xF02200) && (offset < 0xF022A0))
1127 return BlitterReadByte(offset, who);
1128 else if (offset == 0xF00050)
1129 return tomTimerPrescaler >> 8;
1130 else if (offset == 0xF00051)
1131 return tomTimerPrescaler & 0xFF;
1132 else if (offset == 0xF00052)
1133 return tomTimerDivider >> 8;
1134 else if (offset == 0xF00053)
1135 return tomTimerDivider & 0xFF;
1137 return tomRam8[offset & 0x3FFF];
1141 // TOM word access (read)
1143 uint16 TOMReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
1145 //???Is this needed???
1146 // offset &= 0xFF3FFF;
1148 WriteLog("TOM: Reading word at %06X for %s\n", offset, whoName[who]);
1150 if (offset >= 0xF02000 && offset <= 0xF020FF)
1151 WriteLog("TOM: Read attempted from GPU register file by %s (unimplemented)!\n", whoName[who]);
1153 if (offset == 0xF000E0)
1155 // For reading, should only return the lower 5 bits...
1156 uint16 data = (tom_jerry_int_pending << 4) | (tom_timer_int_pending << 3)
1157 | (tom_object_int_pending << 2) | (tom_gpu_int_pending << 1)
1158 | (tom_video_int_pending << 0);
1159 //WriteLog("tom: interrupt status is 0x%.4x \n",data);
1162 //Shoud be handled by the jaguar main loop now... And it is! ;-)
1163 /* else if (offset == 0xF00006) // VC
1164 // What if we're in interlaced mode?
1165 // According to docs, in non-interlace mode VC is ALWAYS even...
1166 // return (tom_scanline << 1);// + 1;
1167 //But it's causing Rayman to be fucked up... Why???
1168 //Because VC is even in NI mode when calling the OP! That's why!
1169 return (tom_scanline << 1) + 1;//*/
1171 // F00004 R/W -----xxx xxxxxxxx HC - horizontal count
1172 // -----x-- -------- (which half of the display)
1173 // ------xx xxxxxxxx (10-bit counter)
1175 // This is a kludge to get the HC working somewhat... What we really should do here
1176 // is check what the global time is at the time of the read and calculate the correct HC...
1178 else if (offset == 0xF00004)
1179 return rand() & 0x03FF;
1180 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE + 0x20))
1181 return GPUReadWord(offset, who);
1182 else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
1183 return GPUReadWord(offset, who);
1184 /* else if ((offset >= 0xF00010) && (offset < 0xF00028))
1185 return OPReadWord(offset, who);*/
1186 else if ((offset >= 0xF02200) && (offset < 0xF022A0))
1187 return BlitterReadWord(offset, who);
1188 else if (offset == 0xF00050)
1189 return tomTimerPrescaler;
1190 else if (offset == 0xF00052)
1191 return tomTimerDivider;
1194 return (TOMReadByte(offset, who) << 8) | TOMReadByte(offset + 1, who);
1197 #define TOM_STRICT_MEMORY_ACCESS
1199 // TOM byte access (write)
1201 void TOMWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
1204 WriteLog("TOM: Writing byte %02X at %06X", data, offset);
1206 //???Is this needed???
1207 // Perhaps on the writes--32-bit writes that is! And masked with FF7FFF...
1208 #ifndef TOM_STRICT_MEMORY_ACCESS
1211 // "Fast" (32-bit only) write access to the GPU
1212 // if ((offset >= 0xF0A100) && (offset <= 0xF0BFFF))
1213 if ((offset >= 0xF08000) && (offset <= 0xF0BFFF))
1217 WriteLog(" -->[%06X] by %s\n", offset, whoName[who]);
1220 #ifdef TOM_STRICT_MEMORY_ACCESS
1221 // Sanity check ("Aww, there ain't no Sanity Clause...")
1222 if ((offset < 0xF00000) || (offset > 0xF03FFF))
1226 if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
1228 GPUWriteByte(offset, data, who);
1231 else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
1233 GPUWriteByte(offset, data, who);
1236 /* else if ((offset >= 0xF00010) && (offset < 0xF00028))
1238 OPWriteByte(offset, data, who);
1241 else if ((offset >= 0xF02200) && (offset < 0xF022A0))
1243 BlitterWriteByte(offset, data, who);
1246 else if (offset == 0xF00050)
1248 tomTimerPrescaler = (tomTimerPrescaler & 0x00FF) | (data << 8);
1252 else if (offset == 0xF00051)
1254 tomTimerPrescaler = (tomTimerPrescaler & 0xFF00) | data;
1258 else if (offset == 0xF00052)
1260 tomTimerDivider = (tomTimerDivider & 0x00FF) | (data << 8);
1264 else if (offset == 0xF00053)
1266 tomTimerDivider = (tomTimerDivider & 0xFF00) | data;
1270 else if (offset >= 0xF00400 && offset <= 0xF007FF) // CLUT (A & B)
1272 // Writing to one CLUT writes to the other
1273 offset &= 0x5FF; // Mask out $F00600 (restrict to $F00400-5FF)
1274 tomRam8[offset] = data, tomRam8[offset + 0x200] = data;
1277 tomRam8[offset & 0x3FFF] = data;
1281 // TOM word access (write)
1283 void TOMWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
1286 WriteLog("TOM: Writing byte %04X at %06X", data, offset);
1288 //???Is this needed??? Yes, but we need to be more vigilant than this.
1289 #ifndef TOM_STRICT_MEMORY_ACCESS
1292 // "Fast" (32-bit only) write access to the GPU
1293 // if ((offset >= 0xF0A100) && (offset <= 0xF0BFFF))
1294 if ((offset >= 0xF08000) && (offset <= 0xF0BFFF))
1298 WriteLog(" -->[%06X] by %s\n", offset, whoName[who]);
1301 #ifdef TOM_STRICT_MEMORY_ACCESS
1303 if ((offset < 0xF00000) || (offset > 0xF03FFF))
1307 if (offset == 0xF00000 + MEMCON1)
1308 WriteLog("TOM: Memory Configuration 1 written by %s: %04X\n", whoName[who], data);
1309 if (offset == 0xF00000 + MEMCON2)
1310 WriteLog("TOM: Memory Configuration 2 written by %s: %04X\n", whoName[who], data);
1311 if (offset >= 0xF02000 && offset <= 0xF020FF)
1312 WriteLog("TOM: Write attempted to GPU register file by %s (unimplemented)!\n", whoName[who]);
1314 if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
1316 GPUWriteWord(offset, data, who);
1319 else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
1321 GPUWriteWord(offset, data, who);
1324 //What's so special about this?
1325 /* else if ((offset >= 0xF00000) && (offset < 0xF00002))
1327 TOMWriteByte(offset, data >> 8);
1328 TOMWriteByte(offset+1, data & 0xFF);
1330 /* else if ((offset >= 0xF00010) && (offset < 0xF00028))
1332 OPWriteWord(offset, data, who);
1335 else if (offset == 0xF00050)
1337 tomTimerPrescaler = data;
1341 else if (offset == 0xF00052)
1343 tomTimerDivider = data;
1347 else if (offset == 0xF000E0)
1351 tom_video_int_pending = 0;
1353 tom_gpu_int_pending = 0;
1355 tom_object_int_pending = 0;
1357 tom_timer_int_pending = 0;
1359 tom_jerry_int_pending = 0;
1363 else if ((offset >= 0xF02200) && (offset <= 0xF0229F))
1365 BlitterWriteWord(offset, data, who);
1368 else if (offset >= 0xF00400 && offset <= 0xF007FE) // CLUT (A & B)
1370 // Writing to one CLUT writes to the other
1371 offset &= 0x5FF; // Mask out $F00600 (restrict to $F00400-5FF)
1372 // Watch out for unaligned writes here! (Not fixed yet)
1373 #warning "!!! Watch out for unaligned writes here !!! FIX !!!"
1374 SET16(tomRam8, offset, data);
1375 SET16(tomRam8, offset + 0x200, data);
1379 if (offset == 0x28) // VMODE (Why? Why not OBF?)
1380 //Actually, we should check to see if the Enable bit of VMODE is set before doing this... !!! FIX !!!
1381 #warning "Actually, we should check to see if the Enable bit of VMODE is set before doing this... !!! FIX !!!"
1382 objectp_running = 1;
1384 if (offset >= 0x30 && offset <= 0x4E)
1385 data &= 0x07FF; // These are (mostly) 11-bit registers
1386 if (offset == 0x2E || offset == 0x36 || offset == 0x54)
1387 data &= 0x03FF; // These are all 10-bit registers
1389 // Fix a lockup bug... :-P
1390 TOMWriteByte(0xF00000 | offset, data >> 8, who);
1391 TOMWriteByte(0xF00000 | (offset+1), data & 0xFF, who);
1394 WriteLog("TOM: Vertical Display Begin written by %s: %u\n", whoName[who], data);
1396 WriteLog("TOM: Vertical Display End written by %s: %u\n", whoName[who], data);
1398 WriteLog("TOM: Vertical Period written by %s: %u (%sinterlaced)\n", whoName[who], data, (data & 0x01 ? "non-" : ""));
1400 WriteLog("TOM: Horizontal Display Begin 1 written by %s: %u\n", whoName[who], data);
1402 WriteLog("TOM: Horizontal Display Begin 2 written by %s: %u\n", whoName[who], data);
1404 WriteLog("TOM: Horizontal Display End written by %s: %u\n", whoName[who], data);
1406 WriteLog("TOM: Horizontal Period written by %s: %u (+1*2 = %u)\n", whoName[who], data, (data + 1) * 2);
1408 WriteLog("TOM: Vertical Blank Begin written by %s: %u\n", whoName[who], data);
1410 WriteLog("TOM: Vertical Blank End written by %s: %u\n", whoName[who], data);
1412 WriteLog("TOM: Vertical Sync written by %s: %u\n", whoName[who], data);
1414 WriteLog("TOM: Vertical Interrupt written by %s: %u\n", whoName[who], data);
1416 WriteLog("TOM: Horizontal Blank Begin written by %s: %u\n", whoName[who], data);
1418 WriteLog("TOM: Horizontal Blank End written by %s: %u\n", whoName[who], data);
1419 if (offset == VMODE)
1420 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));
1422 WriteLog("TOM: PIT0 written by %s: %u\n", whoName[who], data);
1424 WriteLog("TOM: PIT1 written by %s: %u\n", whoName[who], data);
1425 //if (offset == INT1)
1426 // 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" : ""));
1428 // detect screen resolution changes
1429 //This may go away in the future, if we do the virtualized screen thing...
1430 //This may go away soon!
1431 // TOM Shouldn't be mucking around with this, it's up to the host system to properly
1432 // handle this kind of crap.
1433 // NOTE: This is needed somehow, need to get rid of the dependency on this crap.
1434 #warning "!!! Need to get rid of this dependency !!!"
1436 if ((offset >= 0x28) && (offset <= 0x4F))
1438 uint32 width = TOMGetVideoModeWidth(), height = TOMGetVideoModeHeight();
1440 if ((width != tomWidth) || (height != tomHeight))
1442 tomWidth = width, tomHeight = height;
1444 #warning "!!! TOM: ResizeScreen commented out !!!"
1445 // No need to resize anything, since we're prepared for this...
1446 // if (vjs.renderType == RT_NORMAL)
1447 // ResizeScreen(tomWidth, tomHeight);
1453 int TOMIRQEnabled(int irq)
1455 // This is the correct byte in big endian... D'oh!
1456 // return jaguar_byte_read(0xF000E1) & (1 << irq);
1457 return tomRam8[INT1 + 1/*0xE1*/] & (1 << irq);
1461 // TOM Programmable Interrupt Timer handler
1462 // NOTE: TOM's PIT is only enabled if the prescaler is != 0
1463 // The PIT only generates an interrupt when it counts down to zero, not when loaded!
1465 void TOMPITCallback(void);
1467 void TOMResetPIT(void)
1469 #ifndef NEW_TIMER_SYSTEM
1470 //Probably should *add* this amount to the counter to retain cycle accuracy! !!! FIX !!! [DONE]
1471 //Also, why +1??? 'Cause that's what it says in the JTRM...!
1472 //There is a small problem with this approach: If both the prescaler and the divider are equal
1473 //to $FFFF then the counter won't be large enough to handle it. !!! FIX !!!
1474 if (tom_timer_prescaler)
1475 tom_timer_counter += (1 + tom_timer_prescaler) * (1 + tom_timer_divider);
1476 // WriteLog("tom: reseting timer to 0x%.8x (%i)\n",tom_timer_counter,tom_timer_counter);
1478 // Need to remove previous timer from the queue, if it exists...
1479 RemoveCallback(TOMPITCallback);
1481 if (tomTimerPrescaler)
1483 double usecs = (float)(tomTimerPrescaler + 1) * (float)(tomTimerDivider + 1) * RISC_CYCLE_IN_USEC;
1484 SetCallbackTime(TOMPITCallback, usecs);
1490 // TOM Programmable Interrupt Timer handler
1491 // NOTE: TOM's PIT is only enabled if the prescaler is != 0
1493 //NOTE: This is only used by the old execution code... Safe to remove
1494 // once the timer system is stable.
1495 void TOMExecPIT(uint32 cycles)
1497 if (tomTimerPrescaler)
1499 tomTimerCounter -= cycles;
1501 if (tomTimerCounter <= 0)
1503 TOMSetPendingTimerInt();
1504 GPUSetIRQLine(GPUIRQ_TIMER, ASSERT_LINE); // GPUSetIRQLine does the 'IRQ enabled' checking
1506 if (TOMIRQEnabled(IRQ_TIMER))
1507 m68k_set_irq(2); // Cause a 68000 IPL 2...
1514 void TOMPITCallback(void)
1516 // INT1_RREG |= 0x08; // Set TOM PIT interrupt pending
1517 TOMSetPendingTimerInt();
1518 GPUSetIRQLine(GPUIRQ_TIMER, ASSERT_LINE); // It does the 'IRQ enabled' checking
1520 // if (INT1_WREG & 0x08)
1521 if (TOMIRQEnabled(IRQ_TIMER))
1522 m68k_set_irq(2); // Generate a 68K IPL 2...