1
/***************************************************************************
3
P&P Marketing Police Trainer hardware
5
***************************************************************************/
8
#include "cpu/mips/r3000.h"
9
#include "includes/policetr.h"
13
#define SRCBITMAP_WIDTH 4096
15
#define DSTBITMAP_WIDTH 512
16
#define DSTBITMAP_HEIGHT 256
19
/*************************************
23
*************************************/
25
VIDEO_START( policetr )
27
policetr_state *state = machine.driver_data<policetr_state>();
28
/* the source bitmap is in ROM */
29
state->m_srcbitmap = machine.region("gfx1")->base();
31
/* compute the height */
32
state->m_srcbitmap_height_mask = (machine.region("gfx1")->bytes() / SRCBITMAP_WIDTH) - 1;
34
/* the destination bitmap is not directly accessible to the CPU */
35
state->m_dstbitmap = auto_alloc_array(machine, UINT8, DSTBITMAP_WIDTH * DSTBITMAP_HEIGHT);
40
/*************************************
42
* Display list processor
44
*************************************/
46
static void render_display_list(running_machine &machine, offs_t offset)
48
policetr_state *state = machine.driver_data<policetr_state>();
49
/* mask against the R3000 address space */
52
/* loop over all items */
53
while (offset != 0x1fffffff)
55
UINT32 *entry = &state->m_rambase[offset / 4];
56
UINT32 srcx = entry[0] & 0xfffffff;
57
UINT32 srcy = entry[1] & ((state->m_srcbitmap_height_mask << 16) | 0xffff);
58
UINT32 srcxstep = entry[2];
59
UINT32 srcystep = entry[3];
60
int dstw = (entry[4] & 0x1ff) + 1;
61
int dsth = ((entry[4] >> 12) & 0x1ff) + 1;
62
int dstx = entry[5] & 0x1ff;
63
int dsty = (entry[5] >> 12) & 0x1ff;
64
UINT8 mask = ~entry[6] >> 16;
65
UINT8 color = (entry[6] >> 24) & ~mask;
69
if (dstx > state->m_render_clip.max_x)
74
/* apply X clipping */
75
if (dstx < state->m_render_clip.min_x)
77
srcx += srcxstep * (state->m_render_clip.min_x - dstx);
78
dstw -= state->m_render_clip.min_x - dstx;
79
dstx = state->m_render_clip.min_x;
81
if (dstx + dstw > state->m_render_clip.max_x)
82
dstw = state->m_render_clip.max_x - dstx + 1;
84
/* apply Y clipping */
85
if (dsty < state->m_render_clip.min_y)
87
srcy += srcystep * (state->m_render_clip.min_y - dsty);
88
dsth -= state->m_render_clip.min_y - dsty;
89
dsty = state->m_render_clip.min_y;
91
if (dsty + dsth > state->m_render_clip.max_y)
92
dsth = state->m_render_clip.max_y - dsty + 1;
94
/* special case for fills */
95
if (srcxstep == 0 && srcystep == 0)
97
/* prefetch the pixel */
98
UINT8 pixel = state->m_srcbitmap[((srcy >> 16) * state->m_srcbitmap_height_mask) * SRCBITMAP_WIDTH + (srcx >> 16) % SRCBITMAP_WIDTH];
99
pixel = color | (pixel & mask);
101
/* loop over rows and columns */
103
for (y = 0; y < dsth; y++)
105
UINT8 *dst = &state->m_dstbitmap[(dsty + y) * DSTBITMAP_WIDTH + dstx];
106
memset(dst, pixel, dstw);
110
/* otherwise, standard render */
114
for (y = 0, cury = srcy; y < dsth; y++, cury += srcystep)
116
UINT8 *src = &state->m_srcbitmap[((cury >> 16) & state->m_srcbitmap_height_mask) * SRCBITMAP_WIDTH];
117
UINT8 *dst = &state->m_dstbitmap[(dsty + y) * DSTBITMAP_WIDTH + dstx];
119
/* loop over columns */
120
for (x = 0, curx = srcx; x < dstw; x++, curx += srcxstep)
122
UINT8 pixel = src[(curx >> 16) % SRCBITMAP_WIDTH];
124
dst[x] = color | (pixel & mask);
129
/* advance to the next link */
130
offset = entry[7] & 0x1fffffff;
136
/*************************************
138
* Video controller writes
140
*************************************/
142
WRITE32_HANDLER( policetr_video_w )
144
policetr_state *state = space->machine().driver_data<policetr_state>();
145
/* we assume 4-byte accesses */
147
logerror("%08X: policetr_video_w access with mask %08X\n", cpu_get_previouspc(&space->device()), mem_mask);
152
/* offset 0 specifies the start address of a display list */
154
render_display_list(space->machine(), data);
157
/* offset 1 specifies a latch value in the upper 8 bits */
159
state->m_video_latch = data >> 24;
162
/* offset 2 has various meanings based on the latch */
165
switch (state->m_video_latch)
167
/* latch 0x04 specifies the source X offset for a source bitmap pixel read */
169
state->m_src_xoffs = data >> 16;
172
/* latch 0x14 specifies the source Y offset for a source bitmap pixel read */
174
state->m_src_yoffs = data >> 16;
177
/* latch 0x20 specifies the top/left corners of the render cliprect */
179
state->m_render_clip.min_y = (data >> 12) & 0xfff;
180
state->m_render_clip.min_x = data & 0xfff;
183
/* latch 0x30 specifies the bottom/right corners of the render cliprect */
185
state->m_render_clip.max_y = (data >> 12) & 0xfff;
186
state->m_render_clip.max_x = data & 0xfff;
189
/* latch 0x50 allows a direct write to the destination bitmap */
191
if (ACCESSING_BITS_24_31 && state->m_dst_xoffs < DSTBITMAP_WIDTH && state->m_dst_yoffs < DSTBITMAP_HEIGHT)
192
state->m_dstbitmap[state->m_dst_yoffs * DSTBITMAP_WIDTH + state->m_dst_xoffs] = data >> 24;
195
/* log anything else */
197
logerror("%08X: policetr_video_w(2) = %08X & %08X with latch %02X\n", cpu_get_previouspc(&space->device()), data, mem_mask, state->m_video_latch);
203
/* offset 3 has various meanings based on the latch */
206
switch (state->m_video_latch)
208
/* latch 0x00 is unknown; 0, 1, and 2 get written into the upper 12 bits before rendering */
210
if (data != (0 << 20) && data != (1 << 20) && data != (2 << 20))
211
logerror("%08X: policetr_video_w(3) = %08X & %08X with latch %02X\n", cpu_get_previouspc(&space->device()), data, mem_mask, state->m_video_latch);
214
/* latch 0x10 specifies destination bitmap X and Y offsets */
216
state->m_dst_yoffs = (data >> 12) & 0xfff;
217
state->m_dst_xoffs = data & 0xfff;
220
/* latch 0x20 is unknown; either 0xef or 0x100 is written every IRQ4 */
222
if (data != (0x100 << 12) && data != (0xef << 12))
223
logerror("%08X: policetr_video_w(3) = %08X & %08X with latch %02X\n", cpu_get_previouspc(&space->device()), data, mem_mask, state->m_video_latch);
226
/* latch 0x40 is unknown; a 0 is written every IRQ4 */
229
logerror("%08X: policetr_video_w(3) = %08X & %08X with latch %02X\n", cpu_get_previouspc(&space->device()), data, mem_mask, state->m_video_latch);
232
/* latch 0x50 clears IRQ4 */
234
cputag_set_input_line(space->machine(), "maincpu", R3000_IRQ4, CLEAR_LINE);
237
/* latch 0x60 clears IRQ5 */
239
cputag_set_input_line(space->machine(), "maincpu", R3000_IRQ5, CLEAR_LINE);
242
/* log anything else */
244
logerror("%08X: policetr_video_w(3) = %08X & %08X with latch %02X\n", cpu_get_previouspc(&space->device()), data, mem_mask, state->m_video_latch);
254
/*************************************
256
* Video controller reads
258
*************************************/
260
READ32_HANDLER( policetr_video_r )
262
policetr_state *state = space->machine().driver_data<policetr_state>();
264
int width = space->machine().primary_screen->width();
265
int height = space->machine().primary_screen->height();
267
/* the value read is based on the latch */
268
switch (state->m_video_latch)
270
/* latch 0x00 is player 1's gun X coordinate */
272
inputval = ((input_port_read(space->machine(), "GUNX1") & 0xff) * width) >> 8;
274
return (inputval << 20) | 0x20000000;
276
/* latch 0x01 is player 1's gun Y coordinate */
278
inputval = ((input_port_read(space->machine(), "GUNY1") & 0xff) * height) >> 8;
280
return (inputval << 20);
282
/* latch 0x02 is player 2's gun X coordinate */
284
inputval = ((input_port_read(space->machine(), "GUNX2") & 0xff) * width) >> 8;
286
return (inputval << 20) | 0x20000000;
288
/* latch 0x03 is player 2's gun Y coordinate */
290
inputval = ((input_port_read(space->machine(), "GUNY2") & 0xff) * height) >> 8;
292
return (inputval << 20);
294
/* latch 0x04 is the pixel value in the ROM at the specified address */
296
return state->m_srcbitmap[(state->m_src_yoffs & state->m_srcbitmap_height_mask) * SRCBITMAP_WIDTH + state->m_src_xoffs % SRCBITMAP_WIDTH] << 24;
298
/* latch 0x50 is read at IRQ 4; the top 2 bits are checked. If they're not 0,
299
they skip the rest of the interrupt processing */
304
/* log anything else */
305
logerror("%08X: policetr_video_r with latch %02X\n", cpu_get_previouspc(&space->device()), state->m_video_latch);
312
/*************************************
316
*************************************/
318
WRITE32_HANDLER( policetr_palette_offset_w )
320
policetr_state *state = space->machine().driver_data<policetr_state>();
321
if (ACCESSING_BITS_16_23)
323
state->m_palette_offset = (data >> 16) & 0xff;
324
state->m_palette_index = 0;
329
WRITE32_HANDLER( policetr_palette_data_w )
331
policetr_state *state = space->machine().driver_data<policetr_state>();
332
if (ACCESSING_BITS_16_23)
334
state->m_palette_data[state->m_palette_index] = (data >> 16) & 0xff;
335
if (++state->m_palette_index == 3)
337
palette_set_color(space->machine(), state->m_palette_offset, MAKE_RGB(state->m_palette_data[0], state->m_palette_data[1], state->m_palette_data[2]));
338
state->m_palette_index = 0;
345
/*************************************
349
*************************************/
351
SCREEN_UPDATE( policetr )
353
policetr_state *state = screen->machine().driver_data<policetr_state>();
354
int width = cliprect->max_x - cliprect->min_x + 1;
357
/* render all the scanlines from the dstbitmap to MAME's bitmap */
358
for (y = cliprect->min_y; y <= cliprect->max_y; y++)
359
draw_scanline8(bitmap, cliprect->min_x, y, width, &state->m_dstbitmap[DSTBITMAP_WIDTH * y + cliprect->min_x], NULL);