1 // license:BSD-3-Clause
2 // copyright-holders:Brad Oliver
3 /***************************************************************************
4
5 video.c
6
7 Functions to emulate the video hardware of the machine.
8
9 ***************************************************************************/
10
11 #include "emu.h"
12 #include "includes/espial.h"
13
14 /***************************************************************************
15
16 Convert the color PROMs into a more useable format.
17
18 Espial has two 256x4 palette PROMs.
19
20 I don't know for sure how the palette PROMs are connected to the RGB
21 output, but it's probably the usual:
22
23 bit 3 -- 220 ohm resistor -- BLUE
24 -- 470 ohm resistor -- BLUE
25 -- 220 ohm resistor -- GREEN
26 bit 0 -- 470 ohm resistor -- GREEN
27 bit 3 -- 1 kohm resistor -- GREEN
28 -- 220 ohm resistor -- RED
29 -- 470 ohm resistor -- RED
30 bit 0 -- 1 kohm resistor -- RED
31
32 ***************************************************************************/
33
espial_palette(palette_device & palette) const34 void espial_state::espial_palette(palette_device &palette) const
35 {
36 uint8_t const *const color_prom = memregion("proms")->base();
37
38 for (int i = 0; i < palette.entries(); i++)
39 {
40 int bit0, bit1, bit2;
41
42 // red component
43 bit0 = BIT(color_prom[i], 0);
44 bit1 = BIT(color_prom[i], 1);
45 bit2 = BIT(color_prom[i], 2);
46 int const r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
47 // green component
48 bit0 = BIT(color_prom[i], 3);
49 bit1 = BIT(color_prom[i + palette.entries()], 0);
50 bit2 = BIT(color_prom[i + palette.entries()], 1);
51 int const g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
52 // blue component
53 bit0 = 0;
54 bit1 = BIT(color_prom[i + palette.entries()], 2);
55 bit2 = BIT(color_prom[i + palette.entries()], 3);
56 int const b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
57
58 palette.set_pen_color(i, rgb_t(r, g, b));
59 }
60 }
61
62
63
64 /***************************************************************************
65
66 Callbacks for the TileMap code
67
68 ***************************************************************************/
69
TILE_GET_INFO_MEMBER(espial_state::get_tile_info)70 TILE_GET_INFO_MEMBER(espial_state::get_tile_info)
71 {
72 uint8_t code = m_videoram[tile_index];
73 uint8_t col = m_colorram[tile_index];
74 uint8_t attr = m_attributeram[tile_index];
75 tileinfo.set(0,
76 code | ((attr & 0x03) << 8),
77 col & 0x3f,
78 TILE_FLIPYX(attr >> 2));
79 }
80
81
82
83 /*************************************
84 *
85 * Video system start
86 *
87 *************************************/
88
video_start()89 void espial_state::video_start()
90 {
91 m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(espial_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
92 m_bg_tilemap->set_scroll_cols(32);
93
94 save_item(NAME(m_flipscreen));
95 }
96
VIDEO_START_MEMBER(espial_state,netwars)97 VIDEO_START_MEMBER(espial_state,netwars)
98 {
99 /* Net Wars has a tile map that's twice as big as Espial's */
100 m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(espial_state::get_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 64);
101
102 m_bg_tilemap->set_scroll_cols(32);
103 m_bg_tilemap->set_scrolldy(0, 0x100);
104
105 save_item(NAME(m_flipscreen));
106 }
107
108
109 /*************************************
110 *
111 * Memory handlers
112 *
113 *************************************/
114
espial_videoram_w(offs_t offset,uint8_t data)115 void espial_state::espial_videoram_w(offs_t offset, uint8_t data)
116 {
117 m_videoram[offset] = data;
118 m_bg_tilemap->mark_tile_dirty(offset);
119 }
120
121
espial_colorram_w(offs_t offset,uint8_t data)122 void espial_state::espial_colorram_w(offs_t offset, uint8_t data)
123 {
124 m_colorram[offset] = data;
125 m_bg_tilemap->mark_tile_dirty(offset);
126 }
127
128
espial_attributeram_w(offs_t offset,uint8_t data)129 void espial_state::espial_attributeram_w(offs_t offset, uint8_t data)
130 {
131 m_attributeram[offset] = data;
132 m_bg_tilemap->mark_tile_dirty(offset);
133 }
134
135
espial_scrollram_w(offs_t offset,uint8_t data)136 void espial_state::espial_scrollram_w(offs_t offset, uint8_t data)
137 {
138 m_scrollram[offset] = data;
139 m_bg_tilemap->set_scrolly(offset, data);
140 }
141
142
espial_flipscreen_w(uint8_t data)143 void espial_state::espial_flipscreen_w(uint8_t data)
144 {
145 m_flipscreen = data;
146 m_bg_tilemap->set_flip(m_flipscreen ? TILEMAP_FLIPX | TILEMAP_FLIPY : 0);
147 }
148
149
150 /*************************************
151 *
152 * Video update
153 *
154 *************************************/
155
draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect)156 void espial_state::draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect )
157 {
158 int offs;
159
160 /* Note that it is important to draw them exactly in this */
161 /* order, to have the correct priorities. */
162 for (offs = 0; offs < 16; offs++)
163 {
164 int sx, sy, code, color, flipx, flipy;
165
166
167 sx = m_spriteram_1[offs + 16];
168 sy = m_spriteram_2[offs];
169 code = m_spriteram_1[offs] >> 1;
170 color = m_spriteram_2[offs + 16];
171 flipx = m_spriteram_3[offs] & 0x04;
172 flipy = m_spriteram_3[offs] & 0x08;
173
174 if (m_flipscreen)
175 {
176 flipx = !flipx;
177 flipy = !flipy;
178 }
179 else
180 {
181 sy = 240 - sy;
182 }
183
184 if (m_spriteram_1[offs] & 1) /* double height */
185 {
186 if (m_flipscreen)
187 {
188 m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
189 code,color,
190 flipx,flipy,
191 sx,sy + 16,0);
192 m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
193 code + 1,
194 color,
195 flipx,flipy,
196 sx,sy,0);
197 }
198 else
199 {
200 m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
201 code,color,
202 flipx,flipy,
203 sx,sy - 16,0);
204 m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
205 code + 1,color,
206 flipx,flipy,
207 sx,sy,0);
208 }
209 }
210 else
211 {
212 m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,
213 code,color,
214 flipx,flipy,
215 sx,sy,0);
216 }
217 }
218 }
219
220
screen_update_espial(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)221 uint32_t espial_state::screen_update_espial(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
222 {
223 m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
224 draw_sprites(bitmap, cliprect);
225 return 0;
226 }
227