1 // license:BSD-3-Clause
2 // copyright-holders:R. Belmont
3 /*
4 Cristaltec "Game Cristal" (MAME bootleg)
5
6 Skeleton driver by R. Belmont, based on taitowlf.c by Ville Linde
7
8 Note:
9 - bp 000F16B5 do bx=0x16bb (can't skip this check?)
10
11 Specs: P3-866, SiS 630 graphics card, SiS 7018 sound, Windows 98, DirectX 8.1.
12
13 Input is via a custom COM1 port JAMMA adaptor.
14
15 The custom emulator is a heavily modified version of MAME32. If you extract the
16 disk image, it's in C:\GH4\GH4.EXE. It's UPX compressed, so unpack it before doing
17 any forensics. The emulator does run on Windows as new as XP Pro SP2 but you can't
18 control it due to the lack of the custom input.
19
20 Updates 27/11/2007 (Diego Nappino):
21 The COM1 port is opened at 19200 bps, No parity, 8 bit data,1 stop bit.
22 The protocol is based on a 6 bytes frame with a leading byte valued 0x05 and a trailing one at 0x02
23 The four middle bytes are used, in negative logic (0xFF = No button pressed), to implement the inputs.
24 Each bit meaning as follows :
25
26 Byte 1 Byte 2 Byte 3 Byte 4
27 Bit 0 P1-Credit P1-Button C P2-Left UNUSED
28 Bit 1 P1-Start P1-Button D P2-Right UNUSED
29 Bit 2 P1-Down P1-Button E P2-Button A SERVICE
30 Bit 3 P1-Up TEST P2-Button B UNUSED
31 Bit 4 P1-Left P2-Credit P2-Button C UNUSED
32 Bit 5 P1-Right P2-Start P2-Button D UNUSED
33 Bit 6 P1-Button A P2-Down P2-Button E UNUSED
34 Bit 7 P1-Button B P2-Up VIDEO-MODE UNUSED
35
36 The JAMMA adaptor sends a byte frame each time an input changes. So, in example, if the P1-Button A and P1-Button B are both pressed, it will send :
37
38 0x05 0xFC 0xFF 0xFF 0xFF 0x02
39
40 And when the buttons are both released
41
42 0x05 0xFF 0xFF 0xFF 0xFF 0x02
43
44 CPUID info:
45 Original set:
46
47 CPUID Level: EAX: EBX: ECX: EDX:
48 00000000 00000003 756E6547 6C65746E 49656E69
49 00000001 0000068A 00000002 00000000 0387F9FF
50 00000002 03020101 00000000 00000000 0C040882
51 00000003 00000000 00000000 CA976D2E 000082F6
52 80000000 00000000 00000000 CA976D2E 000082F6
53 C0000000 00000000 00000000 CA976D2E 000082F6
54
55
56 Version 2:
57 CPUID Level: EAX: EBX: ECX: EDX:
58 00000000 00000003 756E6547 6C65746E 49656E69
59 00000001 0000068A 00000002 00000000 0387F9FF
60 00000002 03020101 00000000 00000000 0C040882
61 00000003 00000000 00000000 B8BA1941 00038881
62 80000000 00000000 00000000 B8BA1941 00038881
63 C0000000 00000000 00000000 B8BA1941 00038881
64
65 */
66
67 #include "emu.h"
68 #include "cpu/i386/i386.h"
69 #include "machine/idectrl.h"
70 #include "machine/lpci.h"
71 #include "machine/pckeybrd.h"
72 #include "machine/pcshare.h"
73 #include "emupal.h"
74 #include "screen.h"
75
76
77 class gamecstl_state : public pcat_base_state
78 {
79 public:
gamecstl_state(const machine_config & mconfig,device_type type,const char * tag)80 gamecstl_state(const machine_config &mconfig, device_type type, const char *tag)
81 : pcat_base_state(mconfig, type, tag),
82 m_cga_ram(*this, "cga_ram"),
83 m_gfxdecode(*this, "gfxdecode"),
84 m_palette(*this, "palette") { }
85
86 void gamecstl(machine_config &config);
87
88 void init_gamecstl();
89
90 private:
91 required_shared_ptr<uint32_t> m_cga_ram;
92 required_device<gfxdecode_device> m_gfxdecode;
93 required_device<palette_device> m_palette;
94 std::unique_ptr<uint32_t[]> m_bios_ram;
95 uint8_t m_mtxc_config_reg[256];
96 uint8_t m_piix4_config_reg[4][256];
97
98 void pnp_config_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
99 void pnp_data_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
100 void bios_ram_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
101 virtual void machine_start() override;
102 virtual void machine_reset() override;
103 virtual void video_start() override;
104 uint32_t screen_update_gamecstl(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
105 void draw_char(bitmap_ind16 &bitmap, const rectangle &cliprect, gfx_element *gfx, int ch, int att, int x, int y);
106 void intel82439tx_init();
107 void gamecstl_io(address_map &map);
108 void gamecstl_map(address_map &map);
109
110 uint8_t mtxc_config_r(int function, int reg);
111 void mtxc_config_w(int function, int reg, uint8_t data);
112 uint32_t intel82439tx_pci_r(int function, int reg, uint32_t mem_mask);
113 void intel82439tx_pci_w(int function, int reg, uint32_t data, uint32_t mem_mask);
114 uint8_t piix4_config_r(int function, int reg);
115 void piix4_config_w(int function, int reg, uint8_t data);
116 uint32_t intel82371ab_pci_r(int function, int reg, uint32_t mem_mask);
117 void intel82371ab_pci_w(int function, int reg, uint32_t data, uint32_t mem_mask);
118 uint32_t pci_3dfx_r(int function, int reg, uint32_t mem_mask);
119 void pci_3dfx_w(int function, int reg, uint32_t data, uint32_t mem_mask);
120 };
121
122
123 static const rgb_t cga_palette[16] =
124 {
125 rgb_t( 0x00, 0x00, 0x00 ), rgb_t( 0x00, 0x00, 0xaa ), rgb_t( 0x00, 0xaa, 0x00 ), rgb_t( 0x00, 0xaa, 0xaa ),
126 rgb_t( 0xaa, 0x00, 0x00 ), rgb_t( 0xaa, 0x00, 0xaa ), rgb_t( 0xaa, 0x55, 0x00 ), rgb_t( 0xaa, 0xaa, 0xaa ),
127 rgb_t( 0x55, 0x55, 0x55 ), rgb_t( 0x55, 0x55, 0xff ), rgb_t( 0x55, 0xff, 0x55 ), rgb_t( 0x55, 0xff, 0xff ),
128 rgb_t( 0xff, 0x55, 0x55 ), rgb_t( 0xff, 0x55, 0xff ), rgb_t( 0xff, 0xff, 0x55 ), rgb_t( 0xff, 0xff, 0xff ),
129 };
130
video_start()131 void gamecstl_state::video_start()
132 {
133 int i;
134 for (i=0; i < 16; i++)
135 m_palette->set_pen_color(i, cga_palette[i]);
136 }
137
draw_char(bitmap_ind16 & bitmap,const rectangle & cliprect,gfx_element * gfx,int ch,int att,int x,int y)138 void gamecstl_state::draw_char(bitmap_ind16 &bitmap, const rectangle &cliprect, gfx_element *gfx, int ch, int att, int x, int y)
139 {
140 int index = 0;
141 uint8_t const *const dp = gfx->get_data(ch);
142
143 for (int j=y; j < y+8; j++)
144 {
145 uint16_t *const p = &bitmap.pix(j);
146
147 for (int i=x; i < x+8; i++)
148 {
149 uint8_t pen = dp[index++];
150 if (pen)
151 p[i] = gfx->colorbase() + (att & 0xf);
152 else
153 p[i] = gfx->colorbase() + ((att >> 4) & 0x7);
154 }
155 }
156 }
157
screen_update_gamecstl(screen_device & screen,bitmap_ind16 & bitmap,const rectangle & cliprect)158 uint32_t gamecstl_state::screen_update_gamecstl(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
159 {
160 gfx_element *gfx = m_gfxdecode->gfx(0);
161 uint32_t const *const cga = m_cga_ram;
162 int index = 0;
163
164 bitmap.fill(0, cliprect);
165
166 for (int j=0; j < 25; j++)
167 {
168 for (int i=0; i < 80; i+=2)
169 {
170 int att0 = (cga[index] >> 8) & 0xff;
171 int ch0 = (cga[index] >> 0) & 0xff;
172 int att1 = (cga[index] >> 24) & 0xff;
173 int ch1 = (cga[index] >> 16) & 0xff;
174
175 draw_char(bitmap, cliprect, gfx, ch0, att0, i*8, j*8);
176 draw_char(bitmap, cliprect, gfx, ch1, att1, (i*8)+8, j*8);
177 index++;
178 }
179 }
180 return 0;
181 }
182
183 // Intel 82439TX System Controller (MTXC)
184
mtxc_config_r(int function,int reg)185 uint8_t gamecstl_state::mtxc_config_r(int function, int reg)
186 {
187 logerror("MTXC: read %d, %02X\n", function, reg);
188 return m_mtxc_config_reg[reg];
189 }
190
mtxc_config_w(int function,int reg,uint8_t data)191 void gamecstl_state::mtxc_config_w(int function, int reg, uint8_t data)
192 {
193 logerror("%s:MTXC: write %d, %02X, %02X\n", machine().describe_context(), function, reg, data);
194
195 switch(reg)
196 {
197 case 0x59: // PAM0
198 {
199 if (data & 0x10) // enable RAM access to region 0xf0000 - 0xfffff
200 {
201 membank("bank1")->set_base(m_bios_ram.get());
202 }
203 else // disable RAM access (reads go to BIOS ROM)
204 {
205 membank("bank1")->set_base(memregion("bios")->base() + 0x30000);
206 }
207 break;
208 }
209 }
210
211 m_mtxc_config_reg[reg] = data;
212 }
213
intel82439tx_init()214 void gamecstl_state::intel82439tx_init()
215 {
216 m_mtxc_config_reg[0x60] = 0x02;
217 m_mtxc_config_reg[0x61] = 0x02;
218 m_mtxc_config_reg[0x62] = 0x02;
219 m_mtxc_config_reg[0x63] = 0x02;
220 m_mtxc_config_reg[0x64] = 0x02;
221 m_mtxc_config_reg[0x65] = 0x02;
222 }
223
intel82439tx_pci_r(int function,int reg,uint32_t mem_mask)224 uint32_t gamecstl_state::intel82439tx_pci_r(int function, int reg, uint32_t mem_mask)
225 {
226 uint32_t r = 0;
227 if (ACCESSING_BITS_24_31)
228 {
229 r |= mtxc_config_r(function, reg + 3) << 24;
230 }
231 if (ACCESSING_BITS_16_23)
232 {
233 r |= mtxc_config_r(function, reg + 2) << 16;
234 }
235 if (ACCESSING_BITS_8_15)
236 {
237 r |= mtxc_config_r(function, reg + 1) << 8;
238 }
239 if (ACCESSING_BITS_0_7)
240 {
241 r |= mtxc_config_r(function, reg + 0) << 0;
242 }
243 return r;
244 }
245
intel82439tx_pci_w(int function,int reg,uint32_t data,uint32_t mem_mask)246 void gamecstl_state::intel82439tx_pci_w(int function, int reg, uint32_t data, uint32_t mem_mask)
247 {
248 if (ACCESSING_BITS_24_31)
249 {
250 mtxc_config_w(function, reg + 3, (data >> 24) & 0xff);
251 }
252 if (ACCESSING_BITS_16_23)
253 {
254 mtxc_config_w(function, reg + 2, (data >> 16) & 0xff);
255 }
256 if (ACCESSING_BITS_8_15)
257 {
258 mtxc_config_w(function, reg + 1, (data >> 8) & 0xff);
259 }
260 if (ACCESSING_BITS_0_7)
261 {
262 mtxc_config_w(function, reg + 0, (data >> 0) & 0xff);
263 }
264 }
265
266 // Intel 82371AB PCI-to-ISA / IDE bridge (PIIX4)
267
piix4_config_r(int function,int reg)268 uint8_t gamecstl_state::piix4_config_r(int function, int reg)
269 {
270 logerror("PIIX4: read %d, %02X\n", function, reg);
271 return m_piix4_config_reg[function][reg];
272 }
273
piix4_config_w(int function,int reg,uint8_t data)274 void gamecstl_state::piix4_config_w(int function, int reg, uint8_t data)
275 {
276 logerror("%s:PIIX4: write %d, %02X, %02X\n", machine().describe_context(), function, reg, data);
277 m_piix4_config_reg[function][reg] = data;
278 }
279
intel82371ab_pci_r(int function,int reg,uint32_t mem_mask)280 uint32_t gamecstl_state::intel82371ab_pci_r(int function, int reg, uint32_t mem_mask)
281 {
282 uint32_t r = 0;
283 if (ACCESSING_BITS_24_31)
284 {
285 r |= piix4_config_r(function, reg + 3) << 24;
286 }
287 if (ACCESSING_BITS_16_23)
288 {
289 r |= piix4_config_r(function, reg + 2) << 16;
290 }
291 if (ACCESSING_BITS_8_15)
292 {
293 r |= piix4_config_r(function, reg + 1) << 8;
294 }
295 if (ACCESSING_BITS_0_7)
296 {
297 r |= piix4_config_r(function, reg + 0) << 0;
298 }
299 return r;
300 }
301
intel82371ab_pci_w(int function,int reg,uint32_t data,uint32_t mem_mask)302 void gamecstl_state::intel82371ab_pci_w(int function, int reg, uint32_t data, uint32_t mem_mask)
303 {
304 if (ACCESSING_BITS_24_31)
305 {
306 piix4_config_w(function, reg + 3, (data >> 24) & 0xff);
307 }
308 if (ACCESSING_BITS_16_23)
309 {
310 piix4_config_w(function, reg + 2, (data >> 16) & 0xff);
311 }
312 if (ACCESSING_BITS_8_15)
313 {
314 piix4_config_w(function, reg + 1, (data >> 8) & 0xff);
315 }
316 if (ACCESSING_BITS_0_7)
317 {
318 piix4_config_w(function, reg + 0, (data >> 0) & 0xff);
319 }
320 }
321
322 // ISA Plug-n-Play
pnp_config_w(offs_t offset,uint32_t data,uint32_t mem_mask)323 void gamecstl_state::pnp_config_w(offs_t offset, uint32_t data, uint32_t mem_mask)
324 {
325 if (ACCESSING_BITS_8_15)
326 {
327 // osd_printf_debug("PNP Config: %02X\n", (data >> 8) & 0xff);
328 }
329 }
330
pnp_data_w(offs_t offset,uint32_t data,uint32_t mem_mask)331 void gamecstl_state::pnp_data_w(offs_t offset, uint32_t data, uint32_t mem_mask)
332 {
333 if (ACCESSING_BITS_8_15)
334 {
335 // osd_printf_debug("PNP Data: %02X\n", (data >> 8) & 0xff);
336 }
337 }
338
339
340
bios_ram_w(offs_t offset,uint32_t data,uint32_t mem_mask)341 void gamecstl_state::bios_ram_w(offs_t offset, uint32_t data, uint32_t mem_mask)
342 {
343 if (m_mtxc_config_reg[0x59] & 0x20) // write to RAM if this region is write-enabled
344 {
345 COMBINE_DATA(m_bios_ram.get() + offset);
346 }
347 }
348
349 /*****************************************************************************/
350
gamecstl_map(address_map & map)351 void gamecstl_state::gamecstl_map(address_map &map)
352 {
353 map(0x00000000, 0x0009ffff).ram();
354 map(0x000a0000, 0x000affff).ram();
355 map(0x000b0000, 0x000b7fff).ram().share("cga_ram");
356 map(0x000e0000, 0x000effff).ram();
357 map(0x000f0000, 0x000fffff).bankr("bank1");
358 map(0x000f0000, 0x000fffff).w(FUNC(gamecstl_state::bios_ram_w));
359 map(0x00100000, 0x01ffffff).ram();
360 map(0xfffc0000, 0xffffffff).rom().region("bios", 0); /* System BIOS */
361 }
362
gamecstl_io(address_map & map)363 void gamecstl_state::gamecstl_io(address_map &map)
364 {
365 pcat32_io_common(map);
366 map(0x00e8, 0x00eb).noprw();
367 map(0x00ec, 0x00ef).noprw();
368 map(0x01f0, 0x01f7).rw("ide", FUNC(ide_controller_device::cs0_r), FUNC(ide_controller_device::cs0_w));
369 map(0x0300, 0x03af).noprw();
370 map(0x03b0, 0x03df).noprw();
371 map(0x0278, 0x027b).w(FUNC(gamecstl_state::pnp_config_w));
372 map(0x03f0, 0x03f7).rw("ide", FUNC(ide_controller_device::cs1_r), FUNC(ide_controller_device::cs1_w));
373 map(0x0a78, 0x0a7b).w(FUNC(gamecstl_state::pnp_data_w));
374 map(0x0cf8, 0x0cff).rw("pcibus", FUNC(pci_bus_legacy_device::read), FUNC(pci_bus_legacy_device::write));
375 }
376
377 /*****************************************************************************/
378
379 static const gfx_layout CGA_charlayout =
380 {
381 8,8, /* 8 x 16 characters */
382 256, /* 256 characters */
383 1, /* 1 bits per pixel */
384 { 0 }, /* no bitplanes; 1 bit per pixel */
385 /* x offsets */
386 { 0,1,2,3,4,5,6,7 },
387 /* y offsets */
388 { 0*8,1*8,2*8,3*8,
389 4*8,5*8,6*8,7*8 },
390 8*8 /* every char takes 8 bytes */
391 };
392
393 static GFXDECODE_START( gfx_cga )
394 /* Support up to four CGA fonts */
395 GFXDECODE_ENTRY( "gfx1", 0x0000, CGA_charlayout, 0, 256 ) /* Font 0 */
396 GFXDECODE_ENTRY( "gfx1", 0x0800, CGA_charlayout, 0, 256 ) /* Font 1 */
397 GFXDECODE_ENTRY( "gfx1", 0x1000, CGA_charlayout, 0, 256 ) /* Font 2 */
398 GFXDECODE_ENTRY( "gfx1", 0x1800, CGA_charlayout, 0, 256 ) /* Font 3*/
399 GFXDECODE_END
400
INPUT_PORTS_START(gamecstl)401 static INPUT_PORTS_START(gamecstl)
402 INPUT_PORTS_END
403
404 void gamecstl_state::machine_start()
405 {
406 }
407
machine_reset()408 void gamecstl_state::machine_reset()
409 {
410 membank("bank1")->set_base(memregion("bios")->base() + 0x30000);
411 }
412
gamecstl(machine_config & config)413 void gamecstl_state::gamecstl(machine_config &config)
414 {
415 /* basic machine hardware */
416 PENTIUM3(config, m_maincpu, 200000000);
417 m_maincpu->set_addrmap(AS_PROGRAM, &gamecstl_state::gamecstl_map);
418 m_maincpu->set_addrmap(AS_IO, &gamecstl_state::gamecstl_io);
419 m_maincpu->set_irq_acknowledge_callback("pic8259_1", FUNC(pic8259_device::inta_cb));
420
421 pcat_common(config);
422
423 pci_bus_legacy_device &pcibus(PCI_BUS_LEGACY(config, "pcibus", 0, 0));
424 pcibus.set_device(0, FUNC(gamecstl_state::intel82439tx_pci_r), FUNC(gamecstl_state::intel82439tx_pci_w));
425 pcibus.set_device(7, FUNC(gamecstl_state::intel82371ab_pci_r), FUNC(gamecstl_state::intel82371ab_pci_w));
426
427 ide_controller_device &ide(IDE_CONTROLLER(config, "ide").options(ata_devices, "hdd", nullptr, true));
428 ide.irq_handler().set("pic8259_2", FUNC(pic8259_device::ir6_w));
429
430 /* video hardware */
431 screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
432 screen.set_refresh_hz(60);
433 screen.set_vblank_time(ATTOSECONDS_IN_USEC(0));
434 screen.set_size(640, 480);
435 screen.set_visarea(0, 639, 0, 199);
436 screen.set_screen_update(FUNC(gamecstl_state::screen_update_gamecstl));
437 screen.set_palette(m_palette);
438
439 GFXDECODE(config, m_gfxdecode, m_palette, gfx_cga);
440 PALETTE(config, m_palette).set_entries(16);
441 }
442
init_gamecstl()443 void gamecstl_state::init_gamecstl()
444 {
445 m_bios_ram = std::make_unique<uint32_t[]>(0x10000/4);
446
447 intel82439tx_init();
448 }
449
450 /*****************************************************************************/
451
452 // not the correct BIOS, f205v owes me a dump of it...
453 ROM_START(gamecstl)
454 ROM_REGION32_LE(0x40000, "bios", 0)
455 ROM_LOAD( "bios.bin", 0x000000, 0x040000, BAD_DUMP CRC(27834ce9) SHA1(134c546dd75138c6f4bc5729b40e20e118454df9) )
456
457 ROM_REGION(0x08100, "gfx1", 0)
458 ROM_LOAD("cga.chr", 0x00000, 0x01000, BAD_DUMP CRC(42009069) SHA1(ed08559ce2d7f97f68b9f540bddad5b6295294dd))
459
460 DISK_REGION( "ide:0:hdd:image" )
461 DISK_IMAGE( "gamecstl", 0, SHA1(b431af3c42c48ba07972d77a3d24e60ee1e4359e) )
462 ROM_END
463
464 ROM_START(gamecst2)
465 ROM_REGION32_LE(0x40000, "bios", 0)
466 ROM_LOAD( "bios.bin", 0x000000, 0x040000, BAD_DUMP CRC(27834ce9) SHA1(134c546dd75138c6f4bc5729b40e20e118454df9) )
467
468 ROM_REGION(0x08100, "gfx1", 0)
469 ROM_LOAD("cga.chr", 0x00000, 0x01000, BAD_DUMP CRC(42009069) SHA1(ed08559ce2d7f97f68b9f540bddad5b6295294dd))
470
471 DISK_REGION( "ide:0:hdd:image" )
472 DISK_IMAGE( "gamecst2", 0, SHA1(14e1b311cb474801c7bdda3164a0c220fb102159) )
473 ROM_END
474
475 /*****************************************************************************/
476
477 GAME(2002, gamecstl, 0, gamecstl, gamecstl, gamecstl_state, init_gamecstl, ROT0, "Cristaltec", "GameCristal", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
478 GAME(2002, gamecst2, gamecstl, gamecstl, gamecstl, gamecstl_state, init_gamecstl, ROT0, "Cristaltec", "GameCristal (version 2.613)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND)
479