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)
279 #define OLP 0x20 // Object list pointer
280 #define OBF 0x26 // Object processor flag
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
291 #define HS 0x34 // Horizontal sync
292 #define HVS 0x36 // Horizontal vertical sync
293 #define HDB1 0x38 // Horizontal display begin 1
296 #define VP 0x3E // Value ranges from 1 - 2048 (value written + 1)
297 #define VBB 0x40 // Vertical blank begin
299 #define VS 0x44 // Vertical sync
300 #define VDB 0x46 // Vertical display begin
302 #define VEB 0x4A // Vertical equalization begin
303 #define VEE 0x4C // Vertical equalization end
304 #define VI 0x4E // Vertical interrupt
307 #define HEQ 0x54 // Horizontal equalization end
308 #define BG 0x58 // Background color
311 //NOTE: These arbitrary cutoffs are NOT taken into account for PAL jaguar screens. !!! FIX !!!
313 // Arbitrary video cutoff values (i.e., first/last visible spots on a TV, in HC ticks)
314 /*#define LEFT_VISIBLE_HC 208
315 #define RIGHT_VISIBLE_HC 1528//*/
316 #define LEFT_VISIBLE_HC 208
317 #define RIGHT_VISIBLE_HC 1488
318 //#define TOP_VISIBLE_VC 25
319 //#define BOTTOM_VISIBLE_VC 503
320 #define TOP_VISIBLE_VC 31
321 #define BOTTOM_VISIBLE_VC 511
323 //Are these PAL horizontals correct?
324 //They seem to be for the most part, but there are some games that seem to be
325 //shifted over to the right from this "window".
326 #define LEFT_VISIBLE_HC_PAL 208
327 #define RIGHT_VISIBLE_HC_PAL 1488
328 #define TOP_VISIBLE_VC_PAL 67
329 #define BOTTOM_VISIBLE_VC_PAL 579
331 //This can be defined in the makefile as well...
332 //(It's easier to do it here, though...)
335 uint8 tomRam8[0x4000];
336 uint32 tomWidth, tomHeight;
337 uint32 tomTimerPrescaler;
338 uint32 tomTimerDivider;
339 int32 tomTimerCounter;
340 uint16 tom_jerry_int_pending, tom_timer_int_pending, tom_object_int_pending,
341 tom_gpu_int_pending, tom_video_int_pending;
343 // These are set by the "user" of the Jaguar core lib, since these are
344 // OS/system dependent.
345 uint32 * screenBuffer;
348 static const char * videoMode_to_str[8] =
349 { "16 BPP CRY", "24 BPP RGB", "16 BPP DIRECT", "16 BPP RGB",
350 "Mixed mode", "24 BPP RGB", "16 BPP DIRECT", "16 BPP RGB" };
352 typedef void (render_xxx_scanline_fn)(uint32 *);
354 // Private function prototypes
356 void tom_render_16bpp_cry_scanline(uint32 * backbuffer);
357 void tom_render_24bpp_scanline(uint32 * backbuffer);
358 void tom_render_16bpp_direct_scanline(uint32 * backbuffer);
359 void tom_render_16bpp_rgb_scanline(uint32 * backbuffer);
360 void tom_render_16bpp_cry_rgb_mix_scanline(uint32 * backbuffer);
362 //render_xxx_scanline_fn * scanline_render_normal[] =
363 render_xxx_scanline_fn * scanline_render[] =
365 tom_render_16bpp_cry_scanline,
366 tom_render_24bpp_scanline,
367 tom_render_16bpp_direct_scanline,
368 tom_render_16bpp_rgb_scanline,
369 tom_render_16bpp_cry_rgb_mix_scanline,
370 tom_render_24bpp_scanline,
371 tom_render_16bpp_direct_scanline,
372 tom_render_16bpp_rgb_scanline
375 // Screen info for various games [PAL]...
378 TOM: Horizontal Period written by M68K: 850 (+1*2 = 1702)
379 TOM: Horizontal Blank Begin written by M68K: 1711
380 TOM: Horizontal Blank End written by M68K: 158
381 TOM: Horizontal Display End written by M68K: 1696
382 TOM: Horizontal Display Begin 1 written by M68K: 166
383 TOM: Vertical Period written by M68K: 623 (non-interlaced)
384 TOM: Vertical Blank End written by M68K: 34
385 TOM: Vertical Display Begin written by M68K: 46
386 TOM: Vertical Display End written by M68K: 526
387 TOM: Vertical Blank Begin written by M68K: 600
388 TOM: Vertical Sync written by M68K: 618
389 TOM: Horizontal Display End written by M68K: 1665
390 TOM: Horizontal Display Begin 1 written by M68K: 203
391 TOM: Vertical Display Begin written by M68K: 38
392 TOM: Vertical Display End written by M68K: 518
393 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 151)
394 TOM: Horizontal Display End written by M68K: 1713
395 TOM: Horizontal Display Begin 1 written by M68K: 157
396 TOM: Vertical Display Begin written by M68K: 35
397 TOM: Vertical Display End written by M68K: 2047
398 Horizontal range: 157 - 1713 (width: 1557 / 4 = 389.25, / 5 = 315.4)
401 TOM: Horizontal Period written by M68K: 845 (+1*2 = 1692)
402 TOM: Horizontal Blank Begin written by M68K: 1700
403 TOM: Horizontal Blank End written by M68K: 122
404 TOM: Horizontal Display End written by M68K: 1600
405 TOM: Horizontal Display Begin 1 written by M68K: 268
406 TOM: Vertical Period written by M68K: 523 (non-interlaced)
407 TOM: Vertical Blank End written by M68K: 40
408 TOM: Vertical Display Begin written by M68K: 44
409 TOM: Vertical Display End written by M68K: 492
410 TOM: Vertical Blank Begin written by M68K: 532
411 TOM: Vertical Sync written by M68K: 513
412 TOM: Video Mode written by M68K: 04C7. PWIDTH = 3, MODE = 16 BPP RGB, flags: BGEN (VC = 461)
415 TOM: Horizontal Display End written by M68K: 1713
416 TOM: Horizontal Display Begin 1 written by M68K: 157
417 TOM: Vertical Display Begin written by M68K: 35
418 TOM: Vertical Display End written by M68K: 2047
419 TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 89)
420 TOM: Horizontal Display Begin 1 written by M68K: 208
421 TOM: Horizontal Display End written by M68K: 1662
422 TOM: Vertical Display Begin written by M68K: 100
423 TOM: Vertical Display End written by M68K: 2047
424 TOM: Video Mode written by M68K: 07C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN VARMOD (VC = 205)
425 Horizontal range: 208 - 1662 (width: 1455 / 4 = 363.5)
428 TOM: Vertical Display Begin written by M68K: 96
429 TOM: Vertical Display End written by M68K: 2047
430 TOM: Horizontal Display Begin 1 written by M68K: 239
431 TOM: Horizontal Display End written by M68K: 1692
432 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 378)
433 TOM: Vertical Display Begin written by M68K: 44
434 TOM: Vertical Display End written by M68K: 2047
435 TOM: Horizontal Display Begin 1 written by M68K: 239
436 TOM: Horizontal Display End written by M68K: 1692
437 TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 559)
438 TOM: Vertical Display Begin written by M68K: 84
439 TOM: Vertical Display End written by M68K: 2047
440 TOM: Horizontal Display Begin 1 written by M68K: 239
441 TOM: Horizontal Display End written by M68K: 1692
442 TOM: Vertical Display Begin written by M68K: 44
443 TOM: Vertical Display End written by M68K: 2047
444 TOM: Horizontal Display Begin 1 written by M68K: 239
445 TOM: Horizontal Display End written by M68K: 1692
446 Horizontal range: 239 - 1692 (width: 1454 / 4 = 363.5)
450 // Screen info for various games [NTSC]...
453 TOM: Horizontal Display End written by M68K: 1727
454 TOM: Horizontal Display Begin 1 written by M68K: 123
455 TOM: Vertical Display Begin written by M68K: 25
456 TOM: Vertical Display End written by M68K: 2047
457 TOM: Video Mode written by M68K: 0EC1. PWIDTH = 8, MODE = 16 BPP CRY, flags: BGEN (VC = 5)
458 Also does PWIDTH = 4...
459 Vertical resolution: 238 lines
462 TOM: Horizontal Display End written by M68K: 1727
463 TOM: Horizontal Display Begin 1 written by M68K: 123
464 TOM: Vertical Display Begin written by M68K: 25
465 TOM: Vertical Display End written by M68K: 2047
466 TOM: Vertical Interrupt written by M68K: 507
467 TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 92)
468 TOM: Horizontal Display Begin 1 written by M68K: 208
469 TOM: Horizontal Display End written by M68K: 1670
470 Display starts at 31, then 52!
471 Vertical resolution: 238 lines
474 TOM: Horizontal Display End written by M68K: 1727
475 TOM: Horizontal Display Begin 1 written by M68K: 123
476 TOM: Vertical Display Begin written by M68K: 25
477 TOM: Vertical Display End written by M68K: 2047
478 TOM: Video Mode written by GPU: 08C7. PWIDTH = 5, MODE = 16 BPP RGB, flags: BGEN (VC = 4)
479 TOM: Video Mode written by GPU: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 508)
480 Display starts at 31 (PWIDTH = 4), 24 (PWIDTH = 5)
483 TOM: Vertical Interrupt written by M68K: 2047
484 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 0)
485 TOM: Horizontal Display End written by M68K: 1727
486 TOM: Horizontal Display Begin 1 written by M68K: 123
487 TOM: Vertical Display Begin written by M68K: 25
488 TOM: Vertical Display End written by M68K: 2047
489 TOM: Vertical Interrupt written by M68K: 507
490 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 369)
491 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 510)
492 TOM: Video Mode written by M68K: 06C3. PWIDTH = 4, MODE = 24 BPP RGB, flags: BGEN (VC = 510)
494 Vertical resolution: 238 lines
495 [Seems to be a problem between the horizontal positioning of the 16-bit CRY & 24-bit RGB]
498 TOM: Horizontal Period written by M68K: 844 (+1*2 = 1690)
499 TOM: Horizontal Blank Begin written by M68K: 1713
500 TOM: Horizontal Blank End written by M68K: 125
501 TOM: Horizontal Display End written by M68K: 1696
502 TOM: Horizontal Display Begin 1 written by M68K: 166
503 TOM: Vertical Period written by M68K: 523 (non-interlaced)
504 TOM: Vertical Blank End written by M68K: 24
505 TOM: Vertical Display Begin written by M68K: 46
506 TOM: Vertical Display End written by M68K: 496
507 TOM: Vertical Blank Begin written by M68K: 500
508 TOM: Vertical Sync written by M68K: 517
509 TOM: Vertical Interrupt written by M68K: 497
510 TOM: Video Mode written by M68K: 04C1. PWIDTH = 3, MODE = 16 BPP CRY, flags: BGEN (VC = 270)
514 TOM: Horizontal Display End written by M68K: 1727
515 TOM: Horizontal Display Begin 1 written by M68K: 123
516 TOM: Vertical Display Begin written by M68K: 25
517 TOM: Vertical Display End written by M68K: 2047
518 TOM: Vertical Interrupt written by M68K: 507
519 TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 9)
522 TOM: Horizontal Display End written by M68K: 1823
523 TOM: Horizontal Display Begin 1 written by M68K: 45
524 TOM: Vertical Display Begin written by M68K: 40
525 TOM: Vertical Display End written by M68K: 2047
526 TOM: Vertical Interrupt written by M68K: 491
527 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 398)
528 Display starts at 11 (123 - 45 = 78, 78 / 4 = 19 pixels to skip)
529 Width is 417, so maybe width of 379 would be good (starting at 123, ending at 1639)
530 Vertical resolution: 238 lines
533 TOM: Horizontal Display End written by M68K: 1727
534 TOM: Horizontal Display Begin 1 written by M68K: 188
535 TOM: Vertical Display Begin written by M68K: 1
536 TOM: Vertical Display End written by M68K: 2047
537 TOM: Vertical Interrupt written by M68K: 483
538 TOM: Video Mode written by M68K: 08C7. PWIDTH = 5, MODE = 16 BPP RGB, flags: BGEN (VC = 99)
539 Width would be 303 with above scheme, but border width would be 13 pixels
542 Vertical resolution: 238 lines
545 uint32 RGB16ToRGB32[0x10000];
546 uint32 CRY16ToRGB32[0x10000];
547 uint32 MIX16ToRGB32[0x10000];
549 #warning "This is not endian-safe. !!! FIX !!!"
550 void TOMFillLookupTables(void)
552 // NOTE: Jaguar 16-bit (non-CRY) color is RBG 556 like so:
553 // RRRR RBBB BBGG GGGG
554 for(uint32 i=0; i<0x10000; i++)
555 //hm. RGB16ToRGB32[i] = 0xFF000000
556 // | ((i & 0xF100) >> 8) | ((i & 0xE000) >> 13)
557 // | ((i & 0x07C0) << 13) | ((i & 0x0700) << 8)
558 // | ((i & 0x003F) << 10) | ((i & 0x0030) << 4);
559 RGB16ToRGB32[i] = 0x000000FF
560 | ((i & 0xF100) << 16) // Red
561 | ((i & 0x003F) << 18) // Green
562 | ((i & 0x07C0) << 5); // Blue
564 for(uint32 i=0; i<0x10000; i++)
566 uint32 cyan = (i & 0xF000) >> 12,
567 red = (i & 0x0F00) >> 8,
568 intensity = (i & 0x00FF);
570 uint32 r = (((uint32)redcv[cyan][red]) * intensity) >> 8,
571 g = (((uint32)greencv[cyan][red]) * intensity) >> 8,
572 b = (((uint32)bluecv[cyan][red]) * intensity) >> 8;
574 //hm. CRY16ToRGB32[i] = 0xFF000000 | (b << 16) | (g << 8) | r;
575 CRY16ToRGB32[i] = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
576 MIX16ToRGB32[i] = (i & 0x01 ? RGB16ToRGB32[i] : CRY16ToRGB32[i]);
580 void TOMSetPendingJERRYInt(void)
582 tom_jerry_int_pending = 1;
585 void TOMSetPendingTimerInt(void)
587 tom_timer_int_pending = 1;
590 void TOMSetPendingObjectInt(void)
592 tom_object_int_pending = 1;
595 void TOMSetPendingGPUInt(void)
597 tom_gpu_int_pending = 1;
600 void TOMSetPendingVideoInt(void)
602 tom_video_int_pending = 1;
605 uint8 * TOMGetRamPointer(void)
610 uint8 TOMGetVideoMode(void)
612 uint16 vmode = GET16(tomRam8, VMODE);
613 return ((vmode & VARMOD) >> 6) | ((vmode & MODE) >> 1);
616 //Used in only one place (and for debug purposes): OBJECTP.CPP
617 #warning "Used in only one place (and for debug purposes): OBJECTP.CPP !!! FIX !!!"
618 uint16 TOMGetVDB(void)
620 return GET16(tomRam8, VDB);
624 // 16 BPP CRY/RGB mixed mode rendering
626 void tom_render_16bpp_cry_rgb_mix_scanline(uint32 * backbuffer)
628 //CHANGED TO 32BPP RENDERING
629 uint16 width = tomWidth;
630 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
632 //New stuff--restrict our drawing...
633 uint8 pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
634 //NOTE: May have to check HDB2 as well!
635 // Get start position in HC ticks
636 int16 startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL);
639 current_line_buffer += 2 * -startPos;
641 //This case doesn't properly handle the "start on the right side of virtual screen" case
642 //Dunno why--looks Ok...
643 //What *is* for sure wrong is that it doesn't copy the linebuffer's BG pixels...
644 //This should likely be 4 instead of 2 (?--not sure)
645 backbuffer += 2 * startPos, width -= startPos;
649 uint16 color = (*current_line_buffer++) << 8;
650 color |= *current_line_buffer++;
651 *backbuffer++ = MIX16ToRGB32[color];
657 // 16 BPP CRY mode rendering
659 void tom_render_16bpp_cry_scanline(uint32 * backbuffer)
661 //CHANGED TO 32BPP RENDERING
662 uint16 width = tomWidth;
663 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
665 //New stuff--restrict our drawing...
666 uint8 pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
667 //NOTE: May have to check HDB2 as well!
668 int16 startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL);// Get start position in HC ticks
671 current_line_buffer += 2 * -startPos;
673 //This should likely be 4 instead of 2 (?--not sure)
674 backbuffer += 2 * startPos, width -= startPos;
678 uint16 color = (*current_line_buffer++) << 8;
679 color |= *current_line_buffer++;
680 *backbuffer++ = CRY16ToRGB32[color];
686 // 24 BPP mode rendering
688 void tom_render_24bpp_scanline(uint32 * backbuffer)
690 //CHANGED TO 32BPP RENDERING
691 uint16 width = tomWidth;
692 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
694 //New stuff--restrict our drawing...
695 uint8 pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
696 //NOTE: May have to check HDB2 as well!
697 int16 startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL); // Get start position in HC ticks
700 current_line_buffer += 4 * -startPos;
702 //This should likely be 4 instead of 2 (?--not sure)
703 backbuffer += 2 * startPos, width -= startPos;
707 uint32 g = *current_line_buffer++;
708 uint32 r = *current_line_buffer++;
709 current_line_buffer++;
710 uint32 b = *current_line_buffer++;
711 //hm. *backbuffer++ = 0xFF000000 | (b << 16) | (g << 8) | r;
712 *backbuffer++ = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
717 //Seems to me that this is NOT a valid mode--the JTRM seems to imply that you would need
718 //extra hardware outside of the Jaguar console to support this!
720 // 16 BPP direct mode rendering
722 void tom_render_16bpp_direct_scanline(uint32 * backbuffer)
724 uint16 width = tomWidth;
725 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
729 uint16 color = (*current_line_buffer++) << 8;
730 color |= *current_line_buffer++;
731 *backbuffer++ = color >> 1;
737 // 16 BPP RGB mode rendering
739 void tom_render_16bpp_rgb_scanline(uint32 * backbuffer)
741 //CHANGED TO 32BPP RENDERING
742 // 16 BPP RGB: 0-5 green, 6-10 blue, 11-15 red
744 uint16 width = tomWidth;
745 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
747 //New stuff--restrict our drawing...
748 uint8 pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
749 //NOTE: May have to check HDB2 as well!
750 int16 startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL); // Get start position in HC ticks
754 current_line_buffer += 2 * -startPos;
756 //This should likely be 4 instead of 2 (?--not sure)
757 backbuffer += 2 * startPos, width -= startPos;
761 uint32 color = (*current_line_buffer++) << 8;
762 color |= *current_line_buffer++;
763 *backbuffer++ = RGB16ToRGB32[color];
769 /*void TOMResetBackbuffer(uint32 * backbuffer)
771 TOMBackbuffer = backbuffer;
775 // Process a single scanline
776 // (this is bad terminology; each tick of the VC is actually a half-line)
778 void TOMExecHalfline(uint16 halfline, bool render)
780 bool inActiveDisplayArea = true;
782 //Interlacing is still not handled correctly here... !!! FIX !!!
783 if (halfline & 0x01) // Execute OP only on even lines (non-interlaced only!)
786 //Hm, it seems that the OP needs to execute from zero, so let's try it:
787 // And it works! But need to do some optimizations in the OP to keep it from attempting
788 // to do a scanline render in the non-display area... [DONE]
789 //this seems to cause a regression in certain games, like rayman
790 //which means I have to dig thru the asic nets to see what's wrong...
792 No, the OP doesn't start until VDB, that much is certain. The thing is, VDB is the
793 HALF line that the OP starts on--which means that it needs to start at VDB / 2!!!
795 Hrm, doesn't seem to be enough, though it should be... still sticks for 20 frames.
798 // 16 isn't enough, and neither is 32 for raptgun. 32 fucks up Rayman
799 // if (halfline >= ((uint16)GET16(tomRam8, VDB) / 2) && halfline < ((uint16)GET16(tomRam8, VDE) / 2))
800 if (halfline >= (uint16)GET16(tomRam8, VDB) && halfline < (uint16)GET16(tomRam8, VDE))
801 // if (halfline >= ((uint16)GET16(tomRam8, VDB) - 16) && halfline < (uint16)GET16(tomRam8, VDE))
802 // if (halfline >= 20 && halfline < (uint16)GET16(tomRam8, VDE))
806 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
807 uint8 bgHI = tomRam8[BG], bgLO = tomRam8[BG + 1];
809 // Clear line buffer with BG
810 if (GET16(tomRam8, VMODE) & BGEN) // && (CRY or RGB16)...
811 for(uint32 i=0; i<720; i++)
812 *current_line_buffer++ = bgHI, *current_line_buffer++ = bgLO;
814 OPProcessList(halfline, render);
818 inActiveDisplayArea = false;
820 inActiveDisplayArea =
821 (halfline >= (uint16)GET16(tomRam8, VDB) && halfline < (uint16)GET16(tomRam8, VDE)
824 if (halfline < (uint16)GET16(tomRam8, VDE))
826 if (render)//With JaguarExecuteNew() this is always true...
828 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
829 uint8 bgHI = tomRam8[BG], bgLO = tomRam8[BG + 1];
831 // Clear line buffer with BG
832 if (GET16(tomRam8, VMODE) & BGEN) // && (CRY or RGB16)...
833 for(uint32 i=0; i<720; i++)
834 *current_line_buffer++ = bgHI, *current_line_buffer++ = bgLO;
836 // OPProcessList(halfline, render);
837 //This seems to take care of it...
838 OPProcessList(halfline, inActiveDisplayArea);
843 // Try to take PAL into account... [We do now!]
845 uint16 topVisible = (vjs.hardwareTypeNTSC ? TOP_VISIBLE_VC : TOP_VISIBLE_VC_PAL),
846 bottomVisible = (vjs.hardwareTypeNTSC ? BOTTOM_VISIBLE_VC : BOTTOM_VISIBLE_VC_PAL);
847 uint32 * TOMCurrentLine = &(screenBuffer[((halfline - topVisible) / 2) * screenPitch]);
849 // Here's our virtualized scanline code...
851 if (halfline >= topVisible && halfline < bottomVisible)
853 if (inActiveDisplayArea)
855 //NOTE: The following doesn't put BORDER color on the sides... !!! FIX !!!
856 #warning "The following doesn't put BORDER color on the sides... !!! FIX !!!"
857 if (vjs.renderType == RT_NORMAL)
858 // scanline_render[TOMGetVideoMode()](TOMBackbuffer);
859 scanline_render[TOMGetVideoMode()](TOMCurrentLine);
863 tom_render_16bpp_cry_scanline,
864 tom_render_24bpp_scanline,
865 tom_render_16bpp_direct_scanline,
866 tom_render_16bpp_rgb_scanline,
867 tom_render_16bpp_cry_rgb_mix_scanline,
868 tom_render_24bpp_scanline,
869 tom_render_16bpp_direct_scanline,
870 tom_render_16bpp_rgb_scanline
872 #define MODE 0x0006 // Line buffer to video generator mode
873 #define VARMOD 0x0100 // Mixed CRY/RGB16 mode (only works in MODE 0!)
875 uint8 pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
876 uint8 mode = ((GET16(tomRam8, VMODE) & MODE) >> 1);
877 bool varmod = GET16(tomRam8, VMODE) & VARMOD;
878 //The video texture line buffer ranges from 0 to 1279, with its left edge starting at
879 //LEFT_VISIBLE_HC. So, we need to start writing into the backbuffer at HDB1, using pwidth
880 //as our scaling factor. The way it generates its image on a real TV!
882 //So, for example, if HDB1 is less than LEFT_VISIBLE_HC, then we have to figure out where
883 //in the VTLB that we start writing pixels from the Jaguar line buffer (VTLB start=0,
887 // 24 BPP mode rendering
889 void tom_render_24bpp_scanline(uint32 * backbuffer)
891 //CHANGED TO 32BPP RENDERING
892 uint16 width = tomWidth;
893 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
895 //New stuff--restrict our drawing...
896 uint8 pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
897 //NOTE: May have to check HDB2 as well!
898 int16 startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL); // Get start position in HC ticks
901 current_line_buffer += 4 * -startPos;
903 //This should likely be 4 instead of 2 (?--not sure)
904 backbuffer += 2 * startPos, width -= startPos;
908 uint32 g = *current_line_buffer++;
909 uint32 r = *current_line_buffer++;
910 current_line_buffer++;
911 uint32 b = *current_line_buffer++;
912 *backbuffer++ = 0xFF000000 | (b << 16) | (g << 8) | r;
922 // If outside of VDB & VDE, then display the border color
923 uint32 * currentLineBuffer = TOMCurrentLine;
924 uint8 g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
925 //Hm. uint32 pixel = 0xFF000000 | (b << 16) | (g << 8) | r;
926 uint32 pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
928 for(uint32 i=0; i<tomWidth; i++)
929 *currentLineBuffer++ = pixel;
935 // TOM initialization
939 TOMFillLookupTables();
949 WriteLog("TOM: Resolution %i x %i %s\n", TOMGetVideoModeWidth(), TOMGetVideoModeHeight(),
950 videoMode_to_str[TOMGetVideoMode()]);
951 // WriteLog("\ntom: object processor:\n");
952 // WriteLog("tom: pointer to object list: 0x%.8x\n",op_get_list_pointer());
953 // WriteLog("tom: INT1=0x%.2x%.2x\n",TOMReadByte(0xf000e0),TOMReadByte(0xf000e1));
956 // memory_free(tomRam8);
957 // memory_free(tom_cry_rgb_mix_lut);
960 uint32 TOMGetVideoModeWidth(void)
962 //These widths are pretty bogus. Should use HDB1/2 & HDE/HBB & PWIDTH to calc the width...
963 // uint32 width[8] = { 1330, 665, 443, 332, 266, 222, 190, 166 };
964 //Temporary, for testing Doom...
965 // uint32 width[8] = { 1330, 665, 443, 332, 266, 222, 190, 332 };
967 // Note that the following PWIDTH values have the following pixel aspect ratios:
968 // PWIDTH = 1 -> 0.25:1 (1:4) pixels (X:Y ratio)
969 // PWIDTH = 2 -> 0.50:1 (1:2) pixels
970 // PWIDTH = 3 -> 0.75:1 (3:4) pixels
971 // PWIDTH = 4 -> 1.00:1 (1:1) pixels
972 // PWIDTH = 5 -> 1.25:1 (5:4) pixels
973 // PWIDTH = 6 -> 1.50:1 (3:2) pixels
974 // PWIDTH = 7 -> 1.75:1 (7:4) pixels
975 // PWIDTH = 8 -> 2.00:1 (2:1) pixels
977 // Also note that the JTRM says that PWIDTH of 4 gives pixels that are "about" square--
978 // this implies that the other modes have pixels that are *not* square!
979 // Also, I seriously doubt that you will see any games that use PWIDTH = 1!
981 // NOTE: Even though the PWIDTH value is + 1, here we're using a zero-based index and
982 // so we don't bother to add one...
983 // return width[(GET16(tomRam8, VMODE) & PWIDTH) >> 9];
985 // Now, we just calculate it...
986 /* uint16 hdb1 = GET16(tomRam8, HDB1), hde = GET16(tomRam8, HDE),
987 hbb = GET16(tomRam8, HBB), pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
988 // return ((hbb < hde ? hbb : hde) - hdb1) / pwidth;
989 //Temporary, for testing Doom...
990 return ((hbb < hde ? hbb : hde) - hdb1) / (pwidth == 8 ? 4 : pwidth);*/
992 // To make it easier to make a quasi-fixed display size, we restrict the viewing
993 // area to an arbitrary range of the Horizontal Count.
994 uint16 pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
995 return (vjs.hardwareTypeNTSC ? RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC : RIGHT_VISIBLE_HC_PAL - LEFT_VISIBLE_HC_PAL) / pwidth;
996 //Temporary, for testing Doom...
997 // return (RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC) / (pwidth == 8 ? 4 : pwidth);
998 //// return (RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC) / (pwidth == 4 ? 8 : pwidth);
1000 // More speculating...
1001 // According to the JTRM, the number of potential pixels across is given by the
1002 // Horizontal Period (HP - in NTSC this is 845). The Horizontal Count counts from
1003 // zero to this value twice per scanline (the high bit is set on the second count).
1004 // HBE and HBB define the absolute "black" limits of the screen, while HDB1/2 and
1005 // HDE determine the extent of the OP "on" time. I.e., when the OP is turned on by
1006 // HDB1, it starts fetching the line from position 0 in LBUF.
1008 // The trick, it would seem, is to figure out how long the typical visible scanline
1009 // of a TV is in HP ticks and limit the visible area to that (divided by PWIDTH, of
1010 // course). Using that length, we can establish an "absolute left display limit" with
1011 // which to measure HBB & HDB1/2 against when rendering LBUF (i.e., if HDB1 is 20 ticks
1012 // to the right of the ALDL and PWIDTH is 4, then start writing the LBUF starting at
1013 // backbuffer + 5 pixels).
1015 // That's basically what we're doing now...!
1018 // *** SPECULATION ***
1019 // It might work better to virtualize the height settings, i.e., set the vertical
1020 // height at 240 lines and clip using the VDB and VDE/VP registers...
1021 // Same with the width... [Width is pretty much virtualized now.]
1023 // Now that that the width is virtualized, let's virtualize the height. :-)
1024 uint32 TOMGetVideoModeHeight(void)
1026 // uint16 vmode = GET16(tomRam8, VMODE);
1027 // uint16 vbe = GET16(tomRam8, VBE);
1028 // uint16 vbb = GET16(tomRam8, VBB);
1029 // uint16 vdb = GET16(tomRam8, VDB);
1030 // uint16 vde = GET16(tomRam8, VDE);
1031 // uint16 vp = GET16(tomRam8, VP);
1033 /* if (vde == 0xFFFF)
1036 // return 227;//WAS:(vde/*-vdb*/) >> 1;
1037 // The video mode height probably works this way:
1038 // VC counts from 0 to VP. VDB starts the OP. Either when
1039 // VDE is reached or VP, the OP is stopped. Let's try it...
1040 // Also note that we're conveniently ignoring interlaced display modes...!
1041 // return ((vde > vp ? vp : vde) - vdb) >> 1;
1042 // return ((vde > vbb ? vbb : vde) - vdb) >> 1;
1043 //Let's try from the Vertical Blank interval...
1045 // return (vbb - vbe) >> 1; // Again, doesn't take interlacing into account...
1046 // This of course doesn't take interlacing into account. But I haven't seen any
1047 // Jaguar software that takes advantage of it either...
1048 //Also, doesn't reflect PAL Jaguar either... !!! FIX !!! [DONE]
1049 // return 240; // Set virtual screen height to 240 lines...
1050 return (vjs.hardwareTypeNTSC ? 240 : 256);
1055 // Now PAL friendly!
1061 memset(tomRam8, 0x00, 0x4000);
1063 if (vjs.hardwareTypeNTSC)
1065 SET16(tomRam8, MEMCON1, 0x1861);
1066 SET16(tomRam8, MEMCON2, 0x35CC);
1067 SET16(tomRam8, HP, 844); // Horizontal Period (1-based; HP=845)
1068 SET16(tomRam8, HBB, 1713); // Horizontal Blank Begin
1069 SET16(tomRam8, HBE, 125); // Horizontal Blank End
1070 SET16(tomRam8, HDE, 1665); // Horizontal Display End
1071 SET16(tomRam8, HDB1, 203); // Horizontal Display Begin 1
1072 SET16(tomRam8, VP, 523); // Vertical Period (1-based; in this case VP = 524)
1073 SET16(tomRam8, VBE, 24); // Vertical Blank End
1074 SET16(tomRam8, VDB, 38); // Vertical Display Begin
1075 SET16(tomRam8, VDE, 518); // Vertical Display End
1076 SET16(tomRam8, VBB, 500); // Vertical Blank Begin
1077 SET16(tomRam8, VS, 517); // Vertical Sync
1078 SET16(tomRam8, VMODE, 0x06C1);
1082 SET16(tomRam8, MEMCON1, 0x1861);
1083 SET16(tomRam8, MEMCON2, 0x35CC);
1084 SET16(tomRam8, HP, 850); // Horizontal Period
1085 SET16(tomRam8, HBB, 1711); // Horizontal Blank Begin
1086 SET16(tomRam8, HBE, 158); // Horizontal Blank End
1087 SET16(tomRam8, HDE, 1665); // Horizontal Display End
1088 SET16(tomRam8, HDB1, 203); // Horizontal Display Begin 1
1089 SET16(tomRam8, VP, 623); // Vertical Period (1-based; in this case VP = 624)
1090 SET16(tomRam8, VBE, 34); // Vertical Blank End
1091 SET16(tomRam8, VDB, 38); // Vertical Display Begin
1092 SET16(tomRam8, VDE, 518); // Vertical Display End
1093 SET16(tomRam8, VBB, 600); // Vertical Blank Begin
1094 SET16(tomRam8, VS, 618); // Vertical Sync
1095 SET16(tomRam8, VMODE, 0x06C1);
1101 tom_jerry_int_pending = 0;
1102 tom_timer_int_pending = 0;
1103 tom_object_int_pending = 0;
1104 tom_gpu_int_pending = 0;
1105 tom_video_int_pending = 0;
1107 tomTimerPrescaler = 0; // TOM PIT is disabled
1108 tomTimerDivider = 0;
1109 tomTimerCounter = 0;
1113 // TOM byte access (read)
1115 uint8 TOMReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
1117 //???Is this needed???
1118 // It seems so. Perhaps it's the +$8000 offset being written to (32-bit interface)?
1119 // However, the 32-bit interface is WRITE ONLY, so that can't be it...
1120 // Also, the 68K CANNOT make use of the 32-bit interface, since its bus width is only 16-bits...
1121 // offset &= 0xFF3FFF;
1124 WriteLog("TOM: Reading byte at %06X for %s\n", offset, whoName[who]);
1127 if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
1128 return GPUReadByte(offset, who);
1129 else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
1130 return GPUReadByte(offset, who);
1131 /* else if ((offset >= 0xF00010) && (offset < 0xF00028))
1132 return OPReadByte(offset, who);*/
1133 else if ((offset >= 0xF02200) && (offset < 0xF022A0))
1134 return BlitterReadByte(offset, who);
1135 else if (offset == 0xF00050)
1136 return tomTimerPrescaler >> 8;
1137 else if (offset == 0xF00051)
1138 return tomTimerPrescaler & 0xFF;
1139 else if (offset == 0xF00052)
1140 return tomTimerDivider >> 8;
1141 else if (offset == 0xF00053)
1142 return tomTimerDivider & 0xFF;
1144 return tomRam8[offset & 0x3FFF];
1148 // TOM word access (read)
1150 uint16 TOMReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
1152 //???Is this needed???
1153 // offset &= 0xFF3FFF;
1155 WriteLog("TOM: Reading word at %06X for %s\n", offset, whoName[who]);
1157 if (offset >= 0xF02000 && offset <= 0xF020FF)
1158 WriteLog("TOM: Read attempted from GPU register file by %s (unimplemented)!\n", whoName[who]);
1160 if (offset == 0xF000E0)
1162 // For reading, should only return the lower 5 bits...
1163 uint16 data = (tom_jerry_int_pending << 4) | (tom_timer_int_pending << 3)
1164 | (tom_object_int_pending << 2) | (tom_gpu_int_pending << 1)
1165 | (tom_video_int_pending << 0);
1166 //WriteLog("tom: interrupt status is 0x%.4x \n",data);
1169 //Shoud be handled by the jaguar main loop now... And it is! ;-)
1170 /* else if (offset == 0xF00006) // VC
1171 // What if we're in interlaced mode?
1172 // According to docs, in non-interlace mode VC is ALWAYS even...
1173 // return (tom_scanline << 1);// + 1;
1174 //But it's causing Rayman to be fucked up... Why???
1175 //Because VC is even in NI mode when calling the OP! That's why!
1176 return (tom_scanline << 1) + 1;//*/
1178 // F00004 R/W -----xxx xxxxxxxx HC - horizontal count
1179 // -----x-- -------- (which half of the display)
1180 // ------xx xxxxxxxx (10-bit counter)
1182 // This is a kludge to get the HC working somewhat... What we really should do here
1183 // is check what the global time is at the time of the read and calculate the correct HC...
1185 else if (offset == 0xF00004)
1186 return rand() & 0x03FF;
1187 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE + 0x20))
1188 return GPUReadWord(offset, who);
1189 else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
1190 return GPUReadWord(offset, who);
1191 /* else if ((offset >= 0xF00010) && (offset < 0xF00028))
1192 return OPReadWord(offset, who);*/
1193 else if ((offset >= 0xF02200) && (offset < 0xF022A0))
1194 return BlitterReadWord(offset, who);
1195 else if (offset == 0xF00050)
1196 return tomTimerPrescaler;
1197 else if (offset == 0xF00052)
1198 return tomTimerDivider;
1201 return (TOMReadByte(offset, who) << 8) | TOMReadByte(offset + 1, who);
1204 #define TOM_STRICT_MEMORY_ACCESS
1206 // TOM byte access (write)
1208 void TOMWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
1211 WriteLog("TOM: Writing byte %02X at %06X", data, offset);
1213 //???Is this needed???
1214 // Perhaps on the writes--32-bit writes that is! And masked with FF7FFF...
1215 #ifndef TOM_STRICT_MEMORY_ACCESS
1218 // "Fast" (32-bit only) write access to the GPU
1219 // if ((offset >= 0xF0A100) && (offset <= 0xF0BFFF))
1220 if ((offset >= 0xF08000) && (offset <= 0xF0BFFF))
1224 WriteLog(" -->[%06X] by %s\n", offset, whoName[who]);
1227 #ifdef TOM_STRICT_MEMORY_ACCESS
1228 // Sanity check ("Aww, there ain't no Sanity Clause...")
1229 if ((offset < 0xF00000) || (offset > 0xF03FFF))
1233 if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
1235 GPUWriteByte(offset, data, who);
1238 else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
1240 GPUWriteByte(offset, data, who);
1243 /* else if ((offset >= 0xF00010) && (offset < 0xF00028))
1245 OPWriteByte(offset, data, who);
1248 else if ((offset >= 0xF02200) && (offset < 0xF022A0))
1250 BlitterWriteByte(offset, data, who);
1253 else if (offset == 0xF00050)
1255 tomTimerPrescaler = (tomTimerPrescaler & 0x00FF) | (data << 8);
1259 else if (offset == 0xF00051)
1261 tomTimerPrescaler = (tomTimerPrescaler & 0xFF00) | data;
1265 else if (offset == 0xF00052)
1267 tomTimerDivider = (tomTimerDivider & 0x00FF) | (data << 8);
1271 else if (offset == 0xF00053)
1273 tomTimerDivider = (tomTimerDivider & 0xFF00) | data;
1277 else if (offset >= 0xF00400 && offset <= 0xF007FF) // CLUT (A & B)
1279 // Writing to one CLUT writes to the other
1280 offset &= 0x5FF; // Mask out $F00600 (restrict to $F00400-5FF)
1281 tomRam8[offset] = data, tomRam8[offset + 0x200] = data;
1284 tomRam8[offset & 0x3FFF] = data;
1288 // TOM word access (write)
1290 void TOMWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
1293 WriteLog("TOM: Writing byte %04X at %06X", data, offset);
1295 //???Is this needed??? Yes, but we need to be more vigilant than this.
1296 #ifndef TOM_STRICT_MEMORY_ACCESS
1299 // "Fast" (32-bit only) write access to the GPU
1300 // if ((offset >= 0xF0A100) && (offset <= 0xF0BFFF))
1301 if ((offset >= 0xF08000) && (offset <= 0xF0BFFF))
1305 WriteLog(" -->[%06X] by %s\n", offset, whoName[who]);
1308 #ifdef TOM_STRICT_MEMORY_ACCESS
1310 if ((offset < 0xF00000) || (offset > 0xF03FFF))
1314 //if (offset == 0xF00000 + MEMCON1)
1315 // WriteLog("TOM: Memory Configuration 1 written by %s: %04X\n", whoName[who], data);
1316 //if (offset == 0xF00000 + MEMCON2)
1317 // WriteLog("TOM: Memory Configuration 2 written by %s: %04X\n", whoName[who], data);
1318 if (offset >= 0xF02000 && offset <= 0xF020FF)
1319 WriteLog("TOM: Write attempted to GPU register file by %s (unimplemented)!\n", whoName[who]);
1321 if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
1323 GPUWriteWord(offset, data, who);
1326 else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
1328 GPUWriteWord(offset, data, who);
1331 //What's so special about this?
1332 /* else if ((offset >= 0xF00000) && (offset < 0xF00002))
1334 TOMWriteByte(offset, data >> 8);
1335 TOMWriteByte(offset+1, data & 0xFF);
1337 /* else if ((offset >= 0xF00010) && (offset < 0xF00028))
1339 OPWriteWord(offset, data, who);
1342 else if (offset == 0xF00050)
1344 tomTimerPrescaler = data;
1348 else if (offset == 0xF00052)
1350 tomTimerDivider = data;
1354 else if (offset == 0xF000E0)
1358 tom_video_int_pending = 0;
1360 tom_gpu_int_pending = 0;
1362 tom_object_int_pending = 0;
1364 tom_timer_int_pending = 0;
1366 tom_jerry_int_pending = 0;
1370 else if ((offset >= 0xF02200) && (offset <= 0xF0229F))
1372 BlitterWriteWord(offset, data, who);
1375 else if (offset >= 0xF00400 && offset <= 0xF007FE) // CLUT (A & B)
1377 // Writing to one CLUT writes to the other
1378 offset &= 0x5FF; // Mask out $F00600 (restrict to $F00400-5FF)
1379 // Watch out for unaligned writes here! (Not fixed yet)
1380 #warning "!!! Watch out for unaligned writes here !!! FIX !!!"
1381 SET16(tomRam8, offset, data);
1382 SET16(tomRam8, offset + 0x200, data);
1386 if (offset == 0x28) // VMODE (Why? Why not OBF?)
1387 //Actually, we should check to see if the Enable bit of VMODE is set before doing this... !!! FIX !!!
1388 #warning "Actually, we should check to see if the Enable bit of VMODE is set before doing this... !!! FIX !!!"
1389 objectp_running = 1;
1391 if (offset >= 0x30 && offset <= 0x4E)
1392 data &= 0x07FF; // These are (mostly) 11-bit registers
1393 if (offset == 0x2E || offset == 0x36 || offset == 0x54)
1394 data &= 0x03FF; // These are all 10-bit registers
1396 // Fix a lockup bug... :-P
1397 TOMWriteByte(0xF00000 | offset, data >> 8, who);
1398 TOMWriteByte(0xF00000 | (offset+1), data & 0xFF, who);
1400 if (offset == MEMCON1)
1401 WriteLog("TOM: Memory Config 1 written by %s: $%04X\n", whoName[who], data);
1402 if (offset == MEMCON2)
1403 WriteLog("TOM: Memory Config 2 written by %s: $%04X\n", whoName[who], data);
1404 //if (offset == OLP)
1405 // WriteLog("TOM: Object List Pointer written by %s: $%04X\n", whoName[who], data);
1406 //if (offset == OLP + 2)
1407 // WriteLog("TOM: Object List Pointer +2 written by %s: $%04X\n", whoName[who], data);
1408 //if (offset == OBF)
1409 // WriteLog("TOM: Object Processor Flag written by %s: %u\n", whoName[who], data);
1410 if (offset == VMODE)
1411 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));
1412 if (offset == BORD1)
1413 WriteLog("TOM: Border 1 written by %s: $%04X\n", whoName[who], data);
1414 if (offset == BORD2)
1415 WriteLog("TOM: Border 2 written by %s: $%04X\n", whoName[who], data);
1417 WriteLog("TOM: Horizontal Period written by %s: %u (+1*2 = %u)\n", whoName[who], data, (data + 1) * 2);
1419 WriteLog("TOM: Horizontal Blank Begin written by %s: %u\n", whoName[who], data);
1421 WriteLog("TOM: Horizontal Blank End written by %s: %u\n", whoName[who], data);
1423 WriteLog("TOM: Horizontal Sync written by %s: %u\n", whoName[who], data);
1425 WriteLog("TOM: Horizontal Vertical Sync written by %s: %u\n", whoName[who], data);
1427 WriteLog("TOM: Horizontal Display Begin 1 written by %s: %u\n", whoName[who], data);
1429 WriteLog("TOM: Horizontal Display Begin 2 written by %s: %u\n", whoName[who], data);
1431 WriteLog("TOM: Horizontal Display End written by %s: %u\n", whoName[who], data);
1433 WriteLog("TOM: Vertical Period written by %s: %u (%sinterlaced)\n", whoName[who], data, (data & 0x01 ? "non-" : ""));
1435 WriteLog("TOM: Vertical Blank Begin written by %s: %u\n", whoName[who], data);
1437 WriteLog("TOM: Vertical Blank End written by %s: %u\n", whoName[who], data);
1439 WriteLog("TOM: Vertical Sync written by %s: %u\n", whoName[who], data);
1441 WriteLog("TOM: Vertical Display Begin written by %s: %u\n", whoName[who], data);
1443 WriteLog("TOM: Vertical Display End written by %s: %u\n", whoName[who], data);
1445 WriteLog("TOM: Vertical Equalization Begin written by %s: %u\n", whoName[who], data);
1447 WriteLog("TOM: Vertical Equalization End written by %s: %u\n", whoName[who], data);
1449 WriteLog("TOM: Vertical Interrupt written by %s: %u\n", whoName[who], data);
1451 WriteLog("TOM: PIT0 written by %s: %u\n", whoName[who], data);
1453 WriteLog("TOM: PIT1 written by %s: %u\n", whoName[who], data);
1455 WriteLog("TOM: Horizontal Equalization End written by %s: %u\n", whoName[who], data);
1457 // WriteLog("TOM: Background written by %s: %u\n", whoName[who], data);
1458 //if (offset == INT1)
1459 // 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" : ""));
1461 // detect screen resolution changes
1462 //This may go away in the future, if we do the virtualized screen thing...
1463 //This may go away soon!
1464 // TOM Shouldn't be mucking around with this, it's up to the host system to properly
1465 // handle this kind of crap.
1466 // NOTE: This is needed somehow, need to get rid of the dependency on this crap.
1467 #warning "!!! Need to get rid of this dependency !!!"
1469 if ((offset >= 0x28) && (offset <= 0x4F))
1471 uint32 width = TOMGetVideoModeWidth(), height = TOMGetVideoModeHeight();
1473 if ((width != tomWidth) || (height != tomHeight))
1475 tomWidth = width, tomHeight = height;
1477 #warning "!!! TOM: ResizeScreen commented out !!!"
1478 // No need to resize anything, since we're prepared for this...
1479 // if (vjs.renderType == RT_NORMAL)
1480 // ResizeScreen(tomWidth, tomHeight);
1486 int TOMIRQEnabled(int irq)
1488 // This is the correct byte in big endian... D'oh!
1489 // return jaguar_byte_read(0xF000E1) & (1 << irq);
1490 return tomRam8[INT1 + 1/*0xE1*/] & (1 << irq);
1494 // TOM Programmable Interrupt Timer handler
1495 // NOTE: TOM's PIT is only enabled if the prescaler is != 0
1496 // The PIT only generates an interrupt when it counts down to zero, not when loaded!
1498 void TOMPITCallback(void);
1500 void TOMResetPIT(void)
1502 #ifndef NEW_TIMER_SYSTEM
1503 //Probably should *add* this amount to the counter to retain cycle accuracy! !!! FIX !!! [DONE]
1504 //Also, why +1??? 'Cause that's what it says in the JTRM...!
1505 //There is a small problem with this approach: If both the prescaler and the divider are equal
1506 //to $FFFF then the counter won't be large enough to handle it. !!! FIX !!!
1507 if (tom_timer_prescaler)
1508 tom_timer_counter += (1 + tom_timer_prescaler) * (1 + tom_timer_divider);
1509 // WriteLog("tom: reseting timer to 0x%.8x (%i)\n",tom_timer_counter,tom_timer_counter);
1511 // Need to remove previous timer from the queue, if it exists...
1512 RemoveCallback(TOMPITCallback);
1514 if (tomTimerPrescaler)
1516 double usecs = (float)(tomTimerPrescaler + 1) * (float)(tomTimerDivider + 1) * RISC_CYCLE_IN_USEC;
1517 SetCallbackTime(TOMPITCallback, usecs);
1523 // TOM Programmable Interrupt Timer handler
1524 // NOTE: TOM's PIT is only enabled if the prescaler is != 0
1526 //NOTE: This is only used by the old execution code... Safe to remove
1527 // once the timer system is stable.
1528 void TOMExecPIT(uint32 cycles)
1530 if (tomTimerPrescaler)
1532 tomTimerCounter -= cycles;
1534 if (tomTimerCounter <= 0)
1536 TOMSetPendingTimerInt();
1537 GPUSetIRQLine(GPUIRQ_TIMER, ASSERT_LINE); // GPUSetIRQLine does the 'IRQ enabled' checking
1539 if (TOMIRQEnabled(IRQ_TIMER))
1540 m68k_set_irq(2); // Cause a 68000 IPL 2...
1547 void TOMPITCallback(void)
1549 // INT1_RREG |= 0x08; // Set TOM PIT interrupt pending
1550 TOMSetPendingTimerInt();
1551 GPUSetIRQLine(GPUIRQ_TIMER, ASSERT_LINE); // It does the 'IRQ enabled' checking
1553 // if (INT1_WREG & 0x08)
1554 if (TOMIRQEnabled(IRQ_TIMER))
1555 m68k_set_irq(2); // Generate a 68K IPL 2...