4 // Originally by David Raingeard (cal2)
5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Cleanups, endian wrongness amelioration, and extensive fixes by James Hammons
7 // (C) 2010 Underground Software
9 // JLH = James 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: TOM has only a 16K memory space
18 // ------------------------------------------------------------
19 // TOM REGISTERS (Mapped by Aaron Giles)
20 // ------------------------------------------------------------
21 // F00000-F0FFFF R/W xxxxxxxx xxxxxxxx Internal Registers
22 // F00000 R/W -x-xx--- xxxxxxxx MEMCON1 - memory config reg 1
23 // -x------ -------- (CPU32 - is the CPU 32bits?)
24 // ---xx--- -------- (IOSPEED - external I/O clock cycles)
25 // -------- x------- (FASTROM - reduces ROM clock cycles)
26 // -------- -xx----- (DRAMSPEED - sets RAM clock cycles)
27 // -------- ---xx--- (ROMSPEED - sets ROM clock cycles)
28 // -------- -----xx- (ROMWIDTH - sets width of ROM: 8,16,32,64 bits)
29 // -------- -------x (ROMHI - controls ROM mapping)
30 // F00002 R/W --xxxxxx xxxxxxxx MEMCON2 - memory config reg 2
31 // --x----- -------- (HILO - image display bit order)
32 // ---x---- -------- (BIGEND - big endian addressing?)
33 // ----xxxx -------- (REFRATE - DRAM refresh rate)
34 // -------- xx------ (DWIDTH1 - DRAM1 width: 8,16,32,64 bits)
35 // -------- --xx---- (COLS1 - DRAM1 columns: 256,512,1024,2048)
36 // -------- ----xx-- (DWIDTH0 - DRAM0 width: 8,16,32,64 bits)
37 // -------- ------xx (COLS0 - DRAM0 columns: 256,512,1024,2048)
38 // F00004 R/W -----xxx xxxxxxxx HC - horizontal count
39 // -----x-- -------- (which half of the display)
40 // ------xx xxxxxxxx (10-bit counter)
41 // F00006 R/W ----xxxx xxxxxxxx VC - vertical count
42 // ----x--- -------- (which field is being generated)
43 // -----xxx xxxxxxxx (11-bit counter)
44 // F00008 R -----xxx xxxxxxxx LPH - light pen horizontal position
45 // F0000A R -----xxx xxxxxxxx LPV - light pen vertical position
46 // F00010-F00017 R xxxxxxxx xxxxxxxx OB - current object code from the graphics processor
47 // F00020-F00023 W xxxxxxxx xxxxxxxx OLP - start of the object list
48 // F00026 W -------- -------x OBF - object processor flag
49 // F00028 W ----xxxx xxxxxxxx VMODE - video mode
50 // W ----xxx- -------- (PWIDTH1-8 - width of pixel in video clock cycles)
51 // W -------x -------- (VARMOD - enable variable color resolution)
52 // W -------- x------- (BGEN - clear line buffer to BG color)
53 // W -------- -x------ (CSYNC - enable composite sync on VSYNC)
54 // W -------- --x----- (BINC - local border color if INCEN)
55 // W -------- ---x---- (INCEN - encrustation enable)
56 // W -------- ----x--- (GENLOCK - enable genlock)
57 // W -------- -----xx- (MODE - CRY16,RGB24,DIRECT16,RGB16)
58 // W -------- -------x (VIDEN - enables video)
59 // F0002A W xxxxxxxx xxxxxxxx BORD1 - border color (red/green)
60 // F0002C W -------- xxxxxxxx BORD2 - border color (blue)
61 // F0002E W ------xx xxxxxxxx HP - horizontal period
62 // F00030 W -----xxx xxxxxxxx HBB - horizontal blanking begin
63 // F00032 W -----xxx xxxxxxxx HBE - horizontal blanking end
64 // F00034 W -----xxx xxxxxxxx HSYNC - horizontal sync
65 // F00036 W ------xx xxxxxxxx HVS - horizontal vertical sync
66 // F00038 W -----xxx xxxxxxxx HDB1 - horizontal display begin 1
67 // F0003A W -----xxx xxxxxxxx HDB2 - horizontal display begin 2
68 // F0003C W -----xxx xxxxxxxx HDE - horizontal display end
69 // F0003E W -----xxx xxxxxxxx VP - vertical period
70 // F00040 W -----xxx xxxxxxxx VBB - vertical blanking begin
71 // F00042 W -----xxx xxxxxxxx VBE - vertical blanking end
72 // F00044 W -----xxx xxxxxxxx VS - vertical sync
73 // F00046 W -----xxx xxxxxxxx VDB - vertical display begin
74 // F00048 W -----xxx xxxxxxxx VDE - vertical display end
75 // F0004A W -----xxx xxxxxxxx VEB - vertical equalization begin
76 // F0004C W -----xxx xxxxxxxx VEE - vertical equalization end
77 // F0004E W -----xxx xxxxxxxx VI - vertical interrupt
78 // F00050 W xxxxxxxx xxxxxxxx PIT0 - programmable interrupt timer 0
79 // F00052 W xxxxxxxx xxxxxxxx PIT1 - programmable interrupt timer 1
80 // F00054 W ------xx xxxxxxxx HEQ - horizontal equalization end
81 // F00058 W xxxxxxxx xxxxxxxx BG - background color
82 // F000E0 R/W ---xxxxx ---xxxxx INT1 - CPU interrupt control register
83 // ---x---- -------- (C_JERCLR - clear pending Jerry ints)
84 // ----x--- -------- (C_PITCLR - clear pending PIT ints)
85 // -----x-- -------- (C_OPCLR - clear pending object processor ints)
86 // ------x- -------- (C_GPUCLR - clear pending graphics processor ints)
87 // -------x -------- (C_VIDCLR - clear pending video timebase ints)
88 // -------- ---x---- (C_JERENA - enable Jerry ints)
89 // -------- ----x--- (C_PITENA - enable PIT ints)
90 // -------- -----x-- (C_OPENA - enable object processor ints)
91 // -------- ------x- (C_GPUENA - enable graphics processor ints)
92 // -------- -------x (C_VIDENA - enable video timebase ints)
93 // F000E2 W -------- -------- INT2 - CPU interrupt resume register
94 // F00400-F005FF R/W xxxxxxxx xxxxxxxx CLUT - color lookup table A
95 // F00600-F007FF R/W xxxxxxxx xxxxxxxx CLUT - color lookup table B
96 // F00800-F00D9F R/W xxxxxxxx xxxxxxxx LBUF - line buffer A
97 // F01000-F0159F R/W xxxxxxxx xxxxxxxx LBUF - line buffer B
98 // F01800-F01D9F R/W xxxxxxxx xxxxxxxx LBUF - line buffer currently selected
99 // ------------------------------------------------------------
100 // F02000-F021FF R/W xxxxxxxx xxxxxxxx GPU control registers
101 // F02100 R/W xxxxxxxx xxxxxxxx G_FLAGS - GPU flags register
102 // R/W x------- -------- (DMAEN - DMA enable)
103 // R/W -x------ -------- (REGPAGE - register page)
104 // W --x----- -------- (G_BLITCLR - clear blitter interrupt)
105 // W ---x---- -------- (G_OPCLR - clear object processor int)
106 // W ----x--- -------- (G_PITCLR - clear PIT interrupt)
107 // W -----x-- -------- (G_JERCLR - clear Jerry interrupt)
108 // W ------x- -------- (G_CPUCLR - clear CPU interrupt)
109 // R/W -------x -------- (G_BLITENA - enable blitter interrupt)
110 // R/W -------- x------- (G_OPENA - enable object processor int)
111 // R/W -------- -x------ (G_PITENA - enable PIT interrupt)
112 // R/W -------- --x----- (G_JERENA - enable Jerry interrupt)
113 // R/W -------- ---x---- (G_CPUENA - enable CPU interrupt)
114 // R/W -------- ----x--- (IMASK - interrupt mask)
115 // R/W -------- -----x-- (NEGA_FLAG - ALU negative)
116 // R/W -------- ------x- (CARRY_FLAG - ALU carry)
117 // R/W -------- -------x (ZERO_FLAG - ALU zero)
118 // F02104 W -------- ----xxxx G_MTXC - matrix control register
119 // W -------- ----x--- (MATCOL - column/row major)
120 // W -------- -----xxx (MATRIX3-15 - matrix width)
121 // F02108 W ----xxxx xxxxxx-- G_MTXA - matrix address register
122 // F0210C W -------- -----xxx G_END - data organization register
123 // W -------- -----x-- (BIG_INST - big endian instruction fetch)
124 // W -------- ------x- (BIG_PIX - big endian pixels)
125 // W -------- -------x (BIG_IO - big endian I/O)
126 // F02110 R/W xxxxxxxx xxxxxxxx G_PC - GPU program counter
127 // F02114 R/W xxxxxxxx xx-xxxxx G_CTRL - GPU control/status register
128 // R xxxx---- -------- (VERSION - GPU version code)
129 // R/W ----x--- -------- (BUS_HOG - hog the bus!)
130 // R/W -----x-- -------- (G_BLITLAT - blitter interrupt latch)
131 // R/W ------x- -------- (G_OPLAT - object processor int latch)
132 // R/W -------x -------- (G_PITLAT - PIT interrupt latch)
133 // R/W -------- x------- (G_JERLAT - Jerry interrupt latch)
134 // R/W -------- -x------ (G_CPULAT - CPU interrupt latch)
135 // R/W -------- ---x---- (SINGLE_GO - single step one instruction)
136 // R/W -------- ----x--- (SINGLE_STEP - single step mode)
137 // R/W -------- -----x-- (FORCEINT0 - cause interrupt 0 on GPU)
138 // R/W -------- ------x- (CPUINT - send GPU interrupt to CPU)
139 // R/W -------- -------x (GPUGO - enable GPU execution)
140 // F02118-F0211B R/W xxxxxxxx xxxxxxxx G_HIDATA - high data register
141 // F0211C-F0211F R xxxxxxxx xxxxxxxx G_REMAIN - divide unit remainder
142 // F0211C W -------- -------x G_DIVCTRL - divide unit control
143 // W -------- -------x (DIV_OFFSET - 1=16.16 divide, 0=32-bit divide)
144 // ------------------------------------------------------------
146 // ------------------------------------------------------------
147 // F02200-F022FF R/W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx Blitter registers
148 // F02200 W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx A1_BASE - A1 base register
149 // F02204 W -------- ---xxxxx -xxxxxxx xxxxx-xx A1_FLAGS - A1 flags register
150 // W -------- ---x---- -------- -------- (YSIGNSUB - invert sign of Y delta)
151 // W -------- ----x--- -------- -------- (XSIGNSUB - invert sign of X delta)
152 // W -------- -----x-- -------- -------- (Y add control)
153 // W -------- ------xx -------- -------- (X add control)
154 // W -------- -------- -xxxxxx- -------- (width in 6-bit floating point)
155 // W -------- -------- -------x xx------ (ZOFFS1-6 - Z data offset)
156 // W -------- -------- -------- --xxx--- (PIXEL - pixel size)
157 // W -------- -------- -------- ------xx (PITCH1-4 - data phrase pitch)
158 // F02208 W -xxxxxxx xxxxxxxx -xxxxxxx xxxxxxxx A1_CLIP - A1 clipping size
159 // W -xxxxxxx xxxxxxxx -------- -------- (height)
160 // W -------- -------- -xxxxxxx xxxxxxxx (width)
161 // F0220C R/W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx A1_PIXEL - A1 pixel pointer
162 // R/W xxxxxxxx xxxxxxxx -------- -------- (Y pixel value)
163 // R/W -------- -------- xxxxxxxx xxxxxxxx (X pixel value)
164 // F02210 W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx A1_STEP - A1 step value
165 // W xxxxxxxx xxxxxxxx -------- -------- (Y step value)
166 // W -------- -------- xxxxxxxx xxxxxxxx (X step value)
167 // F02214 W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx A1_FSTEP - A1 step fraction value
168 // W xxxxxxxx xxxxxxxx -------- -------- (Y step fraction value)
169 // W -------- -------- xxxxxxxx xxxxxxxx (X step fraction value)
170 // F02218 R/W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx A1_FPIXEL - A1 pixel pointer fraction
171 // R/W xxxxxxxx xxxxxxxx -------- -------- (Y pixel fraction value)
172 // R/W -------- -------- xxxxxxxx xxxxxxxx (X pixel fraction value)
173 // F0221C W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx A1_INC - A1 increment
174 // W xxxxxxxx xxxxxxxx -------- -------- (Y increment)
175 // W -------- -------- xxxxxxxx xxxxxxxx (X increment)
176 // F02220 W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx A1_FINC - A1 increment fraction
177 // W xxxxxxxx xxxxxxxx -------- -------- (Y increment fraction)
178 // W -------- -------- xxxxxxxx xxxxxxxx (X increment fraction)
179 // F02224 W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx A2_BASE - A2 base register
180 // F02228 W -------- ---xxxxx -xxxxxxx xxxxx-xx A2_FLAGS - A2 flags register
181 // W -------- ---x---- -------- -------- (YSIGNSUB - invert sign of Y delta)
182 // W -------- ----x--- -------- -------- (XSIGNSUB - invert sign of X delta)
183 // W -------- -----x-- -------- -------- (Y add control)
184 // W -------- ------xx -------- -------- (X add control)
185 // W -------- -------- -xxxxxx- -------- (width in 6-bit floating point)
186 // W -------- -------- -------x xx------ (ZOFFS1-6 - Z data offset)
187 // W -------- -------- -------- --xxx--- (PIXEL - pixel size)
188 // W -------- -------- -------- ------xx (PITCH1-4 - data phrase pitch)
189 // F0222C W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx A2_MASK - A2 window mask
190 // F02230 R/W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx A2_PIXEL - A2 pixel pointer
191 // R/W xxxxxxxx xxxxxxxx -------- -------- (Y pixel value)
192 // R/W -------- -------- xxxxxxxx xxxxxxxx (X pixel value)
193 // F02234 W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx A2_STEP - A2 step value
194 // W xxxxxxxx xxxxxxxx -------- -------- (Y step value)
195 // W -------- -------- xxxxxxxx xxxxxxxx (X step value)
196 // F02238 W -xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx B_CMD - command register
197 // W -x------ -------- -------- -------- (SRCSHADE - modify source intensity)
198 // W --x----- -------- -------- -------- (BUSHI - hi priority bus)
199 // W ---x---- -------- -------- -------- (BKGWREN - writeback destination)
200 // W ----x--- -------- -------- -------- (DCOMPEN - write inhibit from data comparator)
201 // W -----x-- -------- -------- -------- (BCOMPEN - write inhibit from bit coparator)
202 // W ------x- -------- -------- -------- (CMPDST - compare dest instead of src)
203 // W -------x xxx----- -------- -------- (logical operation)
204 // W -------- ---xxx-- -------- -------- (ZMODE - Z comparator mode)
205 // W -------- ------x- -------- -------- (ADDDSEL - select sum of src & dst)
206 // W -------- -------x -------- -------- (PATDSEL - select pattern data)
207 // W -------- -------- x------- -------- (TOPNEN - enable carry into top intensity nibble)
208 // W -------- -------- -x------ -------- (TOPBEN - enable carry into top intensity byte)
209 // W -------- -------- --x----- -------- (ZBUFF - enable Z updates in inner loop)
210 // W -------- -------- ---x---- -------- (GOURD - enable gouraud shading in inner loop)
211 // W -------- -------- ----x--- -------- (DSTA2 - reverses A2/A1 roles)
212 // W -------- -------- -----x-- -------- (UPDA2 - add A2 step to A2 in outer loop)
213 // W -------- -------- ------x- -------- (UPDA1 - add A1 step to A1 in outer loop)
214 // W -------- -------- -------x -------- (UPDA1F - add A1 fraction step to A1 in outer loop)
215 // W -------- -------- -------- x------- (diagnostic use)
216 // W -------- -------- -------- -x------ (CLIP_A1 - clip A1 to window)
217 // W -------- -------- -------- --x----- (DSTWRZ - enable dest Z write in inner loop)
218 // W -------- -------- -------- ---x---- (DSTENZ - enable dest Z read in inner loop)
219 // W -------- -------- -------- ----x--- (DSTEN - enables dest data read in inner loop)
220 // W -------- -------- -------- -----x-- (SRCENX - enable extra src read at start of inner)
221 // W -------- -------- -------- ------x- (SRCENZ - enables source Z read in inner loop)
222 // W -------- -------- -------- -------x (SRCEN - enables source data read in inner loop)
223 // F02238 R xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx B_CMD - status register
224 // R xxxxxxxx xxxxxxxx -------- -------- (inner count)
225 // R -------- -------- xxxxxxxx xxxxxx-- (diagnostics)
226 // R -------- -------- -------- ------x- (STOPPED - when stopped in collision detect)
227 // R -------- -------- -------- -------x (IDLE - when idle)
228 // F0223C W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx B_COUNT - counters register
229 // W xxxxxxxx xxxxxxxx -------- -------- (outer loop count)
230 // W -------- -------- xxxxxxxx xxxxxxxx (inner loop count)
231 // F02240-F02247 W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx B_SRCD - source data register
232 // F02248-F0224F W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx B_DSTD - destination data register
233 // F02250-F02257 W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx B_DSTZ - destination Z register
234 // F02258-F0225F W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx B_SRCZ1 - source Z register 1
235 // F02260-F02267 W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx B_SRCZ2 - source Z register 2
236 // F02268-F0226F W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx B_PATD - pattern data register
237 // F02270 W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx B_IINC - intensity increment
238 // F02274 W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx B_ZINC - Z increment
239 // F02278 W -------- -------- -------- -----xxx B_STOP - collision control
240 // W -------- -------- -------- -----x-- (STOPEN - enable blitter collision stops)
241 // W -------- -------- -------- ------x- (ABORT - abort after stop)
242 // W -------- -------- -------- -------x (RESUME - resume after stop)
243 // F0227C W -------- xxxxxxxx xxxxxxxx xxxxxxxx B_I3 - intensity 3
244 // F02280 W -------- xxxxxxxx xxxxxxxx xxxxxxxx B_I2 - intensity 2
245 // F02284 W -------- xxxxxxxx xxxxxxxx xxxxxxxx B_I1 - intensity 1
246 // F02288 W -------- xxxxxxxx xxxxxxxx xxxxxxxx B_I0 - intensity 0
247 // F0228C W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx B_Z3 - Z3
248 // F02290 W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx B_Z2 - Z2
249 // F02294 W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx B_Z1 - Z1
250 // F02298 W xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx B_Z0 - Z0
251 // ------------------------------------------------------------
255 #include <string.h> // For memset()
256 #include <stdlib.h> // For rand()
263 #include "m68000/m68kinterface.h"
264 //#include "memory.h"
266 #include "settings.h"
268 #define NEW_TIMER_SYSTEM
270 // TOM registers (offset from $F00000)
276 #define OLP 0x20 // Object list pointer
277 #define OBF 0x26 // Object processor flag
279 #define MODE 0x0006 // Line buffer to video generator mode
280 #define BGEN 0x0080 // Background enable (CRY & RGB16 only)
281 #define VARMOD 0x0100 // Mixed CRY/RGB16 mode (only works in MODE 0!)
282 #define PWIDTH 0x0E00 // Pixel width in video clock cycles (value written + 1)
283 #define BORD1 0x2A // Border green/red values (8 BPP)
284 #define BORD2 0x2C // Border blue value (8 BPP)
285 #define HP 0x2E // Values range from 1 - 1024 (value written + 1)
286 #define HBB 0x30 // Horizontal blank begin
288 #define HS 0x34 // Horizontal sync
289 #define HVS 0x36 // Horizontal vertical sync
290 #define HDB1 0x38 // Horizontal display begin 1
293 #define VP 0x3E // Value ranges from 1 - 2048 (value written + 1)
294 #define VBB 0x40 // Vertical blank begin
296 #define VS 0x44 // Vertical sync
297 #define VDB 0x46 // Vertical display begin
299 #define VEB 0x4A // Vertical equalization begin
300 #define VEE 0x4C // Vertical equalization end
301 #define VI 0x4E // Vertical interrupt
304 #define HEQ 0x54 // Horizontal equalization end
305 #define BG 0x58 // Background color
309 // Arbitrary video cutoff values (i.e., first/last visible spots on a TV, in HC
311 // Also note that VC is in *half* lines, i.e. divide by 2 to get the scanline
312 /*#define LEFT_VISIBLE_HC 208
313 #define RIGHT_VISIBLE_HC 1528//*/
314 // These were right for Rayman, but that one is offset on a real TV too.
315 //#define LEFT_VISIBLE_HC 208
316 //#define RIGHT_VISIBLE_HC 1488
317 // This is more like a real TV display...
318 //#define LEFT_VISIBLE_HC (208 - 32)
319 //#define RIGHT_VISIBLE_HC (1488 - 32)
320 // Split the difference? (Seems to be OK for the most part...)
322 // (-10 +10)*4 is for opening up the display by 16 pixels (may go to 20). Need to change VIRTUAL_SCREEN_WIDTH to match this as well (went from 320 to 340; this is 4 HCs per one of those pixels).
323 //NB: Went back to 330. May shrink more. :-)
324 //#define LEFT_VISIBLE_HC (208 - 16 - (8 * 4))
325 //#define LEFT_VISIBLE_HC (208 - 16 - (3 * 4))
326 #define LEFT_VISIBLE_HC (208 - 16 - (1 * 4))
327 //#define RIGHT_VISIBLE_HC (1488 - 16 + (10 * 4))
328 #define RIGHT_VISIBLE_HC (LEFT_VISIBLE_HC + (VIRTUAL_SCREEN_WIDTH * 4))
329 //#define TOP_VISIBLE_VC 25
330 //#define BOTTOM_VISIBLE_VC 503
331 #define TOP_VISIBLE_VC 31
332 #define BOTTOM_VISIBLE_VC 511
334 //Are these PAL horizontals correct?
335 //They seem to be for the most part, but there are some games that seem to be
336 //shifted over to the right from this "window".
337 //#define LEFT_VISIBLE_HC_PAL (208 - 16 - (4 * 4))
338 //#define LEFT_VISIBLE_HC_PAL (208 - 16 - (-1 * 4))
339 #define LEFT_VISIBLE_HC_PAL (208 - 16 - (-3 * 4))
340 //#define RIGHT_VISIBLE_HC_PAL (1488 - 16 + (10 * 4))
341 #define RIGHT_VISIBLE_HC_PAL (LEFT_VISIBLE_HC_PAL + (VIRTUAL_SCREEN_WIDTH * 4))
342 #define TOP_VISIBLE_VC_PAL 67
343 #define BOTTOM_VISIBLE_VC_PAL 579
345 //This can be defined in the makefile as well...
346 //(It's easier to do it here, though...)
349 uint8_t tomRam8[0x4000];
350 uint32_t tomWidth, tomHeight;
351 uint32_t tomTimerPrescaler;
352 uint32_t tomTimerDivider;
353 int32_t tomTimerCounter;
354 uint16_t tom_jerry_int_pending, tom_timer_int_pending, tom_object_int_pending,
355 tom_gpu_int_pending, tom_video_int_pending;
357 // These are set by the "user" of the Jaguar core lib, since these are
358 // OS/system dependent.
359 uint32_t * screenBuffer;
360 uint32_t screenPitch;
362 static const char * videoMode_to_str[8] =
363 { "16 BPP CRY", "24 BPP RGB", "16 BPP DIRECT", "16 BPP RGB",
364 "Mixed mode", "24 BPP RGB", "16 BPP DIRECT", "16 BPP RGB" };
366 typedef void (render_xxx_scanline_fn)(uint32_t *);
368 // Private function prototypes
370 void tom_render_16bpp_cry_scanline(uint32_t * backbuffer);
371 void tom_render_24bpp_scanline(uint32_t * backbuffer);
372 void tom_render_16bpp_direct_scanline(uint32_t * backbuffer);
373 void tom_render_16bpp_rgb_scanline(uint32_t * backbuffer);
374 void tom_render_16bpp_cry_rgb_mix_scanline(uint32_t * backbuffer);
376 //render_xxx_scanline_fn * scanline_render_normal[] =
377 render_xxx_scanline_fn * scanline_render[] =
379 tom_render_16bpp_cry_scanline,
380 tom_render_24bpp_scanline,
381 tom_render_16bpp_direct_scanline,
382 tom_render_16bpp_rgb_scanline,
383 tom_render_16bpp_cry_rgb_mix_scanline,
384 tom_render_24bpp_scanline,
385 tom_render_16bpp_direct_scanline,
386 tom_render_16bpp_rgb_scanline
389 // Screen info for various games [PAL]...
392 TOM: Horizontal Period written by M68K: 850 (+1*2 = 1702)
393 TOM: Horizontal Blank Begin written by M68K: 1711
394 TOM: Horizontal Blank End written by M68K: 158
395 TOM: Horizontal Display End written by M68K: 1696
396 TOM: Horizontal Display Begin 1 written by M68K: 166
397 TOM: Vertical Period written by M68K: 623 (non-interlaced)
398 TOM: Vertical Blank End written by M68K: 34
399 TOM: Vertical Display Begin written by M68K: 46
400 TOM: Vertical Display End written by M68K: 526
401 TOM: Vertical Blank Begin written by M68K: 600
402 TOM: Vertical Sync written by M68K: 618
403 TOM: Horizontal Display End written by M68K: 1665
404 TOM: Horizontal Display Begin 1 written by M68K: 203
405 TOM: Vertical Display Begin written by M68K: 38
406 TOM: Vertical Display End written by M68K: 518
407 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 151)
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 Horizontal range: 157 - 1713 (width: 1557 / 4 = 389.25, / 5 = 315.4)
415 TOM: Horizontal Period written by M68K: 845 (+1*2 = 1692)
416 TOM: Horizontal Blank Begin written by M68K: 1700
417 TOM: Horizontal Blank End written by M68K: 122
418 TOM: Horizontal Display End written by M68K: 1600
419 TOM: Horizontal Display Begin 1 written by M68K: 268
420 TOM: Vertical Period written by M68K: 523 (non-interlaced)
421 TOM: Vertical Blank End written by M68K: 40
422 TOM: Vertical Display Begin written by M68K: 44
423 TOM: Vertical Display End written by M68K: 492
424 TOM: Vertical Blank Begin written by M68K: 532
425 TOM: Vertical Sync written by M68K: 513
426 TOM: Video Mode written by M68K: 04C7. PWIDTH = 3, MODE = 16 BPP RGB, flags: BGEN (VC = 461)
429 TOM: Horizontal Display End written by M68K: 1713
430 TOM: Horizontal Display Begin 1 written by M68K: 157
431 TOM: Vertical Display Begin written by M68K: 35
432 TOM: Vertical Display End written by M68K: 2047
433 TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 89)
434 TOM: Horizontal Display Begin 1 written by M68K: 208
435 TOM: Horizontal Display End written by M68K: 1662
436 TOM: Vertical Display Begin written by M68K: 100
437 TOM: Vertical Display End written by M68K: 2047
438 TOM: Video Mode written by M68K: 07C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN VARMOD (VC = 205)
439 Horizontal range: 208 - 1662 (width: 1455 / 4 = 363.5)
442 TOM: Vertical Display Begin written by M68K: 96
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 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 378)
447 TOM: Vertical Display Begin written by M68K: 44
448 TOM: Vertical Display End written by M68K: 2047
449 TOM: Horizontal Display Begin 1 written by M68K: 239
450 TOM: Horizontal Display End written by M68K: 1692
451 TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 559)
452 TOM: Vertical Display Begin written by M68K: 84
453 TOM: Vertical Display End written by M68K: 2047
454 TOM: Horizontal Display Begin 1 written by M68K: 239
455 TOM: Horizontal Display End written by M68K: 1692
456 TOM: Vertical Display Begin written by M68K: 44
457 TOM: Vertical Display End written by M68K: 2047
458 TOM: Horizontal Display Begin 1 written by M68K: 239
459 TOM: Horizontal Display End written by M68K: 1692
460 Horizontal range: 239 - 1692 (width: 1454 / 4 = 363.5)
464 // Screen info for various games [NTSC]...
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 M68K: 0EC1. PWIDTH = 8, MODE = 16 BPP CRY, flags: BGEN (VC = 5)
472 Also does PWIDTH = 4...
473 Vertical resolution: 238 lines
476 TOM: Horizontal Display End written by M68K: 1727
477 TOM: Horizontal Display Begin 1 written by M68K: 123
478 TOM: Vertical Display Begin written by M68K: 25
479 TOM: Vertical Display End written by M68K: 2047
480 TOM: Vertical Interrupt written by M68K: 507
481 TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 92)
482 TOM: Horizontal Display Begin 1 written by M68K: 208
483 TOM: Horizontal Display End written by M68K: 1670
484 Display starts at 31, then 52!
485 Vertical resolution: 238 lines
488 TOM: Horizontal Display End written by M68K: 1727
489 TOM: Horizontal Display Begin 1 written by M68K: 123
490 TOM: Vertical Display Begin written by M68K: 25
491 TOM: Vertical Display End written by M68K: 2047
492 TOM: Video Mode written by GPU: 08C7. PWIDTH = 5, MODE = 16 BPP RGB, flags: BGEN (VC = 4)
493 TOM: Video Mode written by GPU: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 508)
494 Display starts at 31 (PWIDTH = 4), 24 (PWIDTH = 5)
497 TOM: Vertical Interrupt written by M68K: 2047
498 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 0)
499 TOM: Horizontal Display End written by M68K: 1727
500 TOM: Horizontal Display Begin 1 written by M68K: 123
501 TOM: Vertical Display Begin written by M68K: 25
502 TOM: Vertical Display End written by M68K: 2047
503 TOM: Vertical Interrupt written by M68K: 507
504 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 369)
505 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 510)
506 TOM: Video Mode written by M68K: 06C3. PWIDTH = 4, MODE = 24 BPP RGB, flags: BGEN (VC = 510)
508 Vertical resolution: 238 lines
509 [Seems to be a problem between the horizontal positioning of the 16-bit CRY & 24-bit RGB]
512 TOM: Horizontal Period written by M68K: 844 (+1*2 = 1690)
513 TOM: Horizontal Blank Begin written by M68K: 1713
514 TOM: Horizontal Blank End written by M68K: 125
515 TOM: Horizontal Display End written by M68K: 1696
516 TOM: Horizontal Display Begin 1 written by M68K: 166
517 TOM: Vertical Period written by M68K: 523 (non-interlaced)
518 TOM: Vertical Blank End written by M68K: 24
519 TOM: Vertical Display Begin written by M68K: 46
520 TOM: Vertical Display End written by M68K: 496
521 TOM: Vertical Blank Begin written by M68K: 500
522 TOM: Vertical Sync written by M68K: 517
523 TOM: Vertical Interrupt written by M68K: 497
524 TOM: Video Mode written by M68K: 04C1. PWIDTH = 3, MODE = 16 BPP CRY, flags: BGEN (VC = 270)
528 TOM: Horizontal Display End written by M68K: 1727
529 TOM: Horizontal Display Begin 1 written by M68K: 123
530 TOM: Vertical Display Begin written by M68K: 25
531 TOM: Vertical Display End written by M68K: 2047
532 TOM: Vertical Interrupt written by M68K: 507
533 TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 9)
536 TOM: Horizontal Display End written by M68K: 1823
537 TOM: Horizontal Display Begin 1 written by M68K: 45
538 TOM: Vertical Display Begin written by M68K: 40
539 TOM: Vertical Display End written by M68K: 2047
540 TOM: Vertical Interrupt written by M68K: 491
541 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 398)
542 Display starts at 11 (123 - 45 = 78, 78 / 4 = 19 pixels to skip)
543 Width is 417, so maybe width of 379 would be good (starting at 123, ending at 1639)
544 Vertical resolution: 238 lines
547 TOM: Horizontal Display End written by M68K: 1727
548 TOM: Horizontal Display Begin 1 written by M68K: 188
549 TOM: Vertical Display Begin written by M68K: 1
550 TOM: Vertical Display End written by M68K: 2047
551 TOM: Vertical Interrupt written by M68K: 483
552 TOM: Video Mode written by M68K: 08C7. PWIDTH = 5, MODE = 16 BPP RGB, flags: BGEN (VC = 99)
553 Width would be 303 with above scheme, but border width would be 13 pixels
556 Vertical resolution: 238 lines
559 // 16-bit color lookup tables
560 uint32_t RGB16ToRGB32[0x10000];
561 uint32_t CRY16ToRGB32[0x10000];
562 uint32_t MIX16ToRGB32[0x10000];
565 #warning "This is not endian-safe. !!! FIX !!!"
566 void TOMFillLookupTables(void)
568 // NOTE: Jaguar 16-bit (non-CRY) color is RBG 556 like so:
569 // RRRR RBBB BBGG GGGG
570 for(uint32_t i=0; i<0x10000; i++)
571 RGB16ToRGB32[i] = 0x000000FF
572 | ((i & 0xF800) << 16) // Red
573 | ((i & 0x003F) << 18) // Green
574 | ((i & 0x07C0) << 5); // Blue
576 for(uint32_t i=0; i<0x10000; i++)
578 uint32_t cyan = (i & 0xF000) >> 12,
579 red = (i & 0x0F00) >> 8,
580 intensity = (i & 0x00FF);
582 uint32_t r = (((uint32_t)redcv[cyan][red]) * intensity) >> 8,
583 g = (((uint32_t)greencv[cyan][red]) * intensity) >> 8,
584 b = (((uint32_t)bluecv[cyan][red]) * intensity) >> 8;
586 CRY16ToRGB32[i] = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
587 MIX16ToRGB32[i] = (i & 0x01 ? RGB16ToRGB32[i] : CRY16ToRGB32[i]);
592 void TOMSetPendingJERRYInt(void)
594 tom_jerry_int_pending = 1;
598 void TOMSetPendingTimerInt(void)
600 tom_timer_int_pending = 1;
604 void TOMSetPendingObjectInt(void)
606 tom_object_int_pending = 1;
610 void TOMSetPendingGPUInt(void)
612 tom_gpu_int_pending = 1;
616 void TOMSetPendingVideoInt(void)
618 tom_video_int_pending = 1;
622 uint8_t * TOMGetRamPointer(void)
628 uint8_t TOMGetVideoMode(void)
630 uint16_t vmode = GET16(tomRam8, VMODE);
631 return ((vmode & VARMOD) >> 6) | ((vmode & MODE) >> 1);
635 //Used in only one place (and for debug purposes): OBJECTP.CPP
636 #warning "Used in only one place (and for debug purposes): OBJECTP.CPP !!! FIX !!!"
637 uint16_t TOMGetVDB(void)
639 return GET16(tomRam8, VDB);
643 uint16_t TOMGetHC(void)
645 return GET16(tomRam8, HC);
649 uint16_t TOMGetVP(void)
651 return GET16(tomRam8, VP);
655 uint16_t TOMGetMEMCON1(void)
657 return GET16(tomRam8, MEMCON1);
663 // 16 BPP CRY/RGB mixed mode rendering
665 void tom_render_16bpp_cry_rgb_mix_scanline(uint32_t * backbuffer)
667 //CHANGED TO 32BPP RENDERING
668 uint16_t width = tomWidth;
669 uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
671 //New stuff--restrict our drawing...
672 uint8_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
673 //NOTE: May have to check HDB2 as well!
674 // Get start position in HC ticks
675 int16_t startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL);
680 // This is x2 because current_line_buffer is uint8_t & we're in a 16bpp mode
681 current_line_buffer += 2 * -startPos;
683 //This case doesn't properly handle the "start on the right side of virtual screen" case
684 //Dunno why--looks Ok...
685 //What *is* for sure wrong is that it doesn't copy the linebuffer's BG pixels... [FIXED NOW]
686 //This should likely be 4 instead of 2 (?--not sure)
687 // Actually, there should be NO multiplier, as startPos is expressed in PIXELS
688 // and so is the backbuffer.
691 uint8_t g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
692 uint32_t pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
694 for(int16_t i=0; i<startPos; i++)
695 *backbuffer++ = pixel;
700 backbuffer += 2 * startPos, width -= startPos;
705 uint16_t color = (*current_line_buffer++) << 8;
706 color |= *current_line_buffer++;
707 *backbuffer++ = MIX16ToRGB32[color];
714 // 16 BPP CRY mode rendering
716 void tom_render_16bpp_cry_scanline(uint32_t * backbuffer)
718 //CHANGED TO 32BPP RENDERING
719 uint16_t width = tomWidth;
720 uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
722 //New stuff--restrict our drawing...
723 uint8_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
724 //NOTE: May have to check HDB2 as well!
725 int16_t startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL);// Get start position in HC ticks
729 current_line_buffer += 2 * -startPos;
733 uint8_t g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
734 uint32_t pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
736 for(int16_t i=0; i<startPos; i++)
737 *backbuffer++ = pixel;
742 //This should likely be 4 instead of 2 (?--not sure)
743 backbuffer += 2 * startPos, width -= startPos;
748 uint16_t color = (*current_line_buffer++) << 8;
749 color |= *current_line_buffer++;
750 *backbuffer++ = CRY16ToRGB32[color];
757 // 24 BPP mode rendering
759 void tom_render_24bpp_scanline(uint32_t * backbuffer)
761 //CHANGED TO 32BPP RENDERING
762 uint16_t width = tomWidth;
763 uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
765 //New stuff--restrict our drawing...
766 uint8_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
767 //NOTE: May have to check HDB2 as well!
768 int16_t startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL); // Get start position in HC ticks
772 current_line_buffer += 4 * -startPos;
776 uint8_t g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
777 uint32_t pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
779 for(int16_t i=0; i<startPos; i++)
780 *backbuffer++ = pixel;
785 //This should likely be 4 instead of 2 (?--not sure)
786 backbuffer += 2 * startPos, width -= startPos;
791 uint32_t g = *current_line_buffer++;
792 uint32_t r = *current_line_buffer++;
793 current_line_buffer++;
794 uint32_t b = *current_line_buffer++;
795 *backbuffer++ = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
801 // Seems to me that this is NOT a valid mode--the JTRM seems to imply that you
802 // would need extra hardware outside of the Jaguar console to support this!
804 // 16 BPP direct mode rendering
806 void tom_render_16bpp_direct_scanline(uint32_t * backbuffer)
808 uint16_t width = tomWidth;
809 uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
813 uint16_t color = (*current_line_buffer++) << 8;
814 color |= *current_line_buffer++;
815 *backbuffer++ = color >> 1;
822 // 16 BPP RGB mode rendering
824 void tom_render_16bpp_rgb_scanline(uint32_t * backbuffer)
826 //CHANGED TO 32BPP RENDERING
827 // 16 BPP RGB: 0-5 green, 6-10 blue, 11-15 red
829 uint16_t width = tomWidth;
830 uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
832 //New stuff--restrict our drawing...
833 uint8_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
834 //NOTE: May have to check HDB2 as well!
835 int16_t startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL); // Get start position in HC ticks
839 current_line_buffer += 2 * -startPos;
843 uint8_t g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
844 uint32_t pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
846 for(int16_t i=0; i<startPos; i++)
847 *backbuffer++ = pixel;
852 //This should likely be 4 instead of 2 (?--not sure)
853 backbuffer += 2 * startPos, width -= startPos;
858 uint32_t color = (*current_line_buffer++) << 8;
859 color |= *current_line_buffer++;
860 *backbuffer++ = RGB16ToRGB32[color];
867 // Process a single halfline
869 void TOMExecHalfline(uint16_t halfline, bool render)
871 uint16_t field2 = halfline & 0x0800;
873 bool inActiveDisplayArea = true;
875 // Execute OP only on even halflines (skip higher resolutions for now...)
879 //Hm, it seems that the OP needs to execute from zero, so let's try it:
880 // And it works! But need to do some optimizations in the OP to keep it from
881 // attempting to do a scanline render in the non-display area... [DONE]
882 //this seems to cause a regression in certain games, like rayman
883 //which means I have to dig thru the asic nets to see what's wrong...
885 No, the OP doesn't start until VDB, that much is certain. The thing is, VDB is
886 the HALF line that the OP starts on--which means that it needs to start at
889 Hrm, doesn't seem to be enough, though it should be... still sticks for 20
892 What triggers this is writing $FFFF to VDE. This causes the OP start signal in VID to latch on, which in effect sets VDB to zero. So that much is correct. But
893 the thing with Rayman is that it shouldn't cause the graphical glitches seen
894 there, so still have to investigate what's going on there. By all rights, it
895 shouldn't glitch because:
897 00006C00: 0000000D 82008F73 (BRANCH) YPOS=494, CC=">", link=$00006C10
898 00006C08: 000003FF 00008173 (BRANCH) YPOS=46, CC=">", link=$001FF800
899 00006C10: 00000000 0000000C (STOP)
900 001FF800: 12FC2BFF 02380000 (BITMAP)
903 Even if the OP is running all the time, the link should tell it to stop at the
904 right place (which it seems to do). But we still get glitchy screen.
906 Seems the glitchy screen went away... Maybe the GPU alignment fixes fixed it???
907 Just need to add the proper checking here then.
909 Some numbers, courtesy of the Jaguar BIOS:
911 VP, 523 // Vertical Period (1-based; in this case VP = 524)
912 VBE, 24 // Vertical Blank End
913 VDB, 38 // Vertical Display Begin
914 VDE, 518 // Vertical Display End
915 VBB, 500 // Vertical Blank Begin
916 VS, 517 // Vertical Sync
919 VP, 623 // Vertical Period (1-based; in this case VP = 624)
920 VBE, 34 // Vertical Blank End
921 VDB, 38 // Vertical Display Begin
922 VDE, 518 // Vertical Display End
923 VBB, 600 // Vertical Blank Begin
924 VS, 618 // Vertical Sync
926 Numbers for KM, NTSC:
927 KM: (Note that with VDE <= 507, the OP starts at VDB as expected)
928 TOM: Vertical Display Begin written by M68K: 41
929 TOM: Vertical Display End written by M68K: 2047
930 TOM: Vertical Interrupt written by M68K: 491
933 // Initial values that "well behaved" programs use
934 uint16_t startingHalfline = GET16(tomRam8, VDB);
935 uint16_t endingHalfline = GET16(tomRam8, VDE);
937 // Simulate the OP start bug here!
938 // Really, this value is somewhere around 507 for an NTSC Jaguar. But this
939 // should work in a majority of cases, at least until we can figure it out
941 if (endingHalfline > GET16(tomRam8, VP))
942 startingHalfline = 0;
944 if ((halfline >= startingHalfline) && (halfline < endingHalfline))
948 uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
949 uint8_t bgHI = tomRam8[BG], bgLO = tomRam8[BG + 1];
951 // Clear line buffer with BG
952 if (GET16(tomRam8, VMODE) & BGEN) // && (CRY or RGB16)...
953 for(uint32_t i=0; i<720; i++)
954 *current_line_buffer++ = bgHI, *current_line_buffer++ = bgLO;
956 OPProcessList(halfline, render);
960 inActiveDisplayArea = false;
962 // Take PAL into account...
964 uint16_t topVisible = (vjs.hardwareTypeNTSC ? TOP_VISIBLE_VC : TOP_VISIBLE_VC_PAL),
965 bottomVisible = (vjs.hardwareTypeNTSC ? BOTTOM_VISIBLE_VC : BOTTOM_VISIBLE_VC_PAL);
966 uint32_t * TOMCurrentLine = 0;
968 // Bit 0 in VP is interlace flag. 0 = interlace, 1 = non-interlaced
969 if (tomRam8[VP + 1] & 0x01)
970 TOMCurrentLine = &(screenBuffer[((halfline - topVisible) / 2) * screenPitch]);//non-interlace
972 TOMCurrentLine = &(screenBuffer[(((halfline - topVisible) / 2) * screenPitch * 2) + (field2 ? 0 : screenPitch)]);//interlace
974 // Here's our virtualized scanline code...
976 if ((halfline >= topVisible) && (halfline < bottomVisible))
978 if (inActiveDisplayArea)
980 #warning "The following doesn't put BORDER color on the sides... !!! FIX !!!"
981 if (vjs.renderType == RT_NORMAL)
983 scanline_render[TOMGetVideoMode()](TOMCurrentLine);
989 tom_render_16bpp_cry_scanline,
990 tom_render_24bpp_scanline,
991 tom_render_16bpp_direct_scanline,
992 tom_render_16bpp_rgb_scanline,
993 tom_render_16bpp_cry_rgb_mix_scanline,
994 tom_render_24bpp_scanline,
995 tom_render_16bpp_direct_scanline,
996 tom_render_16bpp_rgb_scanline
998 #define MODE 0x0006 // Line buffer to video generator mode
999 #define VARMOD 0x0100 // Mixed CRY/RGB16 mode (only works in MODE 0!)
1001 uint8_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
1002 uint8_t mode = ((GET16(tomRam8, VMODE) & MODE) >> 1);
1003 bool varmod = GET16(tomRam8, VMODE) & VARMOD;
1004 //The video texture line buffer ranges from 0 to 1279, with its left edge
1005 //starting at LEFT_VISIBLE_HC. So, we need to start writing into the backbuffer
1006 //at HDB1, using pwidth as our scaling factor. The way it generates its image
1009 //So, for example, if HDB1 is less than LEFT_VISIBLE_HC, then we have to figure
1010 //out where in the VTLB that we start writing pixels from the Jaguar line
1011 //buffer (VTLB start=0, JLB=something).
1014 // 24 BPP mode rendering
1016 void tom_render_24bpp_scanline(uint32_t * backbuffer)
1018 //CHANGED TO 32BPP RENDERING
1019 uint16_t width = tomWidth;
1020 uint8_t * current_line_buffer = (uint8_t *)&tomRam8[0x1800];
1022 //New stuff--restrict our drawing...
1023 uint8_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
1024 //NOTE: May have to check HDB2 as well!
1025 int16_t startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL); // Get start position in HC ticks
1028 current_line_buffer += 4 * -startPos;
1030 //This should likely be 4 instead of 2 (?--not sure)
1031 backbuffer += 2 * startPos, width -= startPos;
1035 uint32_t g = *current_line_buffer++;
1036 uint32_t r = *current_line_buffer++;
1037 current_line_buffer++;
1038 uint32_t b = *current_line_buffer++;
1039 *backbuffer++ = 0xFF000000 | (b << 16) | (g << 8) | r;
1049 // If outside of VDB & VDE, then display the border color
1050 uint32_t * currentLineBuffer = TOMCurrentLine;
1051 uint8_t g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
1052 //Hm. uint32_t pixel = 0xFF000000 | (b << 16) | (g << 8) | r;
1053 uint32_t pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
1055 for(uint32_t i=0; i<tomWidth; i++)
1056 *currentLineBuffer++ = pixel;
1063 // TOM initialization
1067 TOMFillLookupTables();
1076 TOMDumpIORegistersToLog();
1079 WriteLog("TOM: Resolution %i x %i %s\n", TOMGetVideoModeWidth(),
1080 TOMGetVideoModeHeight(), videoMode_to_str[TOMGetVideoMode()]);
1084 uint32_t TOMGetVideoModeWidth(void)
1086 // Note that the following PWIDTH values have the following pixel aspect
1088 // PWIDTH = 1 -> 0.25:1 (1:4) pixels (X:Y ratio)
1089 // PWIDTH = 2 -> 0.50:1 (1:2) pixels
1090 // PWIDTH = 3 -> 0.75:1 (3:4) pixels
1091 // PWIDTH = 4 -> 1.00:1 (1:1) pixels
1092 // PWIDTH = 5 -> 1.25:1 (5:4) pixels
1093 // PWIDTH = 6 -> 1.50:1 (3:2) pixels
1094 // PWIDTH = 7 -> 1.75:1 (7:4) pixels
1095 // PWIDTH = 8 -> 2.00:1 (2:1) pixels
1097 // Also note that the JTRM says that PWIDTH of 4 gives pixels that are
1098 // "about" square--this implies that the other modes have pixels that are
1099 // *not* square (and they aren't)!
1100 // Also, I seriously doubt that you will see any games that use PWIDTH = 1!
1102 // To make it easier to make a quasi-fixed display size, we restrict the
1103 // viewing area to an arbitrary range of the Horizontal Count.
1104 uint16_t pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
1105 return (vjs.hardwareTypeNTSC ? RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC : RIGHT_VISIBLE_HC_PAL - LEFT_VISIBLE_HC_PAL) / pwidth;
1109 uint32_t TOMGetVideoModeHeight(void)
1111 // Set virtual screen height to 240 (NTSC) or 256 (PAL) lines...
1112 return (vjs.hardwareTypeNTSC ? 240 : 256);
1118 // Now PAL friendly!
1121 The values in TOMReset come from the Jaguar BIOS.
1122 These values are from BJL:
1168 memset(tomRam8, 0x00, 0x4000);
1170 if (vjs.hardwareTypeNTSC)
1172 SET16(tomRam8, MEMCON1, 0x1861);
1173 // SET16(tomRam8, MEMCON1, 0x1865);//Bunch of BS
1174 SET16(tomRam8, MEMCON2, 0x35CC);
1175 SET16(tomRam8, HP, 844); // Horizontal Period (1-based; HP=845)
1176 SET16(tomRam8, HBB, 1713); // Horizontal Blank Begin
1177 SET16(tomRam8, HBE, 125); // Horizontal Blank End
1178 SET16(tomRam8, HDE, 1665); // Horizontal Display End
1179 SET16(tomRam8, HDB1, 203); // Horizontal Display Begin 1
1180 SET16(tomRam8, VP, 523); // Vertical Period (1-based; in this case VP = 524)
1181 SET16(tomRam8, VBE, 24); // Vertical Blank End
1182 SET16(tomRam8, VDB, 38); // Vertical Display Begin
1183 SET16(tomRam8, VDE, 518); // Vertical Display End
1184 SET16(tomRam8, VBB, 500); // Vertical Blank Begin
1185 SET16(tomRam8, VS, 517); // Vertical Sync
1186 SET16(tomRam8, VMODE, 0x06C1);
1190 SET16(tomRam8, MEMCON1, 0x1861);
1191 SET16(tomRam8, MEMCON2, 0x35CC);
1192 SET16(tomRam8, HP, 850); // Horizontal Period
1193 SET16(tomRam8, HBB, 1711); // Horizontal Blank Begin
1194 SET16(tomRam8, HBE, 158); // Horizontal Blank End
1195 SET16(tomRam8, HDE, 1665); // Horizontal Display End
1196 SET16(tomRam8, HDB1, 203); // Horizontal Display Begin 1
1197 SET16(tomRam8, VP, 623); // Vertical Period (1-based; in this case VP = 624)
1198 SET16(tomRam8, VBE, 34); // Vertical Blank End
1199 SET16(tomRam8, VDB, 38); // Vertical Display Begin
1200 SET16(tomRam8, VDE, 518); // Vertical Display End
1201 SET16(tomRam8, VBB, 600); // Vertical Blank Begin
1202 SET16(tomRam8, VS, 618); // Vertical Sync
1203 SET16(tomRam8, VMODE, 0x06C1);
1209 tom_jerry_int_pending = 0;
1210 tom_timer_int_pending = 0;
1211 tom_object_int_pending = 0;
1212 tom_gpu_int_pending = 0;
1213 tom_video_int_pending = 0;
1215 tomTimerPrescaler = 0; // TOM PIT is disabled
1216 tomTimerDivider = 0;
1217 tomTimerCounter = 0;
1222 // Dump all TOM register values to the log
1224 void TOMDumpIORegistersToLog(void)
1226 WriteLog("\n\n---------------------------------------------------------------------\n");
1227 WriteLog("TOM I/O Registers\n");
1228 WriteLog("---------------------------------------------------------------------\n");
1229 WriteLog("F000%02X (MEMCON1): $%04X\n", MEMCON1, GET16(tomRam8, MEMCON1));
1230 WriteLog("F000%02X (MEMCON2): $%04X\n", MEMCON2, GET16(tomRam8, MEMCON2));
1231 WriteLog("F000%02X (HC): $%04X\n", HC, GET16(tomRam8, HC));
1232 WriteLog("F000%02X (VC): $%04X\n", VC, GET16(tomRam8, VC));
1233 WriteLog("F000%02X (OLP): $%08X\n", OLP, GET32(tomRam8, OLP));
1234 WriteLog("F000%02X (OBF): $%04X\n", OBF, GET16(tomRam8, OBF));
1235 WriteLog("F000%02X (VMODE): $%04X\n", VMODE, GET16(tomRam8, VMODE));
1236 WriteLog("F000%02X (BORD1): $%04X\n", BORD1, GET16(tomRam8, BORD1));
1237 WriteLog("F000%02X (BORD2): $%04X\n", BORD2, GET16(tomRam8, BORD2));
1238 WriteLog("F000%02X (HP): $%04X\n", HP, GET16(tomRam8, HP));
1239 WriteLog("F000%02X (HBB): $%04X\n", HBB, GET16(tomRam8, HBB));
1240 WriteLog("F000%02X (HBE): $%04X\n", HBE, GET16(tomRam8, HBE));
1241 WriteLog("F000%02X (HS): $%04X\n", HS, GET16(tomRam8, HS));
1242 WriteLog("F000%02X (HVS): $%04X\n", HVS, GET16(tomRam8, HVS));
1243 WriteLog("F000%02X (HDB1): $%04X\n", HDB1, GET16(tomRam8, HDB1));
1244 WriteLog("F000%02X (HDB2): $%04X\n", HDB2, GET16(tomRam8, HDB2));
1245 WriteLog("F000%02X (HDE): $%04X\n", HDE, GET16(tomRam8, HDE));
1246 WriteLog("F000%02X (VP): $%04X\n", VP, GET16(tomRam8, VP));
1247 WriteLog("F000%02X (VBB): $%04X\n", VBB, GET16(tomRam8, VBB));
1248 WriteLog("F000%02X (VBE): $%04X\n", VBE, GET16(tomRam8, VBE));
1249 WriteLog("F000%02X (VS): $%04X\n", VS, GET16(tomRam8, VS));
1250 WriteLog("F000%02X (VDB): $%04X\n", VDB, GET16(tomRam8, VDB));
1251 WriteLog("F000%02X (VDE): $%04X\n", VDE, GET16(tomRam8, VDE));
1252 WriteLog("F000%02X (VEB): $%04X\n", VEB, GET16(tomRam8, VEB));
1253 WriteLog("F000%02X (VEE): $%04X\n", VEE, GET16(tomRam8, VEE));
1254 WriteLog("F000%02X (VI): $%04X\n", VI, GET16(tomRam8, VI));
1255 WriteLog("F000%02X (PIT0): $%04X\n", PIT0, GET16(tomRam8, PIT0));
1256 WriteLog("F000%02X (PIT1): $%04X\n", PIT1, GET16(tomRam8, PIT1));
1257 WriteLog("F000%02X (HEQ): $%04X\n", HEQ, GET16(tomRam8, HEQ));
1258 WriteLog("F000%02X (BG): $%04X\n", BG, GET16(tomRam8, BG));
1259 WriteLog("F000%02X (INT1): $%04X\n", INT1, GET16(tomRam8, INT1));
1260 WriteLog("F000%02X (INT2): $%04X\n", INT2, GET16(tomRam8, INT2));
1261 WriteLog("---------------------------------------------------------------------\n\n\n");
1266 // TOM byte access (read)
1268 uint8_t TOMReadByte(uint32_t offset, uint32_t who/*=UNKNOWN*/)
1270 //???Is this needed???
1271 // It seems so. Perhaps it's the +$8000 offset being written to (32-bit interface)?
1272 // However, the 32-bit interface is WRITE ONLY, so that can't be it...
1273 // Also, the 68K CANNOT make use of the 32-bit interface, since its bus width is only 16-bits...
1274 // offset &= 0xFF3FFF;
1277 WriteLog("TOM: Reading byte at %06X for %s\n", offset, whoName[who]);
1280 if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
1281 return GPUReadByte(offset, who);
1282 else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
1283 return GPUReadByte(offset, who);
1284 /* else if ((offset >= 0xF00010) && (offset < 0xF00028))
1285 return OPReadByte(offset, who);*/
1286 else if ((offset >= 0xF02200) && (offset < 0xF022A0))
1287 return BlitterReadByte(offset, who);
1288 else if (offset == 0xF00050)
1289 return tomTimerPrescaler >> 8;
1290 else if (offset == 0xF00051)
1291 return tomTimerPrescaler & 0xFF;
1292 else if (offset == 0xF00052)
1293 return tomTimerDivider >> 8;
1294 else if (offset == 0xF00053)
1295 return tomTimerDivider & 0xFF;
1297 return tomRam8[offset & 0x3FFF];
1302 // TOM word access (read)
1304 uint16_t TOMReadWord(uint32_t offset, uint32_t who/*=UNKNOWN*/)
1306 //???Is this needed???
1307 // offset &= 0xFF3FFF;
1309 WriteLog("TOM: Reading word at %06X for %s\n", offset, whoName[who]);
1311 if (offset >= 0xF02000 && offset <= 0xF020FF)
1312 WriteLog("TOM: ReadWord attempted from GPU register file by %s (unimplemented)!\n", whoName[who]);
1314 if (offset == 0xF000E0)
1316 // For reading, should only return the lower 5 bits...
1317 uint16_t data = (tom_jerry_int_pending << 4) | (tom_timer_int_pending << 3)
1318 | (tom_object_int_pending << 2) | (tom_gpu_int_pending << 1)
1319 | (tom_video_int_pending << 0);
1320 //WriteLog("tom: interrupt status is 0x%.4x \n",data);
1323 //Shoud be handled by the jaguar main loop now... And it is! ;-)
1324 /* else if (offset == 0xF00006) // VC
1325 // What if we're in interlaced mode?
1326 // According to docs, in non-interlace mode VC is ALWAYS even...
1327 // return (tom_scanline << 1);// + 1;
1328 //But it's causing Rayman to be fucked up... Why???
1329 //Because VC is even in NI mode when calling the OP! That's why!
1330 return (tom_scanline << 1) + 1;//*/
1332 // F00004 R/W -----xxx xxxxxxxx HC - horizontal count
1333 // -----x-- -------- (which half of the display)
1334 // ------xx xxxxxxxx (10-bit counter)
1336 // This is a kludge to get the HC working somewhat... What we really should do here
1337 // is check what the global time is at the time of the read and calculate the correct HC...
1339 else if (offset == 0xF00004)
1340 return rand() & 0x03FF;
1341 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE + 0x20))
1342 return GPUReadWord(offset, who);
1343 else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
1344 return GPUReadWord(offset, who);
1345 /* else if ((offset >= 0xF00010) && (offset < 0xF00028))
1346 return OPReadWord(offset, who);*/
1347 else if ((offset >= 0xF02200) && (offset < 0xF022A0))
1348 return BlitterReadWord(offset, who);
1349 else if (offset == 0xF00050)
1350 return tomTimerPrescaler;
1351 else if (offset == 0xF00052)
1352 return tomTimerDivider;
1355 return (TOMReadByte(offset, who) << 8) | TOMReadByte(offset + 1, who);
1359 #define TOM_STRICT_MEMORY_ACCESS
1361 // TOM byte access (write)
1363 void TOMWriteByte(uint32_t offset, uint8_t data, uint32_t who/*=UNKNOWN*/)
1365 // Moved here tentatively, so we can see everything written to TOM.
1366 tomRam8[offset & 0x3FFF] = data;
1369 WriteLog("TOM: Writing byte %02X at %06X", data, offset);
1371 //???Is this needed???
1372 // Perhaps on the writes--32-bit writes that is! And masked with FF7FFF...
1373 #ifndef TOM_STRICT_MEMORY_ACCESS
1376 // "Fast" (32-bit only) write access to the GPU
1377 // if ((offset >= 0xF0A100) && (offset <= 0xF0BFFF))
1378 if ((offset >= 0xF08000) && (offset <= 0xF0BFFF))
1382 WriteLog(" -->[%06X] by %s\n", offset, whoName[who]);
1385 #ifdef TOM_STRICT_MEMORY_ACCESS
1386 // Sanity check ("Aww, there ain't no Sanity Clause...")
1387 if ((offset < 0xF00000) || (offset > 0xF03FFF))
1391 if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
1393 GPUWriteByte(offset, data, who);
1396 else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
1398 GPUWriteByte(offset, data, who);
1401 /* else if ((offset >= 0xF00010) && (offset < 0xF00028))
1403 OPWriteByte(offset, data, who);
1406 else if ((offset >= 0xF02200) && (offset < 0xF022A0))
1408 BlitterWriteByte(offset, data, who);
1411 else if (offset == 0xF00050)
1413 tomTimerPrescaler = (tomTimerPrescaler & 0x00FF) | (data << 8);
1417 else if (offset == 0xF00051)
1419 tomTimerPrescaler = (tomTimerPrescaler & 0xFF00) | data;
1423 else if (offset == 0xF00052)
1425 tomTimerDivider = (tomTimerDivider & 0x00FF) | (data << 8);
1429 else if (offset == 0xF00053)
1431 tomTimerDivider = (tomTimerDivider & 0xFF00) | data;
1435 else if (offset >= 0xF00400 && offset <= 0xF007FF) // CLUT (A & B)
1437 // Writing to one CLUT writes to the other
1438 offset &= 0x5FF; // Mask out $F00600 (restrict to $F00400-5FF)
1439 tomRam8[offset] = data, tomRam8[offset + 0x200] = data;
1442 // tomRam8[offset & 0x3FFF] = data;
1447 // TOM word access (write)
1449 void TOMWriteWord(uint32_t offset, uint16_t data, uint32_t who/*=UNKNOWN*/)
1451 // Moved here tentatively, so we can see everything written to TOM.
1452 tomRam8[(offset + 0) & 0x3FFF] = data >> 8;
1453 tomRam8[(offset + 1) & 0x3FFF] = data & 0xFF;
1456 WriteLog("TOM: Writing byte %04X at %06X", data, offset);
1458 //???Is this needed??? Yes, but we need to be more vigilant than this.
1459 #ifndef TOM_STRICT_MEMORY_ACCESS
1462 // "Fast" (32-bit only) write access to the GPU
1463 // if ((offset >= 0xF0A100) && (offset <= 0xF0BFFF))
1464 if ((offset >= 0xF08000) && (offset <= 0xF0BFFF))
1468 WriteLog(" -->[%06X] by %s\n", offset, whoName[who]);
1471 #ifdef TOM_STRICT_MEMORY_ACCESS
1473 if ((offset < 0xF00000) || (offset > 0xF03FFF))
1477 //if (offset == 0xF00000 + MEMCON1)
1478 // WriteLog("TOM: Memory Configuration 1 written by %s: %04X\n", whoName[who], data);
1479 //if (offset == 0xF00000 + MEMCON2)
1480 // WriteLog("TOM: Memory Configuration 2 written by %s: %04X\n", whoName[who], data);
1481 if (offset >= 0xF02000 && offset <= 0xF020FF)
1482 WriteLog("TOM: WriteWord attempted to GPU register file by %s (unimplemented)!\n", whoName[who]);
1484 if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
1486 GPUWriteWord(offset, data, who);
1489 else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
1491 GPUWriteWord(offset, data, who);
1494 //What's so special about this?
1495 /* else if ((offset >= 0xF00000) && (offset < 0xF00002))
1497 TOMWriteByte(offset, data >> 8);
1498 TOMWriteByte(offset+1, data & 0xFF);
1500 /* else if ((offset >= 0xF00010) && (offset < 0xF00028))
1502 OPWriteWord(offset, data, who);
1505 else if (offset == 0xF00050)
1507 tomTimerPrescaler = data;
1511 else if (offset == 0xF00052)
1513 tomTimerDivider = data;
1517 else if (offset == 0xF000E0)
1521 tom_video_int_pending = 0;
1523 tom_gpu_int_pending = 0;
1525 tom_object_int_pending = 0;
1527 tom_timer_int_pending = 0;
1529 tom_jerry_int_pending = 0;
1533 else if ((offset >= 0xF02200) && (offset <= 0xF0229F))
1535 BlitterWriteWord(offset, data, who);
1538 else if (offset >= 0xF00400 && offset <= 0xF007FE) // CLUT (A & B)
1540 // Writing to one CLUT writes to the other
1541 offset &= 0x5FF; // Mask out $F00600 (restrict to $F00400-5FF)
1542 // Watch out for unaligned writes here! (Not fixed yet)
1543 #warning "!!! Watch out for unaligned writes here !!! FIX !!!"
1544 SET16(tomRam8, offset, data);
1545 SET16(tomRam8, offset + 0x200, data);
1549 if (offset == 0x28) // VMODE (Why? Why not OBF?)
1550 //Actually, we should check to see if the Enable bit of VMODE is set before doing this... !!! FIX !!!
1551 #warning "Actually, we should check to see if the Enable bit of VMODE is set before doing this... !!! FIX !!!"
1552 objectp_running = 1;
1554 if (offset >= 0x30 && offset <= 0x4E)
1555 data &= 0x07FF; // These are (mostly) 11-bit registers
1556 if (offset == 0x2E || offset == 0x36 || offset == 0x54)
1557 data &= 0x03FF; // These are all 10-bit registers
1559 // Fix a lockup bug... :-P
1560 // TOMWriteByte(0xF00000 | offset, data >> 8, who);
1561 // TOMWriteByte(0xF00000 | (offset+1), data & 0xFF, who);
1563 if (offset == MEMCON1)
1564 WriteLog("TOM: Memory Config 1 written by %s: $%04X\n", whoName[who], data);
1565 if (offset == MEMCON2)
1566 WriteLog("TOM: Memory Config 2 written by %s: $%04X\n", whoName[who], data);
1567 //if (offset == OLP)
1568 // WriteLog("TOM: Object List Pointer written by %s: $%04X\n", whoName[who], data);
1569 //if (offset == OLP + 2)
1570 // WriteLog("TOM: Object List Pointer +2 written by %s: $%04X\n", whoName[who], data);
1571 //if (offset == OBF)
1572 // WriteLog("TOM: Object Processor Flag written by %s: %u\n", whoName[who], data);
1573 if (offset == VMODE)
1574 WriteLog("TOM: Video Mode written by %s: %04X. PWIDTH = %u, MODE = %s, flags:%s%s (VC = %u) (M68K PC = %06X)\n", whoName[who], data, ((data >> 9) & 0x07) + 1, videoMode_to_str[(data & MODE) >> 1], (data & BGEN ? " BGEN" : ""), (data & VARMOD ? " VARMOD" : ""), GET16(tomRam8, VC), m68k_get_reg(NULL, M68K_REG_PC));
1575 if (offset == BORD1)
1576 WriteLog("TOM: Border 1 written by %s: $%04X\n", whoName[who], data);
1577 if (offset == BORD2)
1578 WriteLog("TOM: Border 2 written by %s: $%04X\n", whoName[who], data);
1580 WriteLog("TOM: Horizontal Period written by %s: %u (+1*2 = %u)\n", whoName[who], data, (data + 1) * 2);
1582 WriteLog("TOM: Horizontal Blank Begin written by %s: %u\n", whoName[who], data);
1584 WriteLog("TOM: Horizontal Blank End written by %s: %u\n", whoName[who], data);
1586 WriteLog("TOM: Horizontal Sync written by %s: %u\n", whoName[who], data);
1588 WriteLog("TOM: Horizontal Vertical Sync written by %s: %u\n", whoName[who], data);
1590 WriteLog("TOM: Horizontal Display Begin 1 written by %s: %u\n", whoName[who], data);
1592 WriteLog("TOM: Horizontal Display Begin 2 written by %s: %u\n", whoName[who], data);
1594 WriteLog("TOM: Horizontal Display End written by %s: %u\n", whoName[who], data);
1596 WriteLog("TOM: Vertical Period written by %s: %u (%sinterlaced)\n", whoName[who], data, (data & 0x01 ? "non-" : ""));
1598 WriteLog("TOM: Vertical Blank Begin written by %s: %u\n", whoName[who], data);
1600 WriteLog("TOM: Vertical Blank End written by %s: %u\n", whoName[who], data);
1602 WriteLog("TOM: Vertical Sync written by %s: %u\n", whoName[who], data);
1604 WriteLog("TOM: Vertical Display Begin written by %s: %u\n", whoName[who], data);
1606 WriteLog("TOM: Vertical Display End written by %s: %u\n", whoName[who], data);
1608 WriteLog("TOM: Vertical Equalization Begin written by %s: %u\n", whoName[who], data);
1610 WriteLog("TOM: Vertical Equalization End written by %s: %u\n", whoName[who], data);
1612 WriteLog("TOM: Vertical Interrupt written by %s: %u\n", whoName[who], data);
1614 WriteLog("TOM: PIT0 written by %s: %u\n", whoName[who], data);
1616 WriteLog("TOM: PIT1 written by %s: %u\n", whoName[who], data);
1618 WriteLog("TOM: Horizontal Equalization End written by %s: %u\n", whoName[who], data);
1620 // WriteLog("TOM: Background written by %s: %u\n", whoName[who], data);
1621 //if (offset == INT1)
1622 // 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" : ""));
1624 // detect screen resolution changes
1625 //This may go away in the future, if we do the virtualized screen thing...
1626 //This may go away soon!
1627 // TOM Shouldn't be mucking around with this, it's up to the host system to properly
1628 // handle this kind of crap.
1629 // NOTE: This is needed somehow, need to get rid of the dependency on this crap.
1630 // N.B.: It's used in the rendering functions... So...
1631 #warning "!!! Need to get rid of this dependency !!!"
1633 if ((offset >= 0x28) && (offset <= 0x4F))
1635 uint32_t width = TOMGetVideoModeWidth(), height = TOMGetVideoModeHeight();
1637 if ((width != tomWidth) || (height != tomHeight))
1639 tomWidth = width, tomHeight = height;
1641 #warning "!!! TOM: ResizeScreen commented out !!!"
1642 // No need to resize anything, since we're prepared for this...
1643 // if (vjs.renderType == RT_NORMAL)
1644 // ResizeScreen(tomWidth, tomHeight);
1651 int TOMIRQEnabled(int irq)
1653 // This is the correct byte in big endian... D'oh!
1654 // return jaguar_byte_read(0xF000E1) & (1 << irq);
1655 return tomRam8[INT1 + 1/*0xE1*/] & (1 << irq);
1660 // TOM Programmable Interrupt Timer handler
1661 // NOTE: TOM's PIT is only enabled if the prescaler is != 0
1662 // The PIT only generates an interrupt when it counts down to zero, not when loaded!
1664 void TOMPITCallback(void);
1667 void TOMResetPIT(void)
1669 #ifndef NEW_TIMER_SYSTEM
1670 //Probably should *add* this amount to the counter to retain cycle accuracy! !!! FIX !!! [DONE]
1671 //Also, why +1??? 'Cause that's what it says in the JTRM...!
1672 //There is a small problem with this approach: If both the prescaler and the divider are equal
1673 //to $FFFF then the counter won't be large enough to handle it. !!! FIX !!!
1674 if (tom_timer_prescaler)
1675 tom_timer_counter += (1 + tom_timer_prescaler) * (1 + tom_timer_divider);
1676 // WriteLog("tom: reseting timer to 0x%.8x (%i)\n",tom_timer_counter,tom_timer_counter);
1678 // Need to remove previous timer from the queue, if it exists...
1679 RemoveCallback(TOMPITCallback);
1681 if (tomTimerPrescaler)
1683 double usecs = (float)(tomTimerPrescaler + 1) * (float)(tomTimerDivider + 1) * RISC_CYCLE_IN_USEC;
1684 SetCallbackTime(TOMPITCallback, usecs);
1691 // TOM Programmable Interrupt Timer handler
1692 // NOTE: TOM's PIT is only enabled if the prescaler is != 0
1694 //NOTE: This is only used by the old execution code... Safe to remove
1695 // once the timer system is stable.
1696 void TOMExecPIT(uint32_t cycles)
1698 if (tomTimerPrescaler)
1700 tomTimerCounter -= cycles;
1702 if (tomTimerCounter <= 0)
1704 TOMSetPendingTimerInt();
1705 GPUSetIRQLine(GPUIRQ_TIMER, ASSERT_LINE); // GPUSetIRQLine does the 'IRQ enabled' checking
1707 if (TOMIRQEnabled(IRQ_TIMER))
1708 m68k_set_irq(2); // Cause a 68000 IPL 2...
1716 void TOMPITCallback(void)
1718 // INT1_RREG |= 0x08; // Set TOM PIT interrupt pending
1719 TOMSetPendingTimerInt();
1720 GPUSetIRQLine(GPUIRQ_TIMER, ASSERT_LINE); // It does the 'IRQ enabled' checking
1722 // if (INT1_WREG & 0x08)
1723 if (TOMIRQEnabled(IRQ_TIMER))
1724 m68k_set_irq(2); // Generate a 68K IPL 2...