1 // license:BSD-3-Clause
2 // copyright-holders:Nicola Salmoria
3 #include "emu.h"
4 #include "includes/gberet.h"
5 
6 
7 /***************************************************************************
8 
9   Convert the color PROMs into a more useable format.
10 
11   Green Beret has a 32 bytes palette PROM and two 256 bytes color lookup table
12   PROMs (one for sprites, one for characters).
13   The palette PROM is connected to the RGB output, this way:
14 
15   bit 7 -- 220 ohm resistor  -- BLUE
16         -- 470 ohm resistor  -- BLUE
17         -- 220 ohm resistor  -- GREEN
18         -- 470 ohm resistor  -- GREEN
19         -- 1  kohm resistor  -- GREEN
20         -- 220 ohm resistor  -- RED
21         -- 470 ohm resistor  -- RED
22   bit 0 -- 1  kohm resistor  -- RED
23 
24 ***************************************************************************/
25 
gberet_palette(palette_device & palette) const26 void gberet_state::gberet_palette(palette_device &palette) const
27 {
28 	uint8_t const *color_prom = memregion("proms")->base();
29 
30 	// create a lookup table for the palette
31 	for (int i = 0; i < 0x20; i++)
32 	{
33 		int bit0, bit1, bit2;
34 
35 		// red component
36 		bit0 = BIT(color_prom[i], 0);
37 		bit1 = BIT(color_prom[i], 1);
38 		bit2 = BIT(color_prom[i], 2);
39 		int const r = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
40 
41 		// green component
42 		bit0 = BIT(color_prom[i], 3);
43 		bit1 = BIT(color_prom[i], 4);
44 		bit2 = BIT(color_prom[i], 5);
45 		int const g = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
46 
47 		// blue component
48 		bit0 = 0;
49 		bit1 = BIT(color_prom[i], 6);
50 		bit2 = BIT(color_prom[i], 7);
51 		int const b = 0x21 * bit0 + 0x47 * bit1 + 0x97 * bit2;
52 
53 		palette.set_indirect_color(i, rgb_t(r, g, b));
54 	}
55 
56 	// color_prom now points to the beginning of the lookup table
57 	color_prom += 0x20;
58 
59 	for (int i = 0; i < 0x100; i++)
60 	{
61 		uint8_t const ctabentry = (color_prom[i] & 0x0f) | 0x10;
62 		palette.set_pen_indirect(i, ctabentry);
63 	}
64 
65 	for (int i = 0x100; i < 0x200; i++)
66 	{
67 		uint8_t const ctabentry = color_prom[i] & 0x0f;
68 		palette.set_pen_indirect(i, ctabentry);
69 	}
70 }
71 
gberet_videoram_w(offs_t offset,uint8_t data)72 void gberet_state::gberet_videoram_w(offs_t offset, uint8_t data)
73 {
74 	m_videoram[offset] = data;
75 	m_bg_tilemap->mark_tile_dirty(offset);
76 }
77 
gberet_colorram_w(offs_t offset,uint8_t data)78 void gberet_state::gberet_colorram_w(offs_t offset, uint8_t data)
79 {
80 	m_colorram[offset] = data;
81 	m_bg_tilemap->mark_tile_dirty(offset);
82 }
83 
gberet_scroll_w(offs_t offset,uint8_t data)84 void gberet_state::gberet_scroll_w(offs_t offset, uint8_t data)
85 {
86 	int scroll;
87 
88 	m_scrollram[offset] = data;
89 
90 	scroll = m_scrollram[offset & 0x1f] | (m_scrollram[offset | 0x20] << 8);
91 	m_bg_tilemap->set_scrollx(offset & 0x1f, scroll);
92 }
93 
gberet_sprite_bank_w(uint8_t data)94 void gberet_state::gberet_sprite_bank_w(uint8_t data)
95 {
96 	m_spritebank = data;
97 }
98 
TILE_GET_INFO_MEMBER(gberet_state::get_bg_tile_info)99 TILE_GET_INFO_MEMBER(gberet_state::get_bg_tile_info)
100 {
101 	int attr = m_colorram[tile_index];
102 	int code = m_videoram[tile_index] + ((attr & 0x40) << 2);
103 	int color = attr & 0x0f;
104 	int flags = TILE_FLIPYX((attr & 0x30) >> 4);
105 
106 	tileinfo.group = color;
107 	tileinfo.category = (attr & 0x80) >> 7;
108 
109 	tileinfo.set(0, code, color, flags);
110 }
111 
VIDEO_START_MEMBER(gberet_state,gberet)112 VIDEO_START_MEMBER(gberet_state,gberet)
113 {
114 	m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(gberet_state::get_bg_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
115 	m_bg_tilemap->configure_groups(*m_gfxdecode->gfx(0), 0x10);
116 	m_bg_tilemap->set_scroll_rows(32);
117 }
118 
gberet_draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect)119 void gberet_state::gberet_draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect )
120 {
121 	int offs;
122 	uint8_t *sr;
123 
124 	if (m_spritebank & 0x08)
125 		sr = m_spriteram2;
126 	else
127 		sr = m_spriteram;
128 
129 	for (offs = 0; offs < 0xc0; offs += 4)
130 	{
131 		if (sr[offs + 3])
132 		{
133 			int attr = sr[offs + 1];
134 			int code = sr[offs + 0] + ((attr & 0x40) << 2);
135 			int color = attr & 0x0f;
136 			int sx = sr[offs + 2] - 2 * (attr & 0x80);
137 			int sy = sr[offs + 3];
138 			int flipx = attr & 0x10;
139 			int flipy = attr & 0x20;
140 
141 			if (flip_screen())
142 			{
143 				sx = 240 - sx;
144 				sy = 240 - sy;
145 				flipx = !flipx;
146 				flipy = !flipy;
147 			}
148 
149 			m_gfxdecode->gfx(1)->transmask(bitmap,cliprect, code, color, flipx, flipy, sx, sy,
150 				m_palette->transpen_mask(*m_gfxdecode->gfx(1), color, 0));
151 		}
152 	}
153 }
154 
screen_update_gberet(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)155 uint32_t gberet_state::screen_update_gberet(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
156 {
157 	m_bg_tilemap->draw(screen, bitmap, cliprect, TILEMAP_DRAW_OPAQUE | TILEMAP_DRAW_ALL_CATEGORIES, 0);
158 	gberet_draw_sprites(bitmap, cliprect);
159 	m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
160 	return 0;
161 }
162 
163 /* Green Beret (bootleg) */
164 
gberetb_scroll_w(offs_t offset,uint8_t data)165 void gberet_state::gberetb_scroll_w(offs_t offset, uint8_t data)
166 {
167 	int scroll = data;
168 
169 	if (offset)
170 		scroll |= 0x100;
171 
172 	for (offset = 6; offset < 29; offset++)
173 		m_bg_tilemap->set_scrollx(offset, scroll + 64 - 8);
174 }
175 
gberetb_draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect)176 void gberet_state::gberetb_draw_sprites( bitmap_ind16 &bitmap, const rectangle &cliprect )
177 {
178 	uint8_t *spriteram = m_spriteram;
179 	int offs;
180 
181 	for (offs = m_spriteram.bytes() - 4; offs >= 0; offs -= 4)
182 	{
183 		if (spriteram[offs + 1])
184 		{
185 			int attr = spriteram[offs + 3];
186 			int code = spriteram[offs] + ((attr & 0x40) << 2);
187 			int color = attr & 0x0f;
188 			int sx = spriteram[offs + 2] - 2 * (attr & 0x80);
189 			int sy = 240 - spriteram[offs + 1];
190 			int flipx = attr & 0x10;
191 			int flipy = attr & 0x20;
192 
193 			if (flip_screen())
194 			{
195 				sx = 240 - sx;
196 				sy = 240 - sy;
197 				flipx = !flipx;
198 				flipy = !flipy;
199 			}
200 
201 			m_gfxdecode->gfx(1)->transmask(bitmap,cliprect, code, color, flipx, flipy, sx, sy,
202 				m_palette->transpen_mask(*m_gfxdecode->gfx(1), color, 0));
203 		}
204 	}
205 }
206 
screen_update_gberetb(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)207 uint32_t gberet_state::screen_update_gberetb(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
208 {
209 	m_bg_tilemap->draw(screen, bitmap, cliprect, TILEMAP_DRAW_OPAQUE | TILEMAP_DRAW_ALL_CATEGORIES, 0);
210 	gberetb_draw_sprites(bitmap, cliprect);
211 	m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
212 	return 0;
213 }
214