1
/***************************************************************************
5
Functions to emulate the video hardware of the machine.
7
***************************************************************************/
10
#include "includes/popeye.h"
12
static const size_t popeye_bitmapram_size = 0x2000;
14
enum { TYPE_SKYSKIPR, TYPE_POPEYE };
18
/***************************************************************************
20
Convert the color PROMs into a more useable format.
22
Popeye has four color PROMS:
24
- 32x8 background palette
25
- two 256x4 sprite palette
27
The char and sprite PROMs are connected to the RGB output this way:
29
bit 7 -- 220 ohm resistor -- BLUE (inverted)
30
-- 470 ohm resistor -- BLUE (inverted)
31
-- 220 ohm resistor -- GREEN (inverted)
32
-- 470 ohm resistor -- GREEN (inverted)
33
-- 1 kohm resistor -- GREEN (inverted)
34
-- 220 ohm resistor -- RED (inverted)
35
-- 470 ohm resistor -- RED (inverted)
36
bit 0 -- 1 kohm resistor -- RED (inverted)
38
The background PROM is connected to the RGB output this way:
40
bit 7 -- 470 ohm resistor -- BLUE (inverted)
41
-- 680 ohm resistor -- BLUE (inverted) (1300 ohm in Sky Skipper)
42
-- 470 ohm resistor -- GREEN (inverted)
43
-- 680 ohm resistor -- GREEN (inverted)
44
-- 1.2kohm resistor -- GREEN (inverted)
45
-- 470 ohm resistor -- RED (inverted)
46
-- 680 ohm resistor -- RED (inverted)
47
bit 0 -- 1.2kohm resistor -- RED (inverted)
49
The bootleg is the same, but the outputs are not inverted.
51
***************************************************************************/
52
static void convert_color_prom(running_machine &machine,const UINT8 *color_prom)
54
popeye_state *state = machine.driver_data<popeye_state>();
58
/* palette entries 0-15 are directly used by the background and changed at runtime */
62
for (i = 0;i < 16;i++)
64
int prom_offs = i | ((i & 8) << 1); /* address bits 3 and 4 are tied together */
65
int bit0,bit1,bit2,r,g,b;
68
bit0 = ((color_prom[prom_offs] ^ state->m_invertmask) >> 0) & 0x01;
69
bit1 = ((color_prom[prom_offs] ^ state->m_invertmask) >> 1) & 0x01;
70
bit2 = ((color_prom[prom_offs] ^ state->m_invertmask) >> 2) & 0x01;
71
r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
73
bit0 = ((color_prom[prom_offs] ^ state->m_invertmask) >> 3) & 0x01;
74
bit1 = ((color_prom[prom_offs] ^ state->m_invertmask) >> 4) & 0x01;
75
bit2 = ((color_prom[prom_offs] ^ state->m_invertmask) >> 5) & 0x01;
76
g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
79
bit1 = ((color_prom[prom_offs] ^ state->m_invertmask) >> 6) & 0x01;
80
bit2 = ((color_prom[prom_offs] ^ state->m_invertmask) >> 7) & 0x01;
81
b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
83
palette_set_color(machine,16 + (2 * i) + 1,MAKE_RGB(r,g,b));
89
for (i = 0;i < 256;i++)
91
int bit0,bit1,bit2,r,g,b;
95
bit0 = ((color_prom[0] ^ state->m_invertmask) >> 0) & 0x01;
96
bit1 = ((color_prom[0] ^ state->m_invertmask) >> 1) & 0x01;
97
bit2 = ((color_prom[0] ^ state->m_invertmask) >> 2) & 0x01;
98
r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
100
bit0 = ((color_prom[0] ^ state->m_invertmask) >> 3) & 0x01;
101
bit1 = ((color_prom[256] ^ state->m_invertmask) >> 0) & 0x01;
102
bit2 = ((color_prom[256] ^ state->m_invertmask) >> 1) & 0x01;
103
g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
106
bit1 = ((color_prom[256] ^ state->m_invertmask) >> 2) & 0x01;
107
bit2 = ((color_prom[256] ^ state->m_invertmask) >> 3) & 0x01;
108
b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
110
palette_set_color(machine,48+i,MAKE_RGB(r,g,b));
116
PALETTE_INIT( popeye )
118
popeye_state *state = machine.driver_data<popeye_state>();
119
state->m_invertmask = 0xff;
121
convert_color_prom(machine,color_prom);
124
PALETTE_INIT( popeyebl )
126
popeye_state *state = machine.driver_data<popeye_state>();
127
state->m_invertmask = 0x00;
129
convert_color_prom(machine,color_prom);
132
static void set_background_palette(running_machine &machine,int bank)
134
popeye_state *state = machine.driver_data<popeye_state>();
136
UINT8 *color_prom = machine.region("proms")->base() + 16 * bank;
138
for (i = 0;i < 16;i++)
144
bit0 = ((*color_prom ^ state->m_invertmask) >> 0) & 0x01;
145
bit1 = ((*color_prom ^ state->m_invertmask) >> 1) & 0x01;
146
bit2 = ((*color_prom ^ state->m_invertmask) >> 2) & 0x01;
147
r = 0x1c * bit0 + 0x31 * bit1 + 0x47 * bit2;
148
/* green component */
149
bit0 = ((*color_prom ^ state->m_invertmask) >> 3) & 0x01;
150
bit1 = ((*color_prom ^ state->m_invertmask) >> 4) & 0x01;
151
bit2 = ((*color_prom ^ state->m_invertmask) >> 5) & 0x01;
152
g = 0x1c * bit0 + 0x31 * bit1 + 0x47 * bit2;
155
bit1 = ((*color_prom ^ state->m_invertmask) >> 6) & 0x01;
156
bit2 = ((*color_prom ^ state->m_invertmask) >> 7) & 0x01;
157
if (state->m_bitmap_type == TYPE_SKYSKIPR)
159
/* Sky Skipper has different weights */
163
b = 0x1c * bit0 + 0x31 * bit1 + 0x47 * bit2;
165
palette_set_color(machine,i,MAKE_RGB(r,g,b));
171
WRITE8_HANDLER( popeye_videoram_w )
173
popeye_state *state = space->machine().driver_data<popeye_state>();
174
state->m_videoram[offset] = data;
175
tilemap_mark_tile_dirty(state->m_fg_tilemap, offset);
178
WRITE8_HANDLER( popeye_colorram_w )
180
popeye_state *state = space->machine().driver_data<popeye_state>();
181
state->m_colorram[offset] = data;
182
tilemap_mark_tile_dirty(state->m_fg_tilemap, offset);
185
WRITE8_HANDLER( popeye_bitmap_w )
187
popeye_state *state = space->machine().driver_data<popeye_state>();
188
int sx,sy,x,y,colour;
190
state->m_bitmapram[offset] = data;
192
if (state->m_bitmap_type == TYPE_SKYSKIPR)
194
sx = 8 * (offset % 128);
195
sy = 8 * (offset / 128);
197
if (flip_screen_get(space->machine()))
200
colour = data & 0x0f;
201
for (y = 0; y < 8; y++)
203
for (x = 0; x < 8; x++)
205
*BITMAP_ADDR16(state->m_tmpbitmap2, sy+y, sx+x) = colour;
211
sx = 8 * (offset % 64);
212
sy = 4 * (offset / 64);
214
if (flip_screen_get(space->machine()))
217
colour = data & 0x0f;
218
for (y = 0; y < 4; y++)
220
for (x = 0; x < 8; x++)
222
*BITMAP_ADDR16(state->m_tmpbitmap2, sy+y, sx+x) = colour;
228
WRITE8_HANDLER( skyskipr_bitmap_w )
230
offset = ((offset & 0xfc0) << 1) | (offset & 0x03f);
234
popeye_bitmap_w(space,offset,data);
237
static TILE_GET_INFO( get_fg_tile_info )
239
popeye_state *state = machine.driver_data<popeye_state>();
240
int code = state->m_videoram[tile_index];
241
int color = state->m_colorram[tile_index] & 0x0f;
243
SET_TILE_INFO(0, code, color, 0);
246
VIDEO_START( skyskipr )
248
popeye_state *state = machine.driver_data<popeye_state>();
249
state->m_bitmapram = auto_alloc_array(machine, UINT8, popeye_bitmapram_size);
250
state->m_tmpbitmap2 = auto_bitmap_alloc(machine,1024,1024,machine.primary_screen->format()); /* actually 1024x512 but not rolling over vertically? */
252
state->m_bitmap_type = TYPE_SKYSKIPR;
254
state->m_fg_tilemap = tilemap_create(machine, get_fg_tile_info, tilemap_scan_rows, 16, 16, 32, 32);
255
tilemap_set_transparent_pen(state->m_fg_tilemap, 0);
257
state->m_lastflip = 0;
259
state_save_register_global(machine, state->m_lastflip);
260
state_save_register_global_bitmap(machine, state->m_tmpbitmap2);
261
state_save_register_global_pointer(machine, state->m_bitmapram, popeye_bitmapram_size);
264
VIDEO_START( popeye )
266
popeye_state *state = machine.driver_data<popeye_state>();
267
state->m_bitmapram = auto_alloc_array(machine, UINT8, popeye_bitmapram_size);
268
state->m_tmpbitmap2 = auto_bitmap_alloc(machine,512,512,machine.primary_screen->format());
270
state->m_bitmap_type = TYPE_POPEYE;
272
state->m_fg_tilemap = tilemap_create(machine, get_fg_tile_info, tilemap_scan_rows, 16, 16, 32, 32);
273
tilemap_set_transparent_pen(state->m_fg_tilemap, 0);
275
state->m_lastflip = 0;
277
state_save_register_global(machine, state->m_lastflip);
278
state_save_register_global_bitmap(machine, state->m_tmpbitmap2);
279
state_save_register_global_pointer(machine, state->m_bitmapram, popeye_bitmapram_size);
282
static void draw_background(running_machine &machine, bitmap_t *bitmap, const rectangle *cliprect)
284
popeye_state *state = machine.driver_data<popeye_state>();
286
address_space *space = machine.device("maincpu")->memory().space(AS_PROGRAM);
288
if (state->m_lastflip != flip_screen_get(machine))
290
for (offs = 0;offs < popeye_bitmapram_size;offs++)
291
popeye_bitmap_w(space,offs,state->m_bitmapram[offs]);
293
state->m_lastflip = flip_screen_get(machine);
296
set_background_palette(machine, (*state->m_palettebank & 0x08) >> 3);
298
if (state->m_background_pos[1] == 0) /* no background */
299
bitmap_fill(bitmap,cliprect,0);
302
/* copy the background graphics */
303
int scrollx = 200 - state->m_background_pos[0] - 256*(state->m_background_pos[2]&1); /* ??? */
304
int scrolly = 2 * (256 - state->m_background_pos[1]);
306
if (state->m_bitmap_type == TYPE_SKYSKIPR)
307
scrollx = 2*scrollx - 512;
309
if (flip_screen_get(machine))
311
if (state->m_bitmap_type == TYPE_POPEYE)
316
copyscrollbitmap(bitmap,state->m_tmpbitmap2,1,&scrollx,1,&scrolly,cliprect);
320
static void draw_sprites(running_machine &machine, bitmap_t *bitmap, const rectangle *cliprect)
322
popeye_state *state = machine.driver_data<popeye_state>();
323
UINT8 *spriteram = state->m_spriteram;
326
for (offs = 0;offs < state->m_spriteram_size;offs += 4)
328
int code,color,flipx,flipy,sx,sy;
335
* bit 4 MSB of sprite code
336
* bit 3 vertical flip
338
* bit 1 \ color (with bit 2 as well)
342
code = (spriteram[offs + 2] & 0x7f) + ((spriteram[offs + 3] & 0x10) << 3)
343
+ ((spriteram[offs + 3] & 0x04) << 6);
344
color = (spriteram[offs + 3] & 0x07) + 8*(*state->m_palettebank & 0x07);
345
if (state->m_bitmap_type == TYPE_SKYSKIPR)
347
/* Two of the PROM address pins are tied together and one is not connected... */
348
color = (color & 0x0f) | ((color & 0x08) << 1);
351
flipx = spriteram[offs + 2] & 0x80;
352
flipy = spriteram[offs + 3] & 0x08;
354
sx = 2*(spriteram[offs])-8;
355
sy = 2*(256-spriteram[offs + 1]);
357
if (flip_screen_get(machine))
365
if (spriteram[offs] != 0)
366
drawgfx_transpen(bitmap,cliprect,machine.gfx[1],
374
SCREEN_UPDATE( popeye )
376
popeye_state *state = screen->machine().driver_data<popeye_state>();
377
draw_background(screen->machine(), bitmap, cliprect);
378
draw_sprites(screen->machine(), bitmap, cliprect);
379
tilemap_draw(bitmap, cliprect, state->m_fg_tilemap, 0, 0);