4 // Originally by David Raingeard (cal2)
5 // GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
6 // Cleanups and endian wrongness amelioration by James Hammons
7 // (C) 2010 Underground Software
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: 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()
266 #include "m68000/m68kinterface.h"
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 !!! [DONE]
313 // Arbitrary video cutoff values (i.e., first/last visible spots on a TV, in HC ticks)
314 // Also note that VC is in *half* lines, i.e. divide by 2 to get the scanline
315 /*#define LEFT_VISIBLE_HC 208
316 #define RIGHT_VISIBLE_HC 1528//*/
317 // These were right for Rayman, but that one is offset on a real TV too.
318 //#define LEFT_VISIBLE_HC 208
319 //#define RIGHT_VISIBLE_HC 1488
320 // This is more like a real TV display...
321 //#define LEFT_VISIBLE_HC (208 - 32)
322 //#define RIGHT_VISIBLE_HC (1488 - 32)
323 // Split the difference? (Seems to be OK for the most part...)
325 // (-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).
326 #define LEFT_VISIBLE_HC (208 - 16 - (8 * 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 RIGHT_VISIBLE_HC_PAL (1488 - 16 + (10 * 4))
339 #define RIGHT_VISIBLE_HC_PAL (LEFT_VISIBLE_HC_PAL + (VIRTUAL_SCREEN_WIDTH * 4))
340 #define TOP_VISIBLE_VC_PAL 67
341 #define BOTTOM_VISIBLE_VC_PAL 579
343 //This can be defined in the makefile as well...
344 //(It's easier to do it here, though...)
347 uint8 tomRam8[0x4000];
348 uint32 tomWidth, tomHeight;
349 uint32 tomTimerPrescaler;
350 uint32 tomTimerDivider;
351 int32 tomTimerCounter;
352 uint16 tom_jerry_int_pending, tom_timer_int_pending, tom_object_int_pending,
353 tom_gpu_int_pending, tom_video_int_pending;
355 // These are set by the "user" of the Jaguar core lib, since these are
356 // OS/system dependent.
357 uint32 * screenBuffer;
360 static const char * videoMode_to_str[8] =
361 { "16 BPP CRY", "24 BPP RGB", "16 BPP DIRECT", "16 BPP RGB",
362 "Mixed mode", "24 BPP RGB", "16 BPP DIRECT", "16 BPP RGB" };
364 typedef void (render_xxx_scanline_fn)(uint32 *);
366 // Private function prototypes
368 void tom_render_16bpp_cry_scanline(uint32 * backbuffer);
369 void tom_render_24bpp_scanline(uint32 * backbuffer);
370 void tom_render_16bpp_direct_scanline(uint32 * backbuffer);
371 void tom_render_16bpp_rgb_scanline(uint32 * backbuffer);
372 void tom_render_16bpp_cry_rgb_mix_scanline(uint32 * backbuffer);
374 //render_xxx_scanline_fn * scanline_render_normal[] =
375 render_xxx_scanline_fn * scanline_render[] =
377 tom_render_16bpp_cry_scanline,
378 tom_render_24bpp_scanline,
379 tom_render_16bpp_direct_scanline,
380 tom_render_16bpp_rgb_scanline,
381 tom_render_16bpp_cry_rgb_mix_scanline,
382 tom_render_24bpp_scanline,
383 tom_render_16bpp_direct_scanline,
384 tom_render_16bpp_rgb_scanline
387 // Screen info for various games [PAL]...
390 TOM: Horizontal Period written by M68K: 850 (+1*2 = 1702)
391 TOM: Horizontal Blank Begin written by M68K: 1711
392 TOM: Horizontal Blank End written by M68K: 158
393 TOM: Horizontal Display End written by M68K: 1696
394 TOM: Horizontal Display Begin 1 written by M68K: 166
395 TOM: Vertical Period written by M68K: 623 (non-interlaced)
396 TOM: Vertical Blank End written by M68K: 34
397 TOM: Vertical Display Begin written by M68K: 46
398 TOM: Vertical Display End written by M68K: 526
399 TOM: Vertical Blank Begin written by M68K: 600
400 TOM: Vertical Sync written by M68K: 618
401 TOM: Horizontal Display End written by M68K: 1665
402 TOM: Horizontal Display Begin 1 written by M68K: 203
403 TOM: Vertical Display Begin written by M68K: 38
404 TOM: Vertical Display End written by M68K: 518
405 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 151)
406 TOM: Horizontal Display End written by M68K: 1713
407 TOM: Horizontal Display Begin 1 written by M68K: 157
408 TOM: Vertical Display Begin written by M68K: 35
409 TOM: Vertical Display End written by M68K: 2047
410 Horizontal range: 157 - 1713 (width: 1557 / 4 = 389.25, / 5 = 315.4)
413 TOM: Horizontal Period written by M68K: 845 (+1*2 = 1692)
414 TOM: Horizontal Blank Begin written by M68K: 1700
415 TOM: Horizontal Blank End written by M68K: 122
416 TOM: Horizontal Display End written by M68K: 1600
417 TOM: Horizontal Display Begin 1 written by M68K: 268
418 TOM: Vertical Period written by M68K: 523 (non-interlaced)
419 TOM: Vertical Blank End written by M68K: 40
420 TOM: Vertical Display Begin written by M68K: 44
421 TOM: Vertical Display End written by M68K: 492
422 TOM: Vertical Blank Begin written by M68K: 532
423 TOM: Vertical Sync written by M68K: 513
424 TOM: Video Mode written by M68K: 04C7. PWIDTH = 3, MODE = 16 BPP RGB, flags: BGEN (VC = 461)
427 TOM: Horizontal Display End written by M68K: 1713
428 TOM: Horizontal Display Begin 1 written by M68K: 157
429 TOM: Vertical Display Begin written by M68K: 35
430 TOM: Vertical Display End written by M68K: 2047
431 TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 89)
432 TOM: Horizontal Display Begin 1 written by M68K: 208
433 TOM: Horizontal Display End written by M68K: 1662
434 TOM: Vertical Display Begin written by M68K: 100
435 TOM: Vertical Display End written by M68K: 2047
436 TOM: Video Mode written by M68K: 07C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN VARMOD (VC = 205)
437 Horizontal range: 208 - 1662 (width: 1455 / 4 = 363.5)
440 TOM: Vertical Display Begin written by M68K: 96
441 TOM: Vertical Display End written by M68K: 2047
442 TOM: Horizontal Display Begin 1 written by M68K: 239
443 TOM: Horizontal Display End written by M68K: 1692
444 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 378)
445 TOM: Vertical Display Begin written by M68K: 44
446 TOM: Vertical Display End written by M68K: 2047
447 TOM: Horizontal Display Begin 1 written by M68K: 239
448 TOM: Horizontal Display End written by M68K: 1692
449 TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 559)
450 TOM: Vertical Display Begin written by M68K: 84
451 TOM: Vertical Display End written by M68K: 2047
452 TOM: Horizontal Display Begin 1 written by M68K: 239
453 TOM: Horizontal Display End written by M68K: 1692
454 TOM: Vertical Display Begin written by M68K: 44
455 TOM: Vertical Display End written by M68K: 2047
456 TOM: Horizontal Display Begin 1 written by M68K: 239
457 TOM: Horizontal Display End written by M68K: 1692
458 Horizontal range: 239 - 1692 (width: 1454 / 4 = 363.5)
462 // Screen info for various games [NTSC]...
465 TOM: Horizontal Display End written by M68K: 1727
466 TOM: Horizontal Display Begin 1 written by M68K: 123
467 TOM: Vertical Display Begin written by M68K: 25
468 TOM: Vertical Display End written by M68K: 2047
469 TOM: Video Mode written by M68K: 0EC1. PWIDTH = 8, MODE = 16 BPP CRY, flags: BGEN (VC = 5)
470 Also does PWIDTH = 4...
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: Vertical Interrupt written by M68K: 507
479 TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 92)
480 TOM: Horizontal Display Begin 1 written by M68K: 208
481 TOM: Horizontal Display End written by M68K: 1670
482 Display starts at 31, then 52!
483 Vertical resolution: 238 lines
486 TOM: Horizontal Display End written by M68K: 1727
487 TOM: Horizontal Display Begin 1 written by M68K: 123
488 TOM: Vertical Display Begin written by M68K: 25
489 TOM: Vertical Display End written by M68K: 2047
490 TOM: Video Mode written by GPU: 08C7. PWIDTH = 5, MODE = 16 BPP RGB, flags: BGEN (VC = 4)
491 TOM: Video Mode written by GPU: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 508)
492 Display starts at 31 (PWIDTH = 4), 24 (PWIDTH = 5)
495 TOM: Vertical Interrupt written by M68K: 2047
496 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 0)
497 TOM: Horizontal Display End written by M68K: 1727
498 TOM: Horizontal Display Begin 1 written by M68K: 123
499 TOM: Vertical Display Begin written by M68K: 25
500 TOM: Vertical Display End written by M68K: 2047
501 TOM: Vertical Interrupt written by M68K: 507
502 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 369)
503 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 510)
504 TOM: Video Mode written by M68K: 06C3. PWIDTH = 4, MODE = 24 BPP RGB, flags: BGEN (VC = 510)
506 Vertical resolution: 238 lines
507 [Seems to be a problem between the horizontal positioning of the 16-bit CRY & 24-bit RGB]
510 TOM: Horizontal Period written by M68K: 844 (+1*2 = 1690)
511 TOM: Horizontal Blank Begin written by M68K: 1713
512 TOM: Horizontal Blank End written by M68K: 125
513 TOM: Horizontal Display End written by M68K: 1696
514 TOM: Horizontal Display Begin 1 written by M68K: 166
515 TOM: Vertical Period written by M68K: 523 (non-interlaced)
516 TOM: Vertical Blank End written by M68K: 24
517 TOM: Vertical Display Begin written by M68K: 46
518 TOM: Vertical Display End written by M68K: 496
519 TOM: Vertical Blank Begin written by M68K: 500
520 TOM: Vertical Sync written by M68K: 517
521 TOM: Vertical Interrupt written by M68K: 497
522 TOM: Video Mode written by M68K: 04C1. PWIDTH = 3, MODE = 16 BPP CRY, flags: BGEN (VC = 270)
526 TOM: Horizontal Display End written by M68K: 1727
527 TOM: Horizontal Display Begin 1 written by M68K: 123
528 TOM: Vertical Display Begin written by M68K: 25
529 TOM: Vertical Display End written by M68K: 2047
530 TOM: Vertical Interrupt written by M68K: 507
531 TOM: Video Mode written by M68K: 06C7. PWIDTH = 4, MODE = 16 BPP RGB, flags: BGEN (VC = 9)
534 TOM: Horizontal Display End written by M68K: 1823
535 TOM: Horizontal Display Begin 1 written by M68K: 45
536 TOM: Vertical Display Begin written by M68K: 40
537 TOM: Vertical Display End written by M68K: 2047
538 TOM: Vertical Interrupt written by M68K: 491
539 TOM: Video Mode written by M68K: 06C1. PWIDTH = 4, MODE = 16 BPP CRY, flags: BGEN (VC = 398)
540 Display starts at 11 (123 - 45 = 78, 78 / 4 = 19 pixels to skip)
541 Width is 417, so maybe width of 379 would be good (starting at 123, ending at 1639)
542 Vertical resolution: 238 lines
545 TOM: Horizontal Display End written by M68K: 1727
546 TOM: Horizontal Display Begin 1 written by M68K: 188
547 TOM: Vertical Display Begin written by M68K: 1
548 TOM: Vertical Display End written by M68K: 2047
549 TOM: Vertical Interrupt written by M68K: 483
550 TOM: Video Mode written by M68K: 08C7. PWIDTH = 5, MODE = 16 BPP RGB, flags: BGEN (VC = 99)
551 Width would be 303 with above scheme, but border width would be 13 pixels
554 Vertical resolution: 238 lines
557 uint32 RGB16ToRGB32[0x10000];
558 uint32 CRY16ToRGB32[0x10000];
559 uint32 MIX16ToRGB32[0x10000];
562 #warning "This is not endian-safe. !!! FIX !!!"
563 void TOMFillLookupTables(void)
565 // NOTE: Jaguar 16-bit (non-CRY) color is RBG 556 like so:
566 // RRRR RBBB BBGG GGGG
567 for(uint32 i=0; i<0x10000; i++)
568 //hm. RGB16ToRGB32[i] = 0xFF000000
569 // | ((i & 0xF100) >> 8) | ((i & 0xE000) >> 13)
570 // | ((i & 0x07C0) << 13) | ((i & 0x0700) << 8)
571 // | ((i & 0x003F) << 10) | ((i & 0x0030) << 4);
572 RGB16ToRGB32[i] = 0x000000FF
573 | ((i & 0xF100) << 16) // Red
574 | ((i & 0x003F) << 18) // Green
575 | ((i & 0x07C0) << 5); // Blue
577 for(uint32 i=0; i<0x10000; i++)
579 uint32 cyan = (i & 0xF000) >> 12,
580 red = (i & 0x0F00) >> 8,
581 intensity = (i & 0x00FF);
583 uint32 r = (((uint32)redcv[cyan][red]) * intensity) >> 8,
584 g = (((uint32)greencv[cyan][red]) * intensity) >> 8,
585 b = (((uint32)bluecv[cyan][red]) * intensity) >> 8;
587 //hm. CRY16ToRGB32[i] = 0xFF000000 | (b << 16) | (g << 8) | r;
588 CRY16ToRGB32[i] = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
589 MIX16ToRGB32[i] = (i & 0x01 ? RGB16ToRGB32[i] : CRY16ToRGB32[i]);
594 void TOMSetPendingJERRYInt(void)
596 tom_jerry_int_pending = 1;
600 void TOMSetPendingTimerInt(void)
602 tom_timer_int_pending = 1;
606 void TOMSetPendingObjectInt(void)
608 tom_object_int_pending = 1;
612 void TOMSetPendingGPUInt(void)
614 tom_gpu_int_pending = 1;
618 void TOMSetPendingVideoInt(void)
620 tom_video_int_pending = 1;
624 uint8 * TOMGetRamPointer(void)
630 uint8 TOMGetVideoMode(void)
632 uint16 vmode = GET16(tomRam8, VMODE);
633 return ((vmode & VARMOD) >> 6) | ((vmode & MODE) >> 1);
637 //Used in only one place (and for debug purposes): OBJECTP.CPP
638 #warning "Used in only one place (and for debug purposes): OBJECTP.CPP !!! FIX !!!"
639 uint16 TOMGetVDB(void)
641 return GET16(tomRam8, VDB);
647 // 16 BPP CRY/RGB mixed mode rendering
649 void tom_render_16bpp_cry_rgb_mix_scanline(uint32 * backbuffer)
651 //CHANGED TO 32BPP RENDERING
652 uint16 width = tomWidth;
653 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
655 //New stuff--restrict our drawing...
656 uint8 pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
657 //NOTE: May have to check HDB2 as well!
658 // Get start position in HC ticks
659 int16 startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL);
664 // This is x2 because current_line_buffer is uint8 & we're in a 16bpp mode
665 current_line_buffer += 2 * -startPos;
667 //This case doesn't properly handle the "start on the right side of virtual screen" case
668 //Dunno why--looks Ok...
669 //What *is* for sure wrong is that it doesn't copy the linebuffer's BG pixels... [FIXED NOW]
670 //This should likely be 4 instead of 2 (?--not sure)
671 // Actually, there should be NO multiplier, as startPos is expressed in PIXELS
672 // and so is the backbuffer.
675 uint8 g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
676 uint32 pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
678 for(int16 i=0; i<startPos; i++)
679 *backbuffer++ = pixel;
684 backbuffer += 2 * startPos, width -= startPos;
689 uint16 color = (*current_line_buffer++) << 8;
690 color |= *current_line_buffer++;
691 *backbuffer++ = MIX16ToRGB32[color];
698 // 16 BPP CRY mode rendering
700 void tom_render_16bpp_cry_scanline(uint32 * backbuffer)
702 //CHANGED TO 32BPP RENDERING
703 uint16 width = tomWidth;
704 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
706 //New stuff--restrict our drawing...
707 uint8 pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
708 //NOTE: May have to check HDB2 as well!
709 int16 startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL);// Get start position in HC ticks
712 current_line_buffer += 2 * -startPos;
716 uint8 g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
717 uint32 pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
719 for(int16 i=0; i<startPos; i++)
720 *backbuffer++ = pixel;
725 //This should likely be 4 instead of 2 (?--not sure)
726 backbuffer += 2 * startPos, width -= startPos;
731 uint16 color = (*current_line_buffer++) << 8;
732 color |= *current_line_buffer++;
733 *backbuffer++ = CRY16ToRGB32[color];
740 // 24 BPP mode rendering
742 void tom_render_24bpp_scanline(uint32 * backbuffer)
744 //CHANGED TO 32BPP RENDERING
745 uint16 width = tomWidth;
746 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
748 //New stuff--restrict our drawing...
749 uint8 pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
750 //NOTE: May have to check HDB2 as well!
751 int16 startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL); // Get start position in HC ticks
754 current_line_buffer += 4 * -startPos;
758 uint8 g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
759 uint32 pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
761 for(int16 i=0; i<startPos; i++)
762 *backbuffer++ = pixel;
767 //This should likely be 4 instead of 2 (?--not sure)
768 backbuffer += 2 * startPos, width -= startPos;
773 uint32 g = *current_line_buffer++;
774 uint32 r = *current_line_buffer++;
775 current_line_buffer++;
776 uint32 b = *current_line_buffer++;
777 //hm. *backbuffer++ = 0xFF000000 | (b << 16) | (g << 8) | r;
778 *backbuffer++ = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
784 //Seems to me that this is NOT a valid mode--the JTRM seems to imply that you would need
785 //extra hardware outside of the Jaguar console to support this!
787 // 16 BPP direct mode rendering
789 void tom_render_16bpp_direct_scanline(uint32 * backbuffer)
791 uint16 width = tomWidth;
792 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
796 uint16 color = (*current_line_buffer++) << 8;
797 color |= *current_line_buffer++;
798 *backbuffer++ = color >> 1;
805 // 16 BPP RGB mode rendering
807 void tom_render_16bpp_rgb_scanline(uint32 * backbuffer)
809 //CHANGED TO 32BPP RENDERING
810 // 16 BPP RGB: 0-5 green, 6-10 blue, 11-15 red
812 uint16 width = tomWidth;
813 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
815 //New stuff--restrict our drawing...
816 uint8 pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
817 //NOTE: May have to check HDB2 as well!
818 int16 startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL); // Get start position in HC ticks
822 current_line_buffer += 2 * -startPos;
826 uint8 g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
827 uint32 pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
829 for(int16 i=0; i<startPos; i++)
830 *backbuffer++ = pixel;
835 //This should likely be 4 instead of 2 (?--not sure)
836 backbuffer += 2 * startPos, width -= startPos;
841 uint32 color = (*current_line_buffer++) << 8;
842 color |= *current_line_buffer++;
843 *backbuffer++ = RGB16ToRGB32[color];
850 // Process a single scanline
851 // (this is bad terminology; each tick of the VC is actually a half-line)
853 void TOMExecHalfline(uint16 halfline, bool render)
855 #warning "!!! Need to handle multiple fields properly !!!"
856 // We ignore the problem for now
859 bool inActiveDisplayArea = true;
861 //Interlacing is still not handled correctly here... !!! FIX !!!
862 if (halfline & 0x01) // Execute OP only on even halflines (non-interlaced only!)
865 //Hm, it seems that the OP needs to execute from zero, so let's try it:
866 // And it works! But need to do some optimizations in the OP to keep it from attempting
867 // to do a scanline render in the non-display area... [DONE]
868 //this seems to cause a regression in certain games, like rayman
869 //which means I have to dig thru the asic nets to see what's wrong...
871 No, the OP doesn't start until VDB, that much is certain. The thing is, VDB is the
872 HALF line that the OP starts on--which means that it needs to start at VDB / 2!!!
874 Hrm, doesn't seem to be enough, though it should be... still sticks for 20 frames.
877 What triggers this is writing $FFFF to VDE. This causes the OP start signal in VID to
878 latch on, which in effect sets VDB to zero. So that much is correct. But the thing with
879 Rayman is that it shouldn't cause the graphical glitches seen there, so still have to
880 investigate what's going on there. By all rights, it shouldn't glitch because:
882 00006C00: 0000000D 82008F73 (BRANCH) YPOS=494, CC=">", link=$00006C10
883 00006C08: 000003FF 00008173 (BRANCH) YPOS=46, CC=">", link=$001FF800
884 00006C10: 00000000 0000000C (STOP)
885 001FF800: 12FC2BFF 02380000 (BITMAP)
888 Even if the OP is running all the time, the link should tell it to stop at the right
889 place (which it seems to do). But we still get glitchy screen.
891 Seems the glitchy screen went away... Maybe the GPU alignment fixes fixed it???
892 Just need to add the proper checking here then.
894 Some numbers, courtesy of the Jaguar BIOS:
896 VP, 523 // Vertical Period (1-based; in this case VP = 524)
897 VBE, 24 // Vertical Blank End
898 VDB, 38 // Vertical Display Begin
899 VDE, 518 // Vertical Display End
900 VBB, 500 // Vertical Blank Begin
901 VS, 517 // Vertical Sync
904 VP, 623 // Vertical Period (1-based; in this case VP = 624)
905 VBE, 34 // Vertical Blank End
906 VDB, 38 // Vertical Display Begin
907 VDE, 518 // Vertical Display End
908 VBB, 600 // Vertical Blank Begin
909 VS, 618 // Vertical Sync
911 Numbers for KM, NTSC:
912 KM: (Note that with VDE <= 507, the OP starts at VDB as expected)
913 TOM: Vertical Display Begin written by M68K: 41
914 TOM: Vertical Display End written by M68K: 2047
915 TOM: Vertical Interrupt written by M68K: 491
918 // Initial values that "well behaved" programs use
919 uint16 startingHalfline = GET16(tomRam8, VDB);
920 uint16 endingHalfline = GET16(tomRam8, VDE);
922 // Simulate the OP start bug here!
923 // Really, this value is somewhere around 507 for an NTSC Jaguar. But this
924 // should work in a majority of cases, at least until we can figure it out properly.
925 if (endingHalfline > GET16(tomRam8, VP))
926 startingHalfline = 0;
928 if (halfline >= startingHalfline && halfline < endingHalfline)
929 // if (halfline >= 0 && halfline < (uint16)GET16(tomRam8, VDE))
930 // 16 isn't enough, and neither is 32 for raptgun. 32 fucks up Rayman
931 // if (halfline >= ((uint16)GET16(tomRam8, VDB) / 2) && halfline < ((uint16)GET16(tomRam8, VDE) / 2))
932 // if (halfline >= ((uint16)GET16(tomRam8, VDB) - 16) && halfline < (uint16)GET16(tomRam8, VDE))
933 // if (halfline >= 20 && halfline < (uint16)GET16(tomRam8, VDE))
934 // if (halfline >= (uint16)GET16(tomRam8, VDB) && halfline < (uint16)GET16(tomRam8, VDE))
938 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
939 uint8 bgHI = tomRam8[BG], bgLO = tomRam8[BG + 1];
941 // Clear line buffer with BG
942 if (GET16(tomRam8, VMODE) & BGEN) // && (CRY or RGB16)...
943 for(uint32 i=0; i<720; i++)
944 *current_line_buffer++ = bgHI, *current_line_buffer++ = bgLO;
946 OPProcessList(halfline, render);
950 inActiveDisplayArea = false;
952 inActiveDisplayArea =
953 (halfline >= (uint16)GET16(tomRam8, VDB) && halfline < (uint16)GET16(tomRam8, VDE)
956 if (halfline < (uint16)GET16(tomRam8, VDE))
958 if (render)//With JaguarExecuteNew() this is always true...
960 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
961 uint8 bgHI = tomRam8[BG], bgLO = tomRam8[BG + 1];
963 // Clear line buffer with BG
964 if (GET16(tomRam8, VMODE) & BGEN) // && (CRY or RGB16)...
965 for(uint32 i=0; i<720; i++)
966 *current_line_buffer++ = bgHI, *current_line_buffer++ = bgLO;
968 // OPProcessList(halfline, render);
969 //This seems to take care of it...
970 OPProcessList(halfline, inActiveDisplayArea);
975 // Try to take PAL into account... [We do now!]
977 uint16 topVisible = (vjs.hardwareTypeNTSC ? TOP_VISIBLE_VC : TOP_VISIBLE_VC_PAL),
978 bottomVisible = (vjs.hardwareTypeNTSC ? BOTTOM_VISIBLE_VC : BOTTOM_VISIBLE_VC_PAL);
979 uint32 * TOMCurrentLine = &(screenBuffer[((halfline - topVisible) / 2) * screenPitch]);
981 // Here's our virtualized scanline code...
983 if (halfline >= topVisible && halfline < bottomVisible)
985 if (inActiveDisplayArea)
987 //NOTE: The following doesn't put BORDER color on the sides... !!! FIX !!!
988 #warning "The following doesn't put BORDER color on the sides... !!! FIX !!!"
989 if (vjs.renderType == RT_NORMAL)
990 // scanline_render[TOMGetVideoMode()](TOMBackbuffer);
991 scanline_render[TOMGetVideoMode()](TOMCurrentLine);
995 tom_render_16bpp_cry_scanline,
996 tom_render_24bpp_scanline,
997 tom_render_16bpp_direct_scanline,
998 tom_render_16bpp_rgb_scanline,
999 tom_render_16bpp_cry_rgb_mix_scanline,
1000 tom_render_24bpp_scanline,
1001 tom_render_16bpp_direct_scanline,
1002 tom_render_16bpp_rgb_scanline
1004 #define MODE 0x0006 // Line buffer to video generator mode
1005 #define VARMOD 0x0100 // Mixed CRY/RGB16 mode (only works in MODE 0!)
1007 uint8 pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
1008 uint8 mode = ((GET16(tomRam8, VMODE) & MODE) >> 1);
1009 bool varmod = GET16(tomRam8, VMODE) & VARMOD;
1010 //The video texture line buffer ranges from 0 to 1279, with its left edge starting at
1011 //LEFT_VISIBLE_HC. So, we need to start writing into the backbuffer at HDB1, using pwidth
1012 //as our scaling factor. The way it generates its image on a real TV!
1014 //So, for example, if HDB1 is less than LEFT_VISIBLE_HC, then we have to figure out where
1015 //in the VTLB that we start writing pixels from the Jaguar line buffer (VTLB start=0,
1019 // 24 BPP mode rendering
1021 void tom_render_24bpp_scanline(uint32 * backbuffer)
1023 //CHANGED TO 32BPP RENDERING
1024 uint16 width = tomWidth;
1025 uint8 * current_line_buffer = (uint8 *)&tomRam8[0x1800];
1027 //New stuff--restrict our drawing...
1028 uint8 pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
1029 //NOTE: May have to check HDB2 as well!
1030 int16 startPos = GET16(tomRam8, HDB1) - (vjs.hardwareTypeNTSC ? LEFT_VISIBLE_HC : LEFT_VISIBLE_HC_PAL); // Get start position in HC ticks
1033 current_line_buffer += 4 * -startPos;
1035 //This should likely be 4 instead of 2 (?--not sure)
1036 backbuffer += 2 * startPos, width -= startPos;
1040 uint32 g = *current_line_buffer++;
1041 uint32 r = *current_line_buffer++;
1042 current_line_buffer++;
1043 uint32 b = *current_line_buffer++;
1044 *backbuffer++ = 0xFF000000 | (b << 16) | (g << 8) | r;
1054 // If outside of VDB & VDE, then display the border color
1055 uint32 * currentLineBuffer = TOMCurrentLine;
1056 uint8 g = tomRam8[BORD1], r = tomRam8[BORD1 + 1], b = tomRam8[BORD2 + 1];
1057 //Hm. uint32 pixel = 0xFF000000 | (b << 16) | (g << 8) | r;
1058 uint32 pixel = 0x000000FF | (r << 24) | (g << 16) | (b << 8);
1060 for(uint32 i=0; i<tomWidth; i++)
1061 *currentLineBuffer++ = pixel;
1068 // TOM initialization
1072 TOMFillLookupTables();
1083 WriteLog("TOM: Resolution %i x %i %s\n", TOMGetVideoModeWidth(), TOMGetVideoModeHeight(),
1084 videoMode_to_str[TOMGetVideoMode()]);
1085 // WriteLog("\ntom: object processor:\n");
1086 // WriteLog("tom: pointer to object list: 0x%.8x\n",op_get_list_pointer());
1087 // WriteLog("tom: INT1=0x%.2x%.2x\n",TOMReadByte(0xf000e0),TOMReadByte(0xf000e1));
1090 // memory_free(tomRam8);
1091 // memory_free(tom_cry_rgb_mix_lut);
1095 uint32 TOMGetVideoModeWidth(void)
1097 //These widths are pretty bogus. Should use HDB1/2 & HDE/HBB & PWIDTH to calc the width...
1098 // uint32 width[8] = { 1330, 665, 443, 332, 266, 222, 190, 166 };
1099 //Temporary, for testing Doom...
1100 // uint32 width[8] = { 1330, 665, 443, 332, 266, 222, 190, 332 };
1102 // Note that the following PWIDTH values have the following pixel aspect ratios:
1103 // PWIDTH = 1 -> 0.25:1 (1:4) pixels (X:Y ratio)
1104 // PWIDTH = 2 -> 0.50:1 (1:2) pixels
1105 // PWIDTH = 3 -> 0.75:1 (3:4) pixels
1106 // PWIDTH = 4 -> 1.00:1 (1:1) pixels
1107 // PWIDTH = 5 -> 1.25:1 (5:4) pixels
1108 // PWIDTH = 6 -> 1.50:1 (3:2) pixels
1109 // PWIDTH = 7 -> 1.75:1 (7:4) pixels
1110 // PWIDTH = 8 -> 2.00:1 (2:1) pixels
1112 // Also note that the JTRM says that PWIDTH of 4 gives pixels that are "about" square--
1113 // this implies that the other modes have pixels that are *not* square!
1114 // Also, I seriously doubt that you will see any games that use PWIDTH = 1!
1116 // NOTE: Even though the PWIDTH value is + 1, here we're using a zero-based index and
1117 // so we don't bother to add one...
1118 // return width[(GET16(tomRam8, VMODE) & PWIDTH) >> 9];
1120 // Now, we just calculate it...
1121 /* uint16 hdb1 = GET16(tomRam8, HDB1), hde = GET16(tomRam8, HDE),
1122 hbb = GET16(tomRam8, HBB), pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
1123 // return ((hbb < hde ? hbb : hde) - hdb1) / pwidth;
1124 //Temporary, for testing Doom...
1125 return ((hbb < hde ? hbb : hde) - hdb1) / (pwidth == 8 ? 4 : pwidth);*/
1127 // To make it easier to make a quasi-fixed display size, we restrict the viewing
1128 // area to an arbitrary range of the Horizontal Count.
1129 uint16 pwidth = ((GET16(tomRam8, VMODE) & PWIDTH) >> 9) + 1;
1130 return (vjs.hardwareTypeNTSC ? RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC : RIGHT_VISIBLE_HC_PAL - LEFT_VISIBLE_HC_PAL) / pwidth;
1131 //Temporary, for testing Doom...
1132 // return (RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC) / (pwidth == 8 ? 4 : pwidth);
1133 //// return (RIGHT_VISIBLE_HC - LEFT_VISIBLE_HC) / (pwidth == 4 ? 8 : pwidth);
1135 // More speculating...
1136 // According to the JTRM, the number of potential pixels across is given by the
1137 // Horizontal Period (HP - in NTSC this is 845). The Horizontal Count counts from
1138 // zero to this value twice per scanline (the high bit is set on the second count).
1139 // HBE and HBB define the absolute "black" limits of the screen, while HDB1/2 and
1140 // HDE determine the extent of the OP "on" time. I.e., when the OP is turned on by
1141 // HDB1, it starts fetching the line from position 0 in LBUF.
1143 // The trick, it would seem, is to figure out how long the typical visible scanline
1144 // of a TV is in HP ticks and limit the visible area to that (divided by PWIDTH, of
1145 // course). Using that length, we can establish an "absolute left display limit" with
1146 // which to measure HBB & HDB1/2 against when rendering LBUF (i.e., if HDB1 is 20 ticks
1147 // to the right of the ALDL and PWIDTH is 4, then start writing the LBUF starting at
1148 // backbuffer + 5 pixels).
1150 // That's basically what we're doing now...!
1154 // *** SPECULATION ***
1155 // It might work better to virtualize the height settings, i.e., set the vertical
1156 // height at 240 lines and clip using the VDB and VDE/VP registers...
1157 // Same with the width... [Width is pretty much virtualized now.]
1159 // Now that that the width is virtualized, let's virtualize the height. :-)
1160 uint32 TOMGetVideoModeHeight(void)
1162 // uint16 vmode = GET16(tomRam8, VMODE);
1163 // uint16 vbe = GET16(tomRam8, VBE);
1164 // uint16 vbb = GET16(tomRam8, VBB);
1165 // uint16 vdb = GET16(tomRam8, VDB);
1166 // uint16 vde = GET16(tomRam8, VDE);
1167 // uint16 vp = GET16(tomRam8, VP);
1169 /* if (vde == 0xFFFF)
1172 // return 227;//WAS:(vde/*-vdb*/) >> 1;
1173 // The video mode height probably works this way:
1174 // VC counts from 0 to VP. VDB starts the OP. Either when
1175 // VDE is reached or VP, the OP is stopped. Let's try it...
1176 // Also note that we're conveniently ignoring interlaced display modes...!
1177 // return ((vde > vp ? vp : vde) - vdb) >> 1;
1178 // return ((vde > vbb ? vbb : vde) - vdb) >> 1;
1179 //Let's try from the Vertical Blank interval...
1181 // return (vbb - vbe) >> 1; // Again, doesn't take interlacing into account...
1182 // This of course doesn't take interlacing into account. But I haven't seen any
1183 // Jaguar software that takes advantage of it either...
1184 //Also, doesn't reflect PAL Jaguar either... !!! FIX !!! [DONE]
1185 // return 240; // Set virtual screen height to 240 lines...
1186 return (vjs.hardwareTypeNTSC ? 240 : 256);
1192 // Now PAL friendly!
1195 The values in TOMReset come from the Jaguar BIOS.
1196 These values are from BJL:
1242 memset(tomRam8, 0x00, 0x4000);
1244 if (vjs.hardwareTypeNTSC)
1246 SET16(tomRam8, MEMCON1, 0x1861);
1247 SET16(tomRam8, MEMCON2, 0x35CC);
1248 SET16(tomRam8, HP, 844); // Horizontal Period (1-based; HP=845)
1249 SET16(tomRam8, HBB, 1713); // Horizontal Blank Begin
1250 SET16(tomRam8, HBE, 125); // Horizontal Blank End
1251 SET16(tomRam8, HDE, 1665); // Horizontal Display End
1252 SET16(tomRam8, HDB1, 203); // Horizontal Display Begin 1
1253 SET16(tomRam8, VP, 523); // Vertical Period (1-based; in this case VP = 524)
1254 SET16(tomRam8, VBE, 24); // Vertical Blank End
1255 SET16(tomRam8, VDB, 38); // Vertical Display Begin
1256 SET16(tomRam8, VDE, 518); // Vertical Display End
1257 SET16(tomRam8, VBB, 500); // Vertical Blank Begin
1258 SET16(tomRam8, VS, 517); // Vertical Sync
1259 SET16(tomRam8, VMODE, 0x06C1);
1263 SET16(tomRam8, MEMCON1, 0x1861);
1264 SET16(tomRam8, MEMCON2, 0x35CC);
1265 SET16(tomRam8, HP, 850); // Horizontal Period
1266 SET16(tomRam8, HBB, 1711); // Horizontal Blank Begin
1267 SET16(tomRam8, HBE, 158); // Horizontal Blank End
1268 SET16(tomRam8, HDE, 1665); // Horizontal Display End
1269 SET16(tomRam8, HDB1, 203); // Horizontal Display Begin 1
1270 SET16(tomRam8, VP, 623); // Vertical Period (1-based; in this case VP = 624)
1271 SET16(tomRam8, VBE, 34); // Vertical Blank End
1272 SET16(tomRam8, VDB, 38); // Vertical Display Begin
1273 SET16(tomRam8, VDE, 518); // Vertical Display End
1274 SET16(tomRam8, VBB, 600); // Vertical Blank Begin
1275 SET16(tomRam8, VS, 618); // Vertical Sync
1276 SET16(tomRam8, VMODE, 0x06C1);
1282 tom_jerry_int_pending = 0;
1283 tom_timer_int_pending = 0;
1284 tom_object_int_pending = 0;
1285 tom_gpu_int_pending = 0;
1286 tom_video_int_pending = 0;
1288 tomTimerPrescaler = 0; // TOM PIT is disabled
1289 tomTimerDivider = 0;
1290 tomTimerCounter = 0;
1295 // TOM byte access (read)
1297 uint8 TOMReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
1299 //???Is this needed???
1300 // It seems so. Perhaps it's the +$8000 offset being written to (32-bit interface)?
1301 // However, the 32-bit interface is WRITE ONLY, so that can't be it...
1302 // Also, the 68K CANNOT make use of the 32-bit interface, since its bus width is only 16-bits...
1303 // offset &= 0xFF3FFF;
1306 WriteLog("TOM: Reading byte at %06X for %s\n", offset, whoName[who]);
1309 if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
1310 return GPUReadByte(offset, who);
1311 else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
1312 return GPUReadByte(offset, who);
1313 /* else if ((offset >= 0xF00010) && (offset < 0xF00028))
1314 return OPReadByte(offset, who);*/
1315 else if ((offset >= 0xF02200) && (offset < 0xF022A0))
1316 return BlitterReadByte(offset, who);
1317 else if (offset == 0xF00050)
1318 return tomTimerPrescaler >> 8;
1319 else if (offset == 0xF00051)
1320 return tomTimerPrescaler & 0xFF;
1321 else if (offset == 0xF00052)
1322 return tomTimerDivider >> 8;
1323 else if (offset == 0xF00053)
1324 return tomTimerDivider & 0xFF;
1326 return tomRam8[offset & 0x3FFF];
1331 // TOM word access (read)
1333 uint16 TOMReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
1335 //???Is this needed???
1336 // offset &= 0xFF3FFF;
1338 WriteLog("TOM: Reading word at %06X for %s\n", offset, whoName[who]);
1340 if (offset >= 0xF02000 && offset <= 0xF020FF)
1341 WriteLog("TOM: ReadWord attempted from GPU register file by %s (unimplemented)!\n", whoName[who]);
1343 if (offset == 0xF000E0)
1345 // For reading, should only return the lower 5 bits...
1346 uint16 data = (tom_jerry_int_pending << 4) | (tom_timer_int_pending << 3)
1347 | (tom_object_int_pending << 2) | (tom_gpu_int_pending << 1)
1348 | (tom_video_int_pending << 0);
1349 //WriteLog("tom: interrupt status is 0x%.4x \n",data);
1352 //Shoud be handled by the jaguar main loop now... And it is! ;-)
1353 /* else if (offset == 0xF00006) // VC
1354 // What if we're in interlaced mode?
1355 // According to docs, in non-interlace mode VC is ALWAYS even...
1356 // return (tom_scanline << 1);// + 1;
1357 //But it's causing Rayman to be fucked up... Why???
1358 //Because VC is even in NI mode when calling the OP! That's why!
1359 return (tom_scanline << 1) + 1;//*/
1361 // F00004 R/W -----xxx xxxxxxxx HC - horizontal count
1362 // -----x-- -------- (which half of the display)
1363 // ------xx xxxxxxxx (10-bit counter)
1365 // This is a kludge to get the HC working somewhat... What we really should do here
1366 // is check what the global time is at the time of the read and calculate the correct HC...
1368 else if (offset == 0xF00004)
1369 return rand() & 0x03FF;
1370 else if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE + 0x20))
1371 return GPUReadWord(offset, who);
1372 else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE + 0x1000))
1373 return GPUReadWord(offset, who);
1374 /* else if ((offset >= 0xF00010) && (offset < 0xF00028))
1375 return OPReadWord(offset, who);*/
1376 else if ((offset >= 0xF02200) && (offset < 0xF022A0))
1377 return BlitterReadWord(offset, who);
1378 else if (offset == 0xF00050)
1379 return tomTimerPrescaler;
1380 else if (offset == 0xF00052)
1381 return tomTimerDivider;
1384 return (TOMReadByte(offset, who) << 8) | TOMReadByte(offset + 1, who);
1388 #define TOM_STRICT_MEMORY_ACCESS
1390 // TOM byte access (write)
1392 void TOMWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
1395 WriteLog("TOM: Writing byte %02X at %06X", data, offset);
1397 //???Is this needed???
1398 // Perhaps on the writes--32-bit writes that is! And masked with FF7FFF...
1399 #ifndef TOM_STRICT_MEMORY_ACCESS
1402 // "Fast" (32-bit only) write access to the GPU
1403 // if ((offset >= 0xF0A100) && (offset <= 0xF0BFFF))
1404 if ((offset >= 0xF08000) && (offset <= 0xF0BFFF))
1408 WriteLog(" -->[%06X] by %s\n", offset, whoName[who]);
1411 #ifdef TOM_STRICT_MEMORY_ACCESS
1412 // Sanity check ("Aww, there ain't no Sanity Clause...")
1413 if ((offset < 0xF00000) || (offset > 0xF03FFF))
1417 if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
1419 GPUWriteByte(offset, data, who);
1422 else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
1424 GPUWriteByte(offset, data, who);
1427 /* else if ((offset >= 0xF00010) && (offset < 0xF00028))
1429 OPWriteByte(offset, data, who);
1432 else if ((offset >= 0xF02200) && (offset < 0xF022A0))
1434 BlitterWriteByte(offset, data, who);
1437 else if (offset == 0xF00050)
1439 tomTimerPrescaler = (tomTimerPrescaler & 0x00FF) | (data << 8);
1443 else if (offset == 0xF00051)
1445 tomTimerPrescaler = (tomTimerPrescaler & 0xFF00) | data;
1449 else if (offset == 0xF00052)
1451 tomTimerDivider = (tomTimerDivider & 0x00FF) | (data << 8);
1455 else if (offset == 0xF00053)
1457 tomTimerDivider = (tomTimerDivider & 0xFF00) | data;
1461 else if (offset >= 0xF00400 && offset <= 0xF007FF) // CLUT (A & B)
1463 // Writing to one CLUT writes to the other
1464 offset &= 0x5FF; // Mask out $F00600 (restrict to $F00400-5FF)
1465 tomRam8[offset] = data, tomRam8[offset + 0x200] = data;
1468 tomRam8[offset & 0x3FFF] = data;
1473 // TOM word access (write)
1475 void TOMWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
1478 WriteLog("TOM: Writing byte %04X at %06X", data, offset);
1480 //???Is this needed??? Yes, but we need to be more vigilant than this.
1481 #ifndef TOM_STRICT_MEMORY_ACCESS
1484 // "Fast" (32-bit only) write access to the GPU
1485 // if ((offset >= 0xF0A100) && (offset <= 0xF0BFFF))
1486 if ((offset >= 0xF08000) && (offset <= 0xF0BFFF))
1490 WriteLog(" -->[%06X] by %s\n", offset, whoName[who]);
1493 #ifdef TOM_STRICT_MEMORY_ACCESS
1495 if ((offset < 0xF00000) || (offset > 0xF03FFF))
1499 //if (offset == 0xF00000 + MEMCON1)
1500 // WriteLog("TOM: Memory Configuration 1 written by %s: %04X\n", whoName[who], data);
1501 //if (offset == 0xF00000 + MEMCON2)
1502 // WriteLog("TOM: Memory Configuration 2 written by %s: %04X\n", whoName[who], data);
1503 if (offset >= 0xF02000 && offset <= 0xF020FF)
1504 WriteLog("TOM: WriteWord attempted to GPU register file by %s (unimplemented)!\n", whoName[who]);
1506 if ((offset >= GPU_CONTROL_RAM_BASE) && (offset < GPU_CONTROL_RAM_BASE+0x20))
1508 GPUWriteWord(offset, data, who);
1511 else if ((offset >= GPU_WORK_RAM_BASE) && (offset < GPU_WORK_RAM_BASE+0x1000))
1513 GPUWriteWord(offset, data, who);
1516 //What's so special about this?
1517 /* else if ((offset >= 0xF00000) && (offset < 0xF00002))
1519 TOMWriteByte(offset, data >> 8);
1520 TOMWriteByte(offset+1, data & 0xFF);
1522 /* else if ((offset >= 0xF00010) && (offset < 0xF00028))
1524 OPWriteWord(offset, data, who);
1527 else if (offset == 0xF00050)
1529 tomTimerPrescaler = data;
1533 else if (offset == 0xF00052)
1535 tomTimerDivider = data;
1539 else if (offset == 0xF000E0)
1543 tom_video_int_pending = 0;
1545 tom_gpu_int_pending = 0;
1547 tom_object_int_pending = 0;
1549 tom_timer_int_pending = 0;
1551 tom_jerry_int_pending = 0;
1555 else if ((offset >= 0xF02200) && (offset <= 0xF0229F))
1557 BlitterWriteWord(offset, data, who);
1560 else if (offset >= 0xF00400 && offset <= 0xF007FE) // CLUT (A & B)
1562 // Writing to one CLUT writes to the other
1563 offset &= 0x5FF; // Mask out $F00600 (restrict to $F00400-5FF)
1564 // Watch out for unaligned writes here! (Not fixed yet)
1565 #warning "!!! Watch out for unaligned writes here !!! FIX !!!"
1566 SET16(tomRam8, offset, data);
1567 SET16(tomRam8, offset + 0x200, data);
1571 if (offset == 0x28) // VMODE (Why? Why not OBF?)
1572 //Actually, we should check to see if the Enable bit of VMODE is set before doing this... !!! FIX !!!
1573 #warning "Actually, we should check to see if the Enable bit of VMODE is set before doing this... !!! FIX !!!"
1574 objectp_running = 1;
1576 if (offset >= 0x30 && offset <= 0x4E)
1577 data &= 0x07FF; // These are (mostly) 11-bit registers
1578 if (offset == 0x2E || offset == 0x36 || offset == 0x54)
1579 data &= 0x03FF; // These are all 10-bit registers
1581 // Fix a lockup bug... :-P
1582 TOMWriteByte(0xF00000 | offset, data >> 8, who);
1583 TOMWriteByte(0xF00000 | (offset+1), data & 0xFF, who);
1585 if (offset == MEMCON1)
1586 WriteLog("TOM: Memory Config 1 written by %s: $%04X\n", whoName[who], data);
1587 if (offset == MEMCON2)
1588 WriteLog("TOM: Memory Config 2 written by %s: $%04X\n", whoName[who], data);
1589 //if (offset == OLP)
1590 // WriteLog("TOM: Object List Pointer written by %s: $%04X\n", whoName[who], data);
1591 //if (offset == OLP + 2)
1592 // WriteLog("TOM: Object List Pointer +2 written by %s: $%04X\n", whoName[who], data);
1593 //if (offset == OBF)
1594 // WriteLog("TOM: Object Processor Flag written by %s: %u\n", whoName[who], data);
1595 if (offset == VMODE)
1596 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));
1597 if (offset == BORD1)
1598 WriteLog("TOM: Border 1 written by %s: $%04X\n", whoName[who], data);
1599 if (offset == BORD2)
1600 WriteLog("TOM: Border 2 written by %s: $%04X\n", whoName[who], data);
1602 WriteLog("TOM: Horizontal Period written by %s: %u (+1*2 = %u)\n", whoName[who], data, (data + 1) * 2);
1604 WriteLog("TOM: Horizontal Blank Begin written by %s: %u\n", whoName[who], data);
1606 WriteLog("TOM: Horizontal Blank End written by %s: %u\n", whoName[who], data);
1608 WriteLog("TOM: Horizontal Sync written by %s: %u\n", whoName[who], data);
1610 WriteLog("TOM: Horizontal Vertical Sync written by %s: %u\n", whoName[who], data);
1612 WriteLog("TOM: Horizontal Display Begin 1 written by %s: %u\n", whoName[who], data);
1614 WriteLog("TOM: Horizontal Display Begin 2 written by %s: %u\n", whoName[who], data);
1616 WriteLog("TOM: Horizontal Display End written by %s: %u\n", whoName[who], data);
1618 WriteLog("TOM: Vertical Period written by %s: %u (%sinterlaced)\n", whoName[who], data, (data & 0x01 ? "non-" : ""));
1620 WriteLog("TOM: Vertical Blank Begin written by %s: %u\n", whoName[who], data);
1622 WriteLog("TOM: Vertical Blank End written by %s: %u\n", whoName[who], data);
1624 WriteLog("TOM: Vertical Sync written by %s: %u\n", whoName[who], data);
1626 WriteLog("TOM: Vertical Display Begin written by %s: %u\n", whoName[who], data);
1628 WriteLog("TOM: Vertical Display End written by %s: %u\n", whoName[who], data);
1630 WriteLog("TOM: Vertical Equalization Begin written by %s: %u\n", whoName[who], data);
1632 WriteLog("TOM: Vertical Equalization End written by %s: %u\n", whoName[who], data);
1634 WriteLog("TOM: Vertical Interrupt written by %s: %u\n", whoName[who], data);
1636 WriteLog("TOM: PIT0 written by %s: %u\n", whoName[who], data);
1638 WriteLog("TOM: PIT1 written by %s: %u\n", whoName[who], data);
1640 WriteLog("TOM: Horizontal Equalization End written by %s: %u\n", whoName[who], data);
1642 // WriteLog("TOM: Background written by %s: %u\n", whoName[who], data);
1643 //if (offset == INT1)
1644 // 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" : ""));
1646 // detect screen resolution changes
1647 //This may go away in the future, if we do the virtualized screen thing...
1648 //This may go away soon!
1649 // TOM Shouldn't be mucking around with this, it's up to the host system to properly
1650 // handle this kind of crap.
1651 // NOTE: This is needed somehow, need to get rid of the dependency on this crap.
1652 #warning "!!! Need to get rid of this dependency !!!"
1654 if ((offset >= 0x28) && (offset <= 0x4F))
1656 uint32 width = TOMGetVideoModeWidth(), height = TOMGetVideoModeHeight();
1658 if ((width != tomWidth) || (height != tomHeight))
1660 tomWidth = width, tomHeight = height;
1662 #warning "!!! TOM: ResizeScreen commented out !!!"
1663 // No need to resize anything, since we're prepared for this...
1664 // if (vjs.renderType == RT_NORMAL)
1665 // ResizeScreen(tomWidth, tomHeight);
1672 int TOMIRQEnabled(int irq)
1674 // This is the correct byte in big endian... D'oh!
1675 // return jaguar_byte_read(0xF000E1) & (1 << irq);
1676 return tomRam8[INT1 + 1/*0xE1*/] & (1 << irq);
1681 // TOM Programmable Interrupt Timer handler
1682 // NOTE: TOM's PIT is only enabled if the prescaler is != 0
1683 // The PIT only generates an interrupt when it counts down to zero, not when loaded!
1685 void TOMPITCallback(void);
1688 void TOMResetPIT(void)
1690 #ifndef NEW_TIMER_SYSTEM
1691 //Probably should *add* this amount to the counter to retain cycle accuracy! !!! FIX !!! [DONE]
1692 //Also, why +1??? 'Cause that's what it says in the JTRM...!
1693 //There is a small problem with this approach: If both the prescaler and the divider are equal
1694 //to $FFFF then the counter won't be large enough to handle it. !!! FIX !!!
1695 if (tom_timer_prescaler)
1696 tom_timer_counter += (1 + tom_timer_prescaler) * (1 + tom_timer_divider);
1697 // WriteLog("tom: reseting timer to 0x%.8x (%i)\n",tom_timer_counter,tom_timer_counter);
1699 // Need to remove previous timer from the queue, if it exists...
1700 RemoveCallback(TOMPITCallback);
1702 if (tomTimerPrescaler)
1704 double usecs = (float)(tomTimerPrescaler + 1) * (float)(tomTimerDivider + 1) * RISC_CYCLE_IN_USEC;
1705 SetCallbackTime(TOMPITCallback, usecs);
1712 // TOM Programmable Interrupt Timer handler
1713 // NOTE: TOM's PIT is only enabled if the prescaler is != 0
1715 //NOTE: This is only used by the old execution code... Safe to remove
1716 // once the timer system is stable.
1717 void TOMExecPIT(uint32 cycles)
1719 if (tomTimerPrescaler)
1721 tomTimerCounter -= cycles;
1723 if (tomTimerCounter <= 0)
1725 TOMSetPendingTimerInt();
1726 GPUSetIRQLine(GPUIRQ_TIMER, ASSERT_LINE); // GPUSetIRQLine does the 'IRQ enabled' checking
1728 if (TOMIRQEnabled(IRQ_TIMER))
1729 m68k_set_irq(2); // Cause a 68000 IPL 2...
1737 void TOMPITCallback(void)
1739 // INT1_RREG |= 0x08; // Set TOM PIT interrupt pending
1740 TOMSetPendingTimerInt();
1741 GPUSetIRQLine(GPUIRQ_TIMER, ASSERT_LINE); // It does the 'IRQ enabled' checking
1743 // if (INT1_WREG & 0x08)
1744 if (TOMIRQEnabled(IRQ_TIMER))
1745 m68k_set_irq(2); // Generate a 68K IPL 2...