1 // license:BSD-3-Clause
2 // copyright-holders:David Haywood, Nicola Salmoria, Tomasz Slanina
3 #include "emu.h"
4 #include "includes/darkmist.h"
5 
6 
7 
8 /* vis. flags */
9 
10 #define DISPLAY_SPR     1
11 #define DISPLAY_FG      2 /* 2 or 8 */
12 #define DISPLAY_BG      4
13 #define DISPLAY_TXT     16
14 
15 
TILE_GET_INFO_MEMBER(darkmist_state::get_bgtile_info)16 TILE_GET_INFO_MEMBER(darkmist_state::get_bgtile_info)
17 {
18 	int code,attr,pal;
19 
20 	code=memregion("bg_map")->base()[tile_index*2]; /* TTTTTTTT */
21 	attr=memregion("bg_map")->base()[(tile_index*2)+1]; /* -PPP--TT - FIXED BITS (0xxx00xx) */
22 
23 	code+=(attr&3)<<8;
24 	pal=(attr>>4) & 0xf;
25 
26 	tileinfo.set(1,
27 		code,
28 		pal,
29 		0);
30 }
31 
TILE_GET_INFO_MEMBER(darkmist_state::get_fgtile_info)32 TILE_GET_INFO_MEMBER(darkmist_state::get_fgtile_info)
33 {
34 	int code,attr,pal;
35 
36 	code = memregion("fg_map")->base()[tile_index*2]; /* TTTTTTTT */
37 	attr = memregion("fg_map")->base()[(tile_index*2)+1]; /* -PPP--TT - FIXED BITS (0xxx00xx) */
38 
39 	code+=(attr&3)<<8;
40 	pal=(attr>>4) & 0xf;
41 
42 	tileinfo.set(2,
43 		code,
44 		pal,
45 		0);
46 }
47 
TILE_GET_INFO_MEMBER(darkmist_state::get_txttile_info)48 TILE_GET_INFO_MEMBER(darkmist_state::get_txttile_info)
49 {
50 	int code,attr,pal;
51 
52 	code=m_videoram[tile_index];
53 	attr=m_videoram[tile_index+0x400];
54 	pal=(attr>>1);
55 
56 	code+=(attr&1)<<8;
57 
58 	tileinfo.set(0,
59 		code,
60 		pal & 0xf,
61 		0);
62 }
63 
darkmist_palette(palette_device & palette) const64 void darkmist_state::darkmist_palette(palette_device &palette) const
65 {
66 	//palette.set_indirect_color(0x100, rgb_t::black());
67 
68 	std::pair<uint8_t const *, uint8_t> const planes[4]{
69 			{ &m_bg_clut[0], 0x80 },
70 			{ &m_fg_clut[0], 0x00 },
71 			{ &m_spr_clut[0], 0x40 },
72 			{ &m_tx_clut[0], 0xc0 } };
73 
74 	for (unsigned plane = 0; ARRAY_LENGTH(planes) > plane; ++plane)
75 	{
76 		for (unsigned i = 0; 0x100 > i; ++i)
77 		{
78 			uint8_t const clut = planes[plane].first[i];
79 //          if (clut & 0x40) // 0x40 indicates transparent pen
80 //              ctabentry = 0x100;
81 //          else
82 			int const ctabentry = (clut & 0x3f) | planes[plane].second;
83 			palette.set_pen_indirect((plane << 8) | i, ctabentry);
84 		}
85 	}
86 }
87 
88 
video_start()89 void darkmist_state::video_start()
90 {
91 	m_bgtilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(darkmist_state::get_bgtile_info)), TILEMAP_SCAN_ROWS, 16, 16, 512, 64);
92 	m_fgtilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(darkmist_state::get_fgtile_info)), TILEMAP_SCAN_ROWS, 16, 16, 64, 256);
93 	m_txtilemap = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(darkmist_state::get_txttile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
94 //  m_fgtilemap->set_transparent_pen(0);
95 //  m_txtilemap->set_transparent_pen(0);
96 
97 	save_item(NAME(m_hw));
98 	m_screen->register_screen_bitmap(m_temp_bitmap);
99 }
100 
101 // TODO: move this code into framework or substitute with a valid alternative
mix_layer(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect,uint8_t * clut)102 void darkmist_state::mix_layer(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, uint8_t* clut)
103 {
104 	for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
105 	{
106 		uint16_t *const dest = &bitmap.pix(y);
107 		uint16_t const *const src = &m_temp_bitmap.pix(y);
108 		for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
109 		{
110 			uint16_t const pix = (src[x] & 0xff);
111 			uint16_t const real = clut[pix];
112 
113 			if (!(real & 0x40))
114 				dest[x] = src[x];
115 		}
116 	}
117 }
118 
119 /*
120     Sprites
121 
122     76543210
123 0 - TTTT TTTT - tile
124 1 - xyBP PPP? - palette (P), flips (x,y), B - use spritebank,
125                 ? - unknown, according to gamecode top bit of one of coords(y/x)
126 2 - YYYY YYYY - y coord
127 3 - XXXX XXXX - x coord
128 
129 */
draw_sprites(bitmap_ind16 & bitmap,const rectangle & cliprect)130 void darkmist_state::draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
131 {
132 	int i,fx,fy,tile,palette;
133 	// fetch from top to bottom
134 	for(i=m_spriteram.bytes()-32;i>=0;i-=32)
135 	{
136 		fy=m_spriteram[i+1]&0x40;
137 		fx=m_spriteram[i+1]&0x80;
138 
139 		tile=m_spriteram[i+0];
140 
141 		if(m_spriteram[i+1]&0x20)
142 			tile += (*m_spritebank << 8);
143 
144 		palette=((m_spriteram[i+1])>>1)&0xf;
145 
146 		if(m_spriteram[i+1]&0x1)
147 			palette=machine().rand()&15;
148 
149 		m_gfxdecode->gfx(3)->transpen(
150 		bitmap,cliprect,
151 		tile,
152 		palette,
153 		fx,fy,
154 		m_spriteram[i+3],m_spriteram[i+2],0 );
155 	}
156 }
157 
screen_update(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)158 uint32_t darkmist_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
159 {
160 #define DM_GETSCROLL(n) (((m_scroll[(n)]<<1)&0xff) + ((m_scroll[(n)]&0x80)?1:0) +( ((m_scroll[(n)-1]<<4) | (m_scroll[(n)-1]<<12) )&0xff00))
161 
162 	m_bgtilemap->set_scrollx(0, DM_GETSCROLL(0x2));
163 	m_bgtilemap->set_scrolly(0, DM_GETSCROLL(0x6));
164 	m_fgtilemap->set_scrollx(0, DM_GETSCROLL(0xa));
165 	m_fgtilemap->set_scrolly(0, DM_GETSCROLL(0xe));
166 
167 	m_temp_bitmap.fill(0,cliprect);
168 	bitmap.fill(m_palette->black_pen(), cliprect);
169 
170 	if(m_hw & DISPLAY_BG)
171 	{
172 		m_bgtilemap->draw(screen, m_temp_bitmap, cliprect, 0,0);
173 		mix_layer(screen, bitmap, cliprect, m_bg_clut);
174 	}
175 
176 	if(m_hw & DISPLAY_FG)
177 	{
178 		m_fgtilemap->draw(screen, m_temp_bitmap, cliprect, 0,0);
179 		mix_layer(screen, bitmap, cliprect, m_fg_clut);
180 	}
181 
182 	if(m_hw & DISPLAY_SPR)
183 	{
184 		draw_sprites(m_temp_bitmap,cliprect);
185 		mix_layer(screen, bitmap, cliprect, m_spr_clut);
186 	}
187 
188 	if(m_hw & DISPLAY_TXT)
189 	{
190 		m_txtilemap->draw(screen, m_temp_bitmap, cliprect, 0,0);
191 		mix_layer(screen, bitmap, cliprect, m_tx_clut);
192 	}
193 
194 	return 0;
195 }
196 
tx_vram_w(offs_t offset,uint8_t data)197 void darkmist_state::tx_vram_w(offs_t offset, uint8_t data)
198 {
199 	m_videoram[offset] = data;
200 	m_txtilemap->mark_tile_dirty(offset & 0x3ff);
201 }
202