add driver for Soviet-Ukrainian games by Terminal (TIA-MC1 & kot) [iq_132, dink]

This commit is contained in:
dinkc64 2023-04-27 09:34:59 -04:00
parent cb7cb4e454
commit ba7529801b
4 changed files with 1243 additions and 2 deletions

View File

@ -69,7 +69,7 @@ drvsrc = d_akkaarrh.o d_arcadecl.o d_atarig1.o d_badlands.o d_batman.o d_blstro
d_qbert.o d_quizo.o d_rallyx.o d_redclash.o d_renegade.o d_quantum.o d_route16.o d_rpunch.o d_safarir.o d_sauro.o d_scregg.o d_seicross.o d_senjyo.o d_sf.o d_shangkid.o d_shisen.o \
d_sidearms.o d_skyarmy.o d_skyfox.o d_skykid.o d_snk.o d_snk6502.o d_snk68.o d_solomon.o d_sonson.o d_spacefb.o d_spdodgeb.o d_speedbal.o d_sprcros2.o \
d_srumbler.o d_ssozumo.o d_sstrangr.o d_starwars.o d_stfight.o d_stuntair.o d_sub.o d_suna8.o d_tagteam.o d_tankbust.o d_taxidriv.o d_tail2nose.o d_tbowl.o d_tceptor.o \
d_tecmo.o d_tempest.o d_terracre.o d_thedeep.o d_thepit.o d_thief.o d_tigeroad.o d_timelimt.o d_toki.o d_toypop.o d_travrusa.o d_tsamurai.o d_tubep.o d_usgames.o \
d_tecmo.o d_tempest.o d_terracre.o d_thedeep.o d_thepit.o d_thief.o d_tiamc1.o d_tigeroad.o d_timelimt.o d_toki.o d_toypop.o d_travrusa.o d_tsamurai.o d_tubep.o d_usgames.o \
d_vastar.o d_vball.o d_vicdual.o d_vulgus.o d_wallc.o d_warpwarp.o d_warpsped.o d_wc90.o d_wc90b.o d_williams.o d_wiping.o d_wiz.o d_wwfsstar.o \
d_xain.o d_xxmissio.o d_xyonix.o d_zaccaria.o d_zodiack.o d_zwackery.o \
\
@ -109,7 +109,7 @@ depobj = burn.o burn_bitmap.o burn_gun.o burn_led.o burn_shift.o burn_memory.o
asteroids.o ay8910.o burn_y8950.o burn_ym2151.o burn_ym2203.o burn_ym2413.o burn_ym2608.o burn_ym2610.o burn_ym2612.o burn_md2612.o \
burn_ym3526.o burn_ym3812.o burn_ymf262.o burn_ymf271.o burn_ymf278b.o bzone.o c6280.o dac.o digitalk.o es5506.o es8712.o exidy440_snd.o flower.o flt_rc.o fm.o fmopl.o ym2612.o gaelco.o hc55516.o \
i5000.o ics2115.o iremga20.o k005289.o k007232.o k051649.o k053260.o k054539.o llander.o mpeg_audio.o msm5205.o msm5232.o msm6295.o multipcm.o namco_snd.o c140.o c352.o nes_apu.o \
t6w28.o tms5110.o tms5220.o tms36xx.o phoenixsound.o pleiadssound.o pokey.o redbaron.o rf5c68.o s14001a.o saa1099.o samples.o segapcm.o sn76477.o sn76496.o \
t6w28.o tiamc1_snd.o tms5110.o tms5220.o tms36xx.o phoenixsound.o pleiadssound.o pokey.o redbaron.o rf5c68.o s14001a.o saa1099.o samples.o segapcm.o sn76477.o sn76496.o \
upd7759.o vlm5030.o wiping.o x1010.o ym2151.o ym2413.o ymdeltat.o ymf262.o ymf271.o ymf278b.o ymz280b.o ymz770.o snk6502_sound.o sp0250.o sp0256.o \
\
adsp2100.o adsp2100_intf.o arm7_intf.o arm_intf.o f8.o h6280_intf.o hd6309_intf.o konami_intf.o m6502_intf.o m6800_intf.o m6805_intf.o m6809_intf.o \

View File

@ -0,0 +1,845 @@
// FinalBurn Neo TIA-MC1 driver module
// Based on MAME driver by Eugene Sandulenko, w/special thanks to Shiru for his standalone emulator and documentation
#include "tiles_generic.h"
#include "z80_intf.h"
#include "8255ppi.h"
#include "burn_pal.h"
#include "tiamc1_snd.h"
static UINT8 *AllMem;
static UINT8 *AllRam;
static UINT8 *RamEnd;
static UINT8 *MemEnd;
static UINT8 *DrvI8080ROM;
static UINT8 *DrvSprROM;
static UINT8 *DrvTileROM;
static UINT8 *DrvI8080RAM;
static UINT8 *DrvTileRAM;
static UINT8 *DrvSprRAM;
static UINT8 *DrvCharRAM;
static UINT8 *DrvCharRAMExp;
static UINT32 *DrvPalette;
static UINT8 layer_control;
static INT32 character_bank;
static UINT8 scrollx;
static UINT8 scrolly;
static UINT8 bg_color;
static INT32 update_characters;
static INT32 update_colors;
static INT32 vblank;
static UINT32 button_config = 0;
static UINT8 DrvJoy1[8];
static UINT8 DrvJoy2[8];
static UINT8 DrvJoy3[8];
static UINT8 DrvInputs[3];
static UINT8 DrvReset;
static INT16 Analog[1];
static INT32 is_gorodki = 0;
static INT32 nExtraCycles;
static struct BurnInputInfo DrvInputList[] = {
{"P1 Coin", BIT_DIGITAL, DrvJoy3 + 4, "p1 coin" },
{"P1 Up", BIT_DIGITAL, DrvJoy2 + 1, "p1 up" },
{"P1 Down", BIT_DIGITAL, DrvJoy2 + 5, "p1 down" },
{"P1 Left", BIT_DIGITAL, DrvJoy1 + 5, "p1 left"} ,
{"P1 Right", BIT_DIGITAL, DrvJoy1 + 1, "p1 right" },
{"P1 Button 1", BIT_DIGITAL, DrvJoy3 + 5, "p1 fire 1" },
{"P1 Button 2", BIT_DIGITAL, DrvJoy3 + 6, "p1 fire 2" },
{"Reset", BIT_DIGITAL, &DrvReset, "reset" },
{"Service Mode", BIT_DIGITAL, DrvJoy2 + 7, "diag" },
};
STDINPUTINFO(Drv)
#define A(a, b, c, d) {a, b, (UINT8*)(c), d}
static struct BurnInputInfo GorodkiInputList[] = {
{"P1 Coin", BIT_DIGITAL, DrvJoy3 + 4, "p1 coin" },
A("P1 Stick X", BIT_ANALOG_REL, &Analog[0], "p1 x-axis"),
{"P1 Button 1", BIT_DIGITAL, DrvJoy3 + 5, "p1 fire 1" },
{"P1 Button 2", BIT_DIGITAL, DrvJoy3 + 6, "p1 fire 2" },
{"Reset", BIT_DIGITAL, &DrvReset, "reset" },
{"Service Mode", BIT_DIGITAL, DrvJoy2 + 7, "diag" },
};
#undef A
STDINPUTINFO(Gorodki)
static void __fastcall tiamc1_videoram_write(UINT16 address, UINT8 data)
{
if ((address & 0x0800) == 0x0000) // b000-b7ff (tiamc1) f000-f3ff (kot)
{
INT32 offs = address & 0x7ff;
if (layer_control & 0x1e) { update_characters = 1; }
if (layer_control & 0x01) DrvTileRAM[offs | 0x0000] = data;
if (layer_control & 0x02) DrvCharRAM[offs | 0x0000] = data;
if (layer_control & 0x04) DrvCharRAM[offs | 0x0800] = data;
if (layer_control & 0x08) DrvCharRAM[offs | 0x1000] = data;
if (layer_control & 0x10) DrvCharRAM[offs | 0x1800] = data;
}
}
static void __fastcall tiamc1_write_port(UINT16 port, UINT8 data)
{
switch (port & 0xf0)
{
case 0x40:
case 0x50:
case 0x60:
case 0x70:
DrvSprRAM[port & 0x3f] = ~data;
return;
case 0xc0:
if ((port & 0x0f) < 4) tiamc1_sound_timer0_write(port & 3, data);
return;
case 0xd0:
switch (port & 0x0c)
{
case 0x00:
ppi8255_w(0, port & 3, data);
return;
case 0x04:
tiamc1_sound_timer1_write(port & 3, data);
return;
case 0x08: // actually A
tiamc1_sound_gate_write(data);
return;
}
return;
case 0xa0:
BurnPalRAM[port & 0xf] = data;
update_colors = 1;
return;
case 0xb0:
{
switch (port & 0x0f)
{
case 0x0c:
scrolly = data;
return;
case 0x0d:
scrollx = data;
return;
case 0x0e:
layer_control = data ^ 0x1f;
return;
case 0x0f:
bg_color = ((data >> 0) & 1) | ((data >> 1) & 2) | ((data >> 2) & 4) | ((data >> 3) & 8);
update_colors = 1;
return;
}
}
return;
}
}
static UINT8 __fastcall tiamc1_read_port(UINT16 port)
{
switch (port & 0xfc)
{
case 0xd0:
return ppi8255_r(0, port & 3);
}
return 0;
}
static void __fastcall kot_write_port(UINT16 port, UINT8 data)
{
switch (port & 0xf0)
{
case 0x00:
case 0x10:
case 0x20:
case 0x30:
DrvSprRAM[port & 0x3f] = ~data;
return;
case 0xc0:
if ((port & 0x0f) < 4) tiamc1_sound_timer0_write(port & 3, data);
return;
case 0xd0:
if ((port & 0x0f) < 4) ppi8255_w(0, port & 3, data);
return;
case 0xe0:
BurnPalRAM[port & 0xf] = data;
update_colors = 1;
return;
case 0xf0:
{
switch (port & 0x0f)
{
case 0x00:
scrolly = data;
return;
case 0x04:
scrollx = data;
return;
case 0x08:
layer_control = (data ^ 1) & 1; // kot != tiamc1
character_bank = (data >> 1) << 5;
return;
}
}
return;
}
}
static UINT8 __fastcall kot_read_port(UINT16 port)
{
switch (port & 0xfc)
{
case 0xc0: // pit8253
return 0xff;
case 0xd0:
return ppi8255_r(0, port & 3);
}
return 0;
}
static UINT8 ppi_port_A_read()
{
return DrvInputs[0];
}
static UINT8 ppi_port_B_read()
{
return DrvInputs[1];
}
static UINT8 ppi_port_C_read()
{
return (DrvInputs[2] & 0x7f) | (vblank ? 0x80 : 0);
}
static tilemap_callback( bg )
{
TILE_SET_INFO(0, DrvTileRAM[offs | ((layer_control & 0x80) << 3)] + character_bank, 0, 0);
}
static INT32 DrvDoReset()
{
memset (AllRam, 0, RamEnd - AllRam);
ZetOpen(0);
ZetReset();
ZetClose();
ppi8255_reset();
layer_control = 0;
character_bank = 0;
scrollx = 0;
scrolly = 0;
bg_color = 0;
update_characters = 0;
update_colors = 0;
nExtraCycles = 0;
return 0;
}
static INT32 MemIndex()
{
UINT8 *Next; Next = AllMem;
DrvI8080ROM = Next; Next += 0x010000;
DrvTileROM = Next; Next += 0x010000;
DrvSprROM = Next; Next += 0x010000;
DrvPalette = (UINT32*)Next; Next += 0x0100 * sizeof(UINT32);
BurnPalette = (UINT32*)Next; Next += 0x0020 * sizeof(UINT32);
AllRam = Next;
DrvI8080RAM = Next; Next += 0x002000;
DrvTileRAM = Next; Next += 0x000800;
DrvSprRAM = Next; Next += 0x000040;
DrvCharRAM = Next; Next += 0x002000;
BurnPalRAM = Next; Next += 0x000010;
RamEnd = Next;
DrvCharRAMExp = Next; Next += 0x004000;
MemEnd = Next;
return 0;
}
static void DrvGfxDecode()
{
INT32 Planes[4] = { STEP4(0x10000*3,-0x10000) };
INT32 XOffs[16] = { STEP8(0,1), STEP8(0x8000,1) };
INT32 YOffs[16] = { STEP16(0,8) };
UINT8 *tmp = (UINT8*)BurnMalloc(0x8000);
if (tmp == NULL) {
return;
}
memcpy (tmp, DrvTileROM, 0x8000);
GfxDecode(0x0400, 4, 8, 8, Planes, XOffs, YOffs, 0x40, tmp, DrvTileROM);
memcpy (tmp, DrvSprROM, 0x8000);
GfxDecode(0x0100, 4, 16, 16, Planes, XOffs, YOffs, 0x80, tmp, DrvSprROM);
BurnFree (tmp);
}
static void DrvPaletteInit()
{
static float g_v[8] = { 1.2071F, 0.9971F, 0.9259F, 0.7159F, 0.4912F, 0.2812F, 0.2100F, 0.0000F };
static float r_v[8] = { 1.5937F, 1.3125F, 1.1562F, 0.8750F, 0.7187F, 0.4375F, 0.2812F, 0.0000F };
static float b_v[4] = { 1.3523F, 0.8750F, 0.4773F, 0.0000F };
for (INT32 col = 0; col < 256; col++)
{
INT32 ir = (col >> 3) & 7;
INT32 ig = col & 7;
INT32 ib = (col >> 6) & 3;
float tcol = 255.0f * r_v[ir] / r_v[0];
INT32 r = 255 - (int(tcol) & 255);
tcol = 255.0f * g_v[ig] / g_v[0];
INT32 g = 255 - (int(tcol) & 255);
tcol = 255.0f * b_v[ib] / b_v[0];
INT32 b = 255 - (int(tcol) & 255);
DrvPalette[col] = (r << 16) | (g << 8) | b;
}
}
static INT32 DrvInit(INT32 romcount)
{
BurnAllocMemIndex();
{
INT32 k = 0;
if (romcount == 6)
{
if (BurnLoadRom(DrvI8080ROM + 0x00000, k++, 1)) return 1;
if (BurnLoadRom(DrvI8080ROM + 0x02000, k++, 1)) return 1;
if (BurnLoadRom(DrvI8080ROM + 0x04000, k++, 1)) return 1;
if (BurnLoadRom(DrvI8080ROM + 0x06000, k++, 1)) return 1;
if (BurnLoadRom(DrvI8080ROM + 0x08000, k++, 1)) return 1;
if (BurnLoadRom(DrvI8080ROM + 0x0c000, k++, 1)) return 1;
}
else if (romcount == 4)
{
if (BurnLoadRom(DrvI8080ROM + 0x00000, k++, 1)) return 1;
if (BurnLoadRom(DrvI8080ROM + 0x02000, k++, 1)) return 1;
if (BurnLoadRom(DrvI8080ROM + 0x04000, k++, 1)) return 1;
if (BurnLoadRom(DrvI8080ROM + 0x06000, k++, 1)) return 1;
}
else if (romcount == 3)
{
if (BurnLoadRom(DrvI8080ROM + 0x00000, k++, 1)) return 1;
if (BurnLoadRom(DrvI8080ROM + 0x02000, k++, 1)) return 1;
if (BurnLoadRom(DrvI8080ROM + 0x0c000, k++, 1)) return 1;
}
if (BurnLoadRom(DrvSprROM + 0x00000, k++, 1)) return 1;
if (BurnLoadRom(DrvSprROM + 0x02000, k++, 1)) return 1;
if (BurnLoadRom(DrvSprROM + 0x04000, k++, 1)) return 1;
if (BurnLoadRom(DrvSprROM + 0x06000, k++, 1)) return 1;
DrvGfxDecode();
DrvPaletteInit();
}
ZetInit(0); // i8080
ZetOpen(0);
ZetMapMemory(DrvI8080ROM, 0x0000, 0xdfff, MAP_ROM);
ZetMapMemory(DrvI8080RAM, 0xe000, 0xffff, MAP_RAM);
ZetSetWriteHandler(tiamc1_videoram_write);
ZetSetOutHandler(tiamc1_write_port);
ZetSetInHandler(tiamc1_read_port);
ZetClose();
ppi8255_init(1);
ppi8255_set_read_ports(0, ppi_port_A_read, ppi_port_B_read, ppi_port_C_read);
// write C = coin counter
tiamc1_sound_init();
GenericTilesInit();
GenericTilemapInit(0, TILEMAP_SCAN_ROWS, bg_map_callback, 8, 8, 32, 32);
GenericTilesSetGfx(0, DrvCharRAMExp, 4, 8, 8, 0x004000, 0x10, 0x0f);
GenericTilesSetGfx(1, DrvSprROM, 4, 16, 16, 0x010000, 0x00, 0x0f);
GenericTilemapSetOffsets(0, 4, 0);
button_config = 0x0a0000;
DrvDoReset();
return 0;
}
static INT32 KotInit()
{
BurnAllocMemIndex();
{
INT32 k = 0;
if (BurnLoadRom(DrvI8080ROM + 0x00000, k++, 1)) return 1;
if (BurnLoadRom(DrvI8080ROM + 0x02000, k++, 1)) return 1;
if (BurnLoadRom(DrvI8080ROM + 0x04000, k++, 1)) return 1;
if (BurnLoadRom(DrvSprROM + 0x00000, k++, 1)) return 1;
if (BurnLoadRom(DrvSprROM + 0x02000, k++, 1)) return 1;
if (BurnLoadRom(DrvSprROM + 0x04000, k++, 1)) return 1;
if (BurnLoadRom(DrvSprROM + 0x06000, k++, 1)) return 1;
if (BurnLoadRom(DrvTileROM + 0x00000, k++, 1)) return 1;
if (BurnLoadRom(DrvTileROM + 0x02000, k++, 1)) return 1;
if (BurnLoadRom(DrvTileROM + 0x04000, k++, 1)) return 1;
if (BurnLoadRom(DrvTileROM + 0x06000, k++, 1)) return 1;
DrvGfxDecode();
DrvPaletteInit();
}
ZetInit(0); // i8080
ZetOpen(0);
ZetMapMemory(DrvI8080ROM, 0x0000, 0xbfff, MAP_ROM);
ZetMapMemory(DrvI8080RAM, 0xc000, 0xcfff, MAP_RAM);
ZetSetWriteHandler(tiamc1_videoram_write);
ZetSetOutHandler(kot_write_port);
ZetSetInHandler(kot_read_port);
ZetClose();
ppi8255_init(1);
ppi8255_set_read_ports(0, ppi_port_A_read, ppi_port_B_read, ppi_port_C_read);
// write C = coin counter
tiamc1_sound_init_kot();
GenericTilesInit();
GenericTilemapInit(0, TILEMAP_SCAN_ROWS, bg_map_callback, 8, 8, 32, 32);
GenericTilesSetGfx(0, DrvTileROM, 4, 8, 8, 0x010000, 0x10, 0x0f);
GenericTilesSetGfx(1, DrvSprROM, 4, 16, 16, 0x010000, 0x00, 0x0f);
GenericTilemapSetOffsets(0, 4, 0);
button_config = 0x6affff;
DrvDoReset();
return 0;
}
static INT32 DrvExit()
{
GenericTilesExit();
ZetExit();
ppi8255_exit();
tiamc1_sound_exit();
BurnFreeMemIndex();
is_gorodki = 0;
return 0;
}
static void DrvCharDecode()
{
INT32 Planes[4] = { STEP4(0x4000*3,-0x4000) };
INT32 XOffs[8] = { STEP8(0,1) };
INT32 YOffs[8] = { STEP8(0,8) };
GfxDecode(0x0100, 4, 8, 8, Planes, XOffs, YOffs, 0x40, DrvCharRAM, DrvCharRAMExp);
}
static void DrawSprites()
{
for (INT32 offs = 0; offs < 16; offs++)
{
if (DrvSprRAM[offs | 0x30] & 1)
{
INT32 sy = DrvSprRAM[offs | 0x00];
INT32 sx = DrvSprRAM[offs | 0x10];
INT32 code = DrvSprRAM[offs | 0x20];
INT32 flipx = DrvSprRAM[offs | 0x30] & 0x08;
INT32 flipy = DrvSprRAM[offs | 0x30] & 0x02;
DrawGfxMaskTile(0, 1, code, sx, sy, flipx, flipy, 0, 0xf);
}
}
}
static INT32 DrvDraw()
{
if (update_colors || BurnRecalc) {
for (INT32 i = 0; i < 16; i++) {
UINT32 p = DrvPalette[BurnPalRAM[i]];
UINT32 b = DrvPalette[BurnPalRAM[i | bg_color]];
BurnPalette[i + 0x00] = BurnHighCol(p >> 16, (p >> 8) & 0xff, p & 0xff, 0);
BurnPalette[i + 0x10] = BurnHighCol(b >> 16, (b >> 8) & 0xff, b & 0xff, 0);
}
update_colors = BurnRecalc = 0;
}
if (update_characters) {
DrvCharDecode();
update_characters = 0;
}
GenericTilemapSetScrollX(0, scrollx);
GenericTilemapSetScrollY(0, scrolly);
GenericTilemapDraw(0, pTransDraw, 0);
DrawSprites();
BurnTransferCopy(BurnPalette);
return 0;
}
static INT32 DrvFrame()
{
if (DrvReset) {
DrvDoReset();
}
ZetNewFrame();
{
for (INT32 i = 0; i < 3; i++) {
DrvInputs[i] = button_config >> (i * 8);
}
for (INT32 i = 0; i < 8; i++) {
DrvInputs[0] ^= (DrvJoy1[i] & 1) << i;
DrvInputs[1] ^= (DrvJoy2[i] & 1) << i;
DrvInputs[2] ^= (DrvJoy3[i] & 1) << i;
}
if (is_gorodki) {
DrvInputs[0] = ProcessAnalog(Analog[0], 1, 1, 0x60, 0xd0);
}
}
INT32 nInterleave = 312;
INT32 nCyclesTotal[1] = { 1750000 / 60 };
INT32 nCyclesDone[1] = { nExtraCycles };
vblank = 1;
for (INT32 i = 0; i < nInterleave; i++)
{
ZetOpen(0);
CPU_RUN(0, Zet);
ZetClose();
if (i == 56) vblank = 0;
}
nExtraCycles = nCyclesDone[0] - nCyclesTotal[0];
if (pBurnSoundOut) {
tiamc1_sound_update(pBurnSoundOut, nBurnSoundLen);
}
if (pBurnDraw) {
BurnDrvRedraw();
}
return 0;
}
static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
{
struct BurnArea ba;
if (pnMin) {
*pnMin = 0x029702;
}
if (nAction & ACB_VOLATILE) {
memset(&ba, 0, sizeof(ba));
ba.Data = AllRam;
ba.nLen = RamEnd - AllRam;
ba.szName = "All Ram";
BurnAcb(&ba);
ZetScan(nAction);
ppi8255_scan();
tiamc1_sound_scan(nAction, pnMin);
SCAN_VAR(layer_control);
SCAN_VAR(character_bank);
SCAN_VAR(scrollx);
SCAN_VAR(scrolly);
SCAN_VAR(bg_color);
SCAN_VAR(update_characters);
SCAN_VAR(update_colors);
SCAN_VAR(nExtraCycles);
}
return 0;
}
// Konek-Gorbunok
static struct BurnRomInfo konekRomDesc[] = {
{ "g1.d17", 0x2000, 0xf41d82c9, 1 | BRF_PRG | BRF_ESS }, // 0 i8080 Code
{ "g2.d17", 0x2000, 0xb44e7491, 1 | BRF_PRG | BRF_ESS }, // 1
{ "g3.d17", 0x2000, 0x91301282, 1 | BRF_PRG | BRF_ESS }, // 2
{ "g4.d17", 0x2000, 0x3ff0c20b, 1 | BRF_PRG | BRF_ESS }, // 3
{ "g5.d17", 0x2000, 0xe3196d30, 1 | BRF_PRG | BRF_ESS }, // 4
{ "g7.d17", 0x2000, 0xfe4e9fdd, 1 | BRF_PRG | BRF_ESS }, // 5
{ "a2.b07", 0x2000, 0x9eed06ee, 2 | BRF_GRA }, // 6 Sprites
{ "a3.g07", 0x2000, 0xeeff9b77, 2 | BRF_GRA }, // 7
{ "a5.l07", 0x2000, 0xfff9e089, 2 | BRF_GRA }, // 8
{ "a6.r07", 0x2000, 0x092e8ee2, 2 | BRF_GRA }, // 9
{ "prom100.e10", 0x0100, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 10 PROMs
{ "prom101.a01", 0x0100, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 11
{ "prom102.b03", 0x0080, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 12
{ "prom102.b06", 0x0080, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 13
{ "prom102.b05", 0x0100, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 14
};
STD_ROM_PICK(konek)
STD_ROM_FN(konek)
static INT32 KonekInit()
{
return DrvInit(6);
}
struct BurnDriver BurnDrvKonek = {
"konek", NULL, NULL, NULL, "198?",
"Konek-Gorbunok\0", NULL, "Terminal", "TIA-MC1",
NULL, NULL, NULL, NULL,
BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_PLATFORM, 0,
NULL, konekRomInfo, konekRomName, NULL, NULL, NULL, NULL, DrvInputInfo, NULL,
KonekInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &BurnRecalc, 0x20,
256, 256, 4, 3
};
// S.O.S.
static struct BurnRomInfo sostermRomDesc[] = {
{ "04.1g", 0x2000, 0xd588081e, 1 | BRF_PRG | BRF_ESS }, // 0 i8080 Code
{ "05.2g", 0x2000, 0xb44e7491, 1 | BRF_PRG | BRF_ESS }, // 1
{ "06.3g", 0x2000, 0x34dacde6, 1 | BRF_PRG | BRF_ESS }, // 2
{ "07.4g", 0x2000, 0x9f6f8cdd, 1 | BRF_PRG | BRF_ESS }, // 3
{ "08.5g", 0x2000, 0x25e70da4, 1 | BRF_PRG | BRF_ESS }, // 4
{ "10.7g", 0x2000, 0x22bc9997, 1 | BRF_PRG | BRF_ESS }, // 5
{ "00.2a", 0x2000, 0xa1c7f07a, 2 | BRF_GRA }, // 6 Sprites
{ "01.3a", 0x2000, 0x788b4036, 2 | BRF_GRA }, // 7
{ "02.5a", 0x2000, 0x9506cf9b, 2 | BRF_GRA }, // 8
{ "03.6a", 0x2000, 0x5a0c14e1, 2 | BRF_GRA }, // 9
{ "prom100.e10", 0x0100, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 10 PROMs
{ "prom101.a01", 0x0100, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 11
{ "prom102.b03", 0x0080, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 12
{ "prom102.b06", 0x0080, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 13
{ "prom102.b05", 0x0100, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 14
};
STD_ROM_PICK(sosterm)
STD_ROM_FN(sosterm)
struct BurnDriver BurnDrvSosterm = {
"sosterm", NULL, NULL, NULL, "198?",
"S.O.S.\0", NULL, "Terminal", "TIA-MC1",
NULL, NULL, NULL, NULL,
BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0,
NULL, sostermRomInfo, sostermRomName, NULL, NULL, NULL, NULL, DrvInputInfo, NULL,
KonekInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &BurnRecalc, 0x20,
256, 256, 4, 3
};
// Snezhnaja Koroleva
static struct BurnRomInfo korolevaRomDesc[] = {
{ "04.1g", 0x2000, 0xc3701225, 1 | BRF_PRG | BRF_ESS }, // 0 i8080 Code
{ "05.2g", 0x2000, 0x1b3742ce, 1 | BRF_PRG | BRF_ESS }, // 1
{ "06.3g", 0x2000, 0x48074786, 1 | BRF_PRG | BRF_ESS }, // 2
{ "07.4g", 0x2000, 0x41a4adb5, 1 | BRF_PRG | BRF_ESS }, // 3
{ "08.5g", 0x2000, 0x8f379d95, 1 | BRF_PRG | BRF_ESS }, // 4
{ "10.7g", 0x2000, 0x397f41f8, 1 | BRF_PRG | BRF_ESS }, // 5
{ "00.2a", 0x2000, 0x6f39f8be, 2 | BRF_GRA }, // 6 Sprites
{ "01.3a", 0x2000, 0x7bdfdd19, 2 | BRF_GRA }, // 7
{ "02.5a", 0x2000, 0x97770b0f, 2 | BRF_GRA }, // 8
{ "03.6a", 0x2000, 0x9b0a686a, 2 | BRF_GRA }, // 9
{ "prom100.e10", 0x0100, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 10 PROMs
{ "prom101.a01", 0x0100, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 11
{ "prom102.b03", 0x0080, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 12
{ "prom102.b06", 0x0080, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 13
{ "prom102.b05", 0x0100, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 14
};
STD_ROM_PICK(koroleva)
STD_ROM_FN(koroleva)
struct BurnDriver BurnDrvKoroleva = {
"koroleva", NULL, NULL, NULL, "198?",
"Snezhnaja Koroleva\0", NULL, "Terminal", "TIA-MC1",
NULL, NULL, NULL, NULL,
BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MAZE, 0,
NULL, korolevaRomInfo, korolevaRomName, NULL, NULL, NULL, NULL, DrvInputInfo, NULL,
KonekInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &BurnRecalc, 0x20,
256, 256, 4, 3
};
// Billiard
static struct BurnRomInfo bilyardRomDesc[] = {
{ "04.1g", 0x2000, 0xa44f913d, 1 | BRF_PRG | BRF_ESS }, // 0 i8080 Code
{ "05.2g", 0x2000, 0x6e41219f, 1 | BRF_PRG | BRF_ESS }, // 1
{ "10.7g", 0x2000, 0x173adb85, 1 | BRF_PRG | BRF_ESS }, // 2
{ "00.2a", 0x2000, 0x6f72e043, 2 | BRF_GRA }, // 3 Sprites
{ "01.3a", 0x2000, 0xdaddbbb5, 2 | BRF_GRA }, // 4
{ "02.5a", 0x2000, 0x3d744d33, 2 | BRF_GRA }, // 5
{ "03.6a", 0x2000, 0x8bfc0b15, 2 | BRF_GRA }, // 6
{ "prom100.e10", 0x0100, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 7 PROMs
{ "prom101.a01", 0x0100, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 8
{ "prom102.b03", 0x0080, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 9
{ "prom102.b06", 0x0080, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 10
{ "prom102.b05", 0x0100, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 11
};
STD_ROM_PICK(bilyard)
STD_ROM_FN(bilyard)
static INT32 BilyardInit()
{
return DrvInit(3);
}
struct BurnDriver BurnDrvBilyard = {
"bilyard", NULL, NULL, NULL, "198?",
"Billiard\0", NULL, "Terminal", "TIA-MC1",
NULL, NULL, NULL, NULL,
BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_SPORTSMISC, 0,
NULL, bilyardRomInfo, bilyardRomName, NULL, NULL, NULL, NULL, DrvInputInfo, NULL,
BilyardInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &BurnRecalc, 0x20,
256, 256, 4, 3
};
// Gorodki
static struct BurnRomInfo gorodkiRomDesc[] = {
{ "70.1g", 0x2000, 0xbd3eb624, 1 | BRF_PRG | BRF_ESS }, // 0 i8080 Code
{ "71.2g", 0x2000, 0x5a9ebd8d, 1 | BRF_PRG | BRF_ESS }, // 1
{ "72.3g", 0x2000, 0xedcc5c13, 1 | BRF_PRG | BRF_ESS }, // 2
{ "73.4g", 0x2000, 0xae69b9f3, 1 | BRF_PRG | BRF_ESS }, // 3
{ "66.2a", 0x2000, 0xb3dd4dec, 2 | BRF_GRA }, // 4 Sprites
{ "67.3a", 0x2000, 0xc94f5579, 2 | BRF_GRA }, // 5
{ "68.5a", 0x2000, 0x0d64708d, 2 | BRF_GRA }, // 6
{ "69.6a", 0x2000, 0x57c8ae81, 2 | BRF_GRA }, // 7
{ "prom100.e10", 0x0100, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 8 PROMs
{ "prom101.a01", 0x0100, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 9
{ "prom102.b03", 0x0080, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 10
{ "prom102.b06", 0x0080, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 11
{ "prom102.b05", 0x0100, 0x00000000, 3 | BRF_NODUMP | BRF_GRA }, // 12
};
STD_ROM_PICK(gorodki)
STD_ROM_FN(gorodki)
static INT32 GorodkiInit()
{
is_gorodki = 1;
return DrvInit(4);
}
struct BurnDriver BurnDrvGorodki = {
"gorodki", NULL, NULL, NULL, "198?",
"Gorodki\0", NULL, "Terminal", "TIA-MC1",
NULL, NULL, NULL, NULL,
BDF_GAME_WORKING, 2, HARDWARE_MISC_PRE90S, GBF_MISC, 0,
NULL, gorodkiRomInfo, gorodkiRomName, NULL, NULL, NULL, NULL, GorodkiInputInfo, NULL, // wrong input!
GorodkiInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &BurnRecalc, 0x20,
256, 256, 4, 3
};
// Kot-Rybolov (Terminal)
static struct BurnRomInfo kotRomDesc[] = {
{ "854.6", 0x2000, 0x44e5e8fc, 1 | BRF_PRG | BRF_ESS }, // 0 i8080 Code
{ "855.7", 0x2000, 0x0bb2e4b2, 1 | BRF_PRG | BRF_ESS }, // 1
{ "856.8", 0x2000, 0x9180c98f, 1 | BRF_PRG | BRF_ESS }, // 2
{ "850.5", 0x2000, 0x5dc3a102, 2 | BRF_GRA }, // 3 Sprites
{ "851.6", 0x2000, 0x7db239a0, 2 | BRF_GRA }, // 4
{ "852.7", 0x2000, 0xc7700f88, 2 | BRF_GRA }, // 5
{ "853.8", 0x2000, 0xb94bf1af, 2 | BRF_GRA }, // 6
{ "846.1", 0x2000, 0x42447f4a, 3 | BRF_GRA }, // 7 Tiles
{ "847.2", 0x2000, 0x99ada5e8, 3 | BRF_GRA }, // 8
{ "848.3", 0x2000, 0xa124cff4, 3 | BRF_GRA }, // 9
{ "849.4", 0x2000, 0x5d27fda6, 3 | BRF_GRA }, // 10
};
STD_ROM_PICK(kot)
STD_ROM_FN(kot)
struct BurnDriver BurnDrvKot = {
"kot", NULL, NULL, NULL, "198?",
"Kot-Rybolov (Terminal)\0", NULL, "Terminal", "TIA-MC1",
NULL, NULL, NULL, NULL,
BDF_GAME_WORKING, 1, HARDWARE_MISC_PRE90S, GBF_VSFIGHT, 0,
NULL, kotRomInfo, kotRomName, NULL, NULL, NULL, NULL, DrvInputInfo, NULL,
KotInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &BurnRecalc, 0x20,
256, 256, 4, 3
};

384
src/burn/snd/tiamc1_snd.cpp Normal file
View File

@ -0,0 +1,384 @@
// license:BSD-3-Clause
// copyright-holders:Eugene Sandulenko
/***************************************************************************
TIA-MC1 sound hardware
driver by Eugene Sandulenko
special thanks to Shiru for his standalone emulator and documentation
timer1 timer0
|--------| |--------|
| 8253 | | 8253 | |---|
in0 | | | | | 1 | |---|
----+ g0 o0 +---+ g0 o0 +---+ | | & |
in1 | | | | | o---+ | out
----+ g1 o1 +---+ g1 o1 +---+ | | +-----
in2 | | | | |---| | |
----+ g2 o2 +---+ g2 o2 +-----------+ |
clk1| | | | |---|
----+ clk | +-+ clk |
| | | | |
|--------| | |--------|
clk0 |
---------------+
in0-in2 comes from port #da
clk0 comes from 8224 and equals to 1777777Hz, i.e. processor clock
clk1 comes from divider 16000000/4/16/16/2 = 7812Hz
********************
TODO: use machine/pit8253.c
***************************************************************************/
#include "burnint.h"
#include "tiamc1_snd.h"
#include "stream.h"
#define CLOCK_DIVIDER 16
#define BUF_LEN 100000
#define T8253_CHAN0 0
#define T8253_CHAN1 1
#define T8253_CHAN2 2
#define T8253_CWORD 3
#if 0
// device type definition
DEFINE_DEVICE_TYPE(TIAMC1, tiamc1_sound_device, "tiamc1_sound", "TIA-MC1 Custom Sound")
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// tiamc1_sound_device - constructor
//-------------------------------------------------
tiamc1_sound_device::tiamc1_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, TIAMC1, tag, owner, clock),
device_sound_interface(mconfig, *this),
m_channel(nullptr),
m_timer1_divider(0)
{
}
#endif
struct timer8253chan
{
UINT16 count;
UINT16 cnval;
UINT8 bcdMode;
UINT8 cntMode;
UINT8 valMode;
UINT8 gate;
UINT8 output;
UINT8 loadCnt;
UINT8 enable;
};
struct timer8253struct
{
struct timer8253chan channel[3];
};
static void timer8253_reset(struct timer8253struct *t);
static void timer8253_tick(struct timer8253struct *t,int chn);
static void timer8253_wr(struct timer8253struct *t, int reg, UINT8 val);
static char timer8253_get_output(struct timer8253struct *t, int chn);
static void timer8253_set_gate(struct timer8253struct *t, int chn, UINT8 gate);
static Stream stream;
static int m_timer1_divider;
static timer8253struct m_timer0;
static timer8253struct m_timer1;
static INT32 kot_mode;
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
static void sound_stream_update(INT16 **streams, INT32 length);
void tiamc1_sound_reset()
{
timer8253_reset(&m_timer0);
timer8253_reset(&m_timer1);
m_timer1_divider = 0;
}
void tiamc1_sound_init()
{
stream.init(15750000/9 / CLOCK_DIVIDER, nBurnSoundRate, 1, 0, sound_stream_update);
tiamc1_sound_reset();
kot_mode = 0;
}
void tiamc1_sound_init_kot()
{
tiamc1_sound_init();
kot_mode = 1;
}
void tiamc1_sound_exit()
{
stream.exit();
}
void tiamc1_sound_update(INT16 *output, INT32 samples_len)
{
if (samples_len != nBurnSoundLen) {
bprintf(0, _T("tiamc1_sound_update(): once per frame, please!\n"));
return;
}
stream.render(output, samples_len);
}
void tiamc1_sound_scan(INT32 nAction, INT32 *pnMin)
{
if (nAction & ACB_DRIVER_DATA) {
SCAN_VAR(m_timer0);
SCAN_VAR(m_timer1);
SCAN_VAR(m_timer1_divider);
}
}
//-------------------------------------------------
// sound_stream_update - handle a stream update
//-------------------------------------------------
static void sound_stream_update(INT16 **streams, INT32 length)
{
int count, o0, o1, o2, len, orval = 0;
len = length * CLOCK_DIVIDER;
for (count = 0; count < len; count++)
{
m_timer1_divider++;
if (m_timer1_divider == 228)
{
m_timer1_divider = 0;
timer8253_tick(&m_timer1, 0);
timer8253_tick(&m_timer1, 1);
timer8253_tick(&m_timer1, 2);
timer8253_set_gate(&m_timer0, 0, timer8253_get_output(&m_timer1, 0));
timer8253_set_gate(&m_timer0, 1, timer8253_get_output(&m_timer1, 1));
timer8253_set_gate(&m_timer0, 2, timer8253_get_output(&m_timer1, 2));
}
if (kot_mode) // myow!
{
timer8253_set_gate(&m_timer0, 2, 1);
}
timer8253_tick(&m_timer0, 0);
timer8253_tick(&m_timer0, 1);
timer8253_tick(&m_timer0, 2);
o0 = timer8253_get_output(&m_timer0, 0) ? 1 : 0;
o1 = timer8253_get_output(&m_timer0, 1) ? 1 : 0;
o2 = timer8253_get_output(&m_timer0, 2) ? 1 : 0;
orval = (orval << 1) | (((o0 | o1) ^ 0xff) & o2);
if ((count + 1) % CLOCK_DIVIDER == 0)
{
streams[0][count / CLOCK_DIVIDER] = orval ? 0x2828 : 0;
orval = 0;
}
}
}
static void timer8253_reset(struct timer8253struct *t)
{
memset(t,0,sizeof(struct timer8253struct));
}
static void timer8253_tick(struct timer8253struct *t, int chn)
{
if (t->channel[chn].enable && t->channel[chn].gate)
{
switch (t->channel[chn].cntMode)
{
case 0:
t->channel[chn].count--;
if (t->channel[chn].count == 0xffff)
t->channel[chn].output = 1;
break;
case 3:
t->channel[chn].count--;
if (t->channel[chn].count < (t->channel[chn].cnval >> 1))
t->channel[chn].output = 0;
else
t->channel[chn].output = 1;
if (t->channel[chn].count == 0xffff)
t->channel[chn].count = t->channel[chn].cnval;
break;
case 4:
t->channel[chn].count--;
if(t->channel[chn].count==0)
t->channel[chn].output = 1;
if(t->channel[chn].count == 0xffff)
{
t->channel[chn].enable = 0;
t->channel[chn].output = 1;
}
break;
}
}
}
static void timer8253_wr(struct timer8253struct *t, int reg, UINT8 val)
{
int chn;
switch (reg)
{
case T8253_CWORD:
chn = val >> 6;
if (chn < 3)
{
t->channel[chn].bcdMode = (val & 1) ? 1 : 0;
t->channel[chn].cntMode = (val >> 1) & 0x07;
t->channel[chn].valMode = (val >> 4) & 0x03;
switch (t->channel[chn].valMode)
{
case 1:
case 2:
t->channel[chn].loadCnt = 1;
break;
case 3:
t->channel[chn].loadCnt = 2;
break;
}
switch (t->channel[chn].cntMode)
{
case 0:
t->channel[chn].output = 0;
t->channel[chn].enable = 0;
break;
case 3:
t->channel[chn].output = 1;
break;
case 4:
t->channel[chn].output = 1;
t->channel[chn].enable = 0;
break;
}
}
break;
default:
chn = reg;
switch (t->channel[chn].valMode)
{
case 1:
t->channel[chn].cnval = (t->channel[chn].cnval & 0xff00) | val;
break;
case 2:
t->channel[chn].cnval = (t->channel[chn].cnval & 0x00ff) | (val << 8);
break;
case 3:
t->channel[chn].cnval = (t->channel[chn].cnval >> 8) | (val << 8);
break;
}
if (t->channel[chn].cntMode==0)
{
t->channel[chn].enable = 0;
}
t->channel[chn].loadCnt--;
if (t->channel[chn].loadCnt == 0)
{
switch (t->channel[chn].valMode)
{
case 1:
case 2:
t->channel[chn].loadCnt = 1;
break;
case 3:
t->channel[chn].loadCnt = 2;
break;
}
switch (t->channel[chn].cntMode)
{
case 3:
t->channel[chn].count = t->channel[chn].cnval;
t->channel[chn].enable = 1;
break;
case 0:
case 4:
t->channel[chn].count = t->channel[chn].cnval;
t->channel[chn].enable = 1;
break;
}
}
}
}
static void timer8253_set_gate(struct timer8253struct *t, int chn, UINT8 gate)
{
t->channel[chn].gate = gate;
}
static char timer8253_get_output(struct timer8253struct *t, int chn)
{
return t->channel[chn].output;
}
void tiamc1_sound_timer0_write(INT32 offset, UINT8 data)
{
stream.update();
timer8253_wr(&m_timer0, offset, data);
}
void tiamc1_sound_timer1_write(INT32 offset, UINT8 data)
{
stream.update();
timer8253_wr(&m_timer1, offset, data);
}
void tiamc1_sound_gate_write(UINT8 data)
{
stream.update();
timer8253_set_gate(&m_timer1, 0, (data & 1) ? 1 : 0);
timer8253_set_gate(&m_timer1, 1, (data & 2) ? 1 : 0);
timer8253_set_gate(&m_timer1, 2, (data & 4) ? 1 : 0);
}

12
src/burn/snd/tiamc1_snd.h Normal file
View File

@ -0,0 +1,12 @@
// tia mc1 sound core
void tiamc1_sound_init();
void tiamc1_sound_init_kot();
void tiamc1_sound_exit();
void tiamc1_sound_update(INT16 *output, INT32 samples_len);
void tiamc1_sound_scan(INT32 nAction, INT32 *pnMin);
void tiamc1_sound_reset();
void tiamc1_sound_timer0_write(INT32 offset, UINT8 data);
void tiamc1_sound_timer1_write(INT32 offset, UINT8 data);
void tiamc1_sound_gate_write(UINT8 data);