From 50c97abc6cd3be1f0094168810c3a12eac2681d2 Mon Sep 17 00:00:00 2001 From: iq_132 <1191709+iq132@users.noreply.github.com> Date: Sun, 14 Sep 2014 00:43:10 +0000 Subject: [PATCH] NMK004 addition. [Trap15, Haze, iq_132] --- src/burn/devices/nmk004.cpp | 1110 +++++-------------------------- src/burn/devices/nmk004.h | 5 +- src/burn/drv/pst90s/d_nmk16.cpp | 525 +++++++++------ src/cpu/tlcs90/tlcs90.cpp | 123 ++-- 4 files changed, 551 insertions(+), 1212 deletions(-) diff --git a/src/burn/devices/nmk004.cpp b/src/burn/devices/nmk004.cpp index 3311a3da4..fc4e22be0 100644 --- a/src/burn/devices/nmk004.cpp +++ b/src/burn/devices/nmk004.cpp @@ -1,5 +1,9 @@ +// NMK004 device +// Based on MAME device by David Haywood and trap15 #include "burnint.h" +#include "m68000_intf.h" +#include "tlcs90_intf.h" #include "nmk004.h" #include "burn_ym2203.h" #include "msm6295.h" @@ -8,1017 +12,213 @@ UINT8 *NMK004OKIROM0; UINT8 *NMK004OKIROM1; UINT8 *NMK004PROGROM; -#define okim6295_w(x,y,z) MSM6295Command(x, z) -#define okim6295_r(x,y) MSM6295ReadStatus(x) +static UINT8 *ram; -#define ym2203_control_port_w(x, y, z) BurnYM2203Write(x, 0, z) -#define ym2203_write_port_w(x, y, z) BurnYM2203Write(x, 1, z) -#define ym2203_status_port_r(x,y) BurnYM2203Read(x, 0); -#define ym2203_read_port_r(x,y) BurnYM2203Read(x, 1) -#define device 0 -#define fatalerror printf -//#define logerror printf +static UINT8 to_nmk004 = 0; +static UINT8 to_main = 0; +static INT32 bankdata[2] = { 0, 0 }; -//-------------------------------------------------------------------------- - -#define FM_CHANNELS 6 -#define PSG_CHANNELS 3 -#define EFFECTS_CHANNELS 8 - -#define FM_FLAG_NEED_INITIALIZATION (1<<0) -#define FM_FLAG_UNKNOWN2 (1<<1) -#define FM_FLAG_NOTE_IS_PAUSE (1<<2) -#define FM_FLAG_UNKNOWN3 (1<<3) -#define FM_FLAG_MODULATE_NOTE (1<<4) -#define FM_FLAG_MUST_SEND_KEYON (1<<5) -#define FM_FLAG_MUST_SEND_CONFIGURATION (1<<6) -#define FM_FLAG_ACTIVE (1<<7) - -#define PSG_FLAG_ACTIVE (1<<0) -#define PSG_FLAG_NOTE_IS_PAUSE (1<<1) -#define PSG_FLAG_NEED_INITIALIZATION (1<<2) -#define PSG_FLAG_INITIALIZE_VOLUME (1<<3) -#define PSG_FLAG_NOTE_IS_NOISE (1<<5) -#define PSG_FLAG_NOISE_NOT_ENABLED (1<<6) - -#define EFFECTS_FLAG_NEED_INITIALIZATION (1<<0) -#define EFFECTS_FLAG_ACTIVE (1<<7) - -#define NOTE_PAUSE 0x0c - -struct psg_control +static UINT8 nmk004_tlcs90_read(UINT32 address) { -/* C220 */ UINT8 flags; -/* C221-C222 */ UINT16 note_timer; -/* C223-C224 */ UINT16 note_length; -/* C225 */ UINT8 volume_timer; -/* C227-C228 */ UINT16 current; // current position in control table -/* C229-C22A */ UINT16 return_address[16]; // return address when control table calls a subtable - INT32 return_address_depth; -/* C22B-C22C */ UINT16 loop_start; // first instruction of loop -/* C22D */ UINT8 loop_times; // number of times to loop -/* C22E */ UINT8 volume_shape; -/* C22F */ UINT8 volume_position; -/* C230 */ UINT8 octave; // base octave -/* C231 */ UINT8 note; // note to play -/* C233 */ UINT8 note_period_hi_bits; -}; + if (address >= 0xfec0 && address < 0xffc0) { // internal ram + return ram[0x800 + (address - 0xfec0)]; + } -struct fm_control -{ -UINT8 note; -/* C020 */ UINT8 flags; -/* C021 */ UINT8 slot; // for ym2203 keyon command -/* C022-C039 */ UINT8 voice_params[0x18]; // parameters for the YM2203 to configure sound shape -/* C03A-C03B */ UINT16 f_number; -/* C03C */ UINT8 self_feedback; -/* C03D */ UINT8 note_duration_table_select; -/* C03E-C03F */ UINT16 current; // current position in control table -/* C040-C041 */ UINT16 loop_start; // first instruction of loop -/* C042 */ UINT8 loop_times; // number of times to loop -/* C043-C044 */ UINT16 return_address[16]; // return address when control table calls a subtable - INT32 return_address_depth; -/* C045 */ UINT8 octave; -/* C046-C047 */ UINT16 timer1; -/* C048-C049 */ UINT16 timer2; -/* C04A-C04B */ UINT16 timer1_duration; -/* C04C-C04D */ UINT16 timer2_duration; -/* C04E */ UINT8 modulation_table_number; -/* C04F-C050 */ UINT16 modulation_timer; -/* C051-C052 */ UINT16 modulation_table; -/* C053-C054 */ UINT16 modulation_table_position; -/* C055-C056 */ UINT16 note_period; -/* C057-C05A */ UINT8 voice_volume[4]; // parameters for the YM2203 to configure sound shape -/* C05C */ UINT8 must_update_voice_params; -}; + switch (address) + { + case 0xf800: + case 0xf801: + return BurnYM2203Read(0, address & 1); -struct effects_control -{ -/* C1A0 */ UINT8 flags; -/* C1BE-C1BF */ UINT16 current; // current position in control table -/* C1C0-C1C1 */ UINT16 loop_start; // first instruction of loop -/* C1C2 */ UINT8 loop_times; // number of times to loop -/* C1C3-C1C4 */ UINT16 return_address[16]; // return address when control table calls a subtable - INT32 return_address_depth; -/* C1C6-C1C7 */ UINT16 timer; -/* C1CA-C1CB */ UINT16 timer_duration; -}; + case 0xf900: + return MSM6295ReadStatus(0); -static struct -{ - const UINT8 *rom; // NMK004 data ROM - UINT8 from_main; // command from main CPU - UINT8 to_main; // answer to main CPU - INT32 protection_check; + case 0xfa00: + return MSM6295ReadStatus(1); - INT32 ymdevice; - INT32 oki1device; - INT32 oki2device; - - /* C001 */ UINT8 last_command; // last command received - /* C016 */ UINT8 oki_playing; // bitmap of active Oki channels - /* C020-C19F */ struct fm_control fm_control[FM_CHANNELS]; - /* C220-C2DF */ struct psg_control psg_control[PSG_CHANNELS]; - /* C1A0-C21F */ struct effects_control effects_control[EFFECTS_CHANNELS]; -} NMK004_state; - - -#define SAMPLE_TABLE_0 0xefe0 -#define SAMPLE_TABLE_1 0xefe2 -#define FM_MODULATION_TABLE 0xefe4 -#define FM_NOTE_TABLE 0xefe6 -#define NOTE_LENGTH_TABLE_1 0xefe8 -#define NOTE_LENGTH_TABLE_2 0xefea -#define NOTE_LENGTH_TABLE_3 0xefec -#define PSG_VOLUME_TABLE 0xefee -#define COMMAND_TABLE 0xeff0 -#define PSG_NOTE_TABLE 0xeff2 - -INT32 NMK004Scan(INT32 nAction, INT32* pnMin) -{ - if (nAction & ACB_VOLATILE) { // Scan volatile data - - if (pnMin) { - *pnMin = 0x029496; - } - const UINT8 *rtemp = NMK004_state.rom; - - SCAN_VAR(NMK004_state); - NMK004_state.rom = rtemp; + case 0xfb00: + return to_nmk004; } return 0; } - -static UINT8 read8(INT32 address) +static void oki_bankswitch(INT32 chip, INT32 bank) { - return NMK004_state.rom[address]; + UINT8 *rom = (chip) ? NMK004OKIROM1 : NMK004OKIROM0; + + bankdata[chip] = bank; + bank = (bank + 1) & 3; + + memcpy (rom + 0x20000, rom + 0x20000 + bank * 0x20000, 0x20000); } -static UINT16 read16(INT32 address) +static void nmk004_tlcs90_write(UINT32 address, UINT8 data) { - return NMK004_state.rom[address] + 256 * NMK004_state.rom[address+1]; -} - -/***************************** - - OKI6295 - -*****************************/ - -static void oki_play_sample(INT32 sample_no) -{ - UINT16 table_start = (sample_no & 0x80) ? read16(SAMPLE_TABLE_1) : read16(SAMPLE_TABLE_0); - UINT8 byte1 = read8(table_start + 2 * (sample_no & 0x7f) + 0); - UINT8 byte2 = read8(table_start + 2 * (sample_no & 0x7f) + 1); - INT32 chip = (byte1 & 0x80) >> 7; - const INT32 okidevice = (chip) ? NMK004_state.oki2device : NMK004_state.oki1device; - - if ((byte1 & 0x7f) == 0) - { - // stop all channels - okim6295_w(okidevice, 0, 0x78 ); + if (address >= 0xfec0 && address < 0xffc0) { // internal ram + ram[0x800 + (address - 0xfec0)] = data; + return; } - else + + switch (address) { - INT32 sample = byte1 & 0x7f; - INT32 ch = byte2 & 0x03; - INT32 force = (byte2 & 0x80) >> 7; + case 0xf800: + case 0xf801: + BurnYM2203Write(0, address & 1, data); + return; - if (!force && (NMK004_state.oki_playing & (1 << (ch + 4*chip)))) - return; + case 0xf900: + MSM6295Command(0, data); + return; - NMK004_state.oki_playing |= 1 << (ch + 4*chip); + case 0xfa00: + MSM6295Command(1, data); + return; - // stop channel - okim6295_w(okidevice, 0, (0x08 << ch) ); + case 0xfc00: + to_main = data; + return; - if (sample != 0) - { - UINT8 *rom = (chip == 0) ? NMK004OKIROM0 : NMK004OKIROM1; - INT32 bank = (byte2 & 0x0c) >> 2; - INT32 vol = (byte2 & 0x70) >> 4; + case 0xfc01: + oki_bankswitch(0, data); + return; - if (bank != 3) - memcpy(rom + 0x20000,rom + 0x40000 + bank * 0x20000,0x20000); + case 0xfc02: + oki_bankswitch(1, data); + return; + } +} - okim6295_w(okidevice, 0, 0x80 | sample ); - okim6295_w(okidevice, 0, (0x10 << ch) | vol ); +static void nmk004_tlcs90_write_port(UINT16 port, UINT8 data) +{ + switch (port) + { + case 0xffc8: { // hack - disable watchdog function + if (data & 1) { + // SekReset(); + // bprintf (0, _T("Resetting 68k!\n")); + } else { + // bprintf (0, _T("Clear 68k reset!\n")); + } } } } -static void oki_update_state(void) +void NMK004_reset() { - NMK004_state.oki_playing = ((okim6295_r(NMK004_state.oki2device, 0) & 0x0f) << 4) | (okim6295_r(NMK004_state.oki1device, 0) & 0x0f); + memset (ram, 0, 0x900); + + tlcs90Open(0); + tlcs90Reset(); + BurnYM2203Reset(); + tlcs90Close(); + + MSM6295Reset(0); + MSM6295Reset(1); + + oki_bankswitch(0,0); + oki_bankswitch(1,0); + to_main = 0; + to_nmk004 = 0; } -/***************************** - - EFFECTS (OKI6295) - -*****************************/ - -static void effects_update(INT32 channel) +static void NMK004YM2203IrqHandler(INT32, INT32 nStatus) { - struct effects_control *effects = &NMK004_state.effects_control[channel]; - - // advance the timers - if (effects->timer) - effects->timer--; - - - if (effects->flags & EFFECTS_FLAG_NEED_INITIALIZATION) - { - effects->flags = EFFECTS_FLAG_ACTIVE; - effects->timer = 0; - } - - - if (effects->flags & EFFECTS_FLAG_ACTIVE) - { - if (effects->timer == 0) - { - UINT8 token; - - do - { - token = read8(effects->current++); - - if (token == 0x0ef || (token & 0xf0) == 0xf0) - { - switch (token) - { - case 0xef: // play sample - oki_play_sample(read8(effects->current++)); - break; - - case 0xf6: // jump - effects->current = read16(effects->current); - break; - - case 0xf7: // begin repeat loop - effects->loop_times = read8(effects->current++); - effects->loop_start = effects->current; - break; - - case 0xf8: // end repeat loop - if (--effects->loop_times > 0) - effects->current = effects->loop_start; - break; - - case 0xf9: // call subtable - effects->return_address[effects->return_address_depth++] = effects->current + 2; - effects->current = read16(effects->current); - break; - - case 0xfa: // return from subtable - effects->current = effects->return_address[--effects->return_address_depth]; - break; - - case 0xfc: // ??? (hachamf command 04) - break; - - case 0xfd: // ??? (hachamf command 04) - break; - - case 0xff: // end - effects->flags = 0; // disable channel - return; - - default: - fatalerror("effects channel %d unsupported token %02x",channel,token); - } - } - } while (token == 0xef || (token & 0xf0) == 0xf0); - - effects->current--; - - if ((read8(effects->current) & 0x80) == 0) - { - if (read8(effects->current++) != 0x0c) - { - // this shouldn't happen on the effects channels (but it happens e.g. hachamf command 04) - } - } - - // optional note length (otherwise use the same length as the previous one) - if (read8(effects->current) & 0x80) - { - UINT16 table_start = read16(NOTE_LENGTH_TABLE_1); - - effects->timer_duration = read16(table_start + 2 * (read8(effects->current++) & 0x7f)); - } - - effects->timer = effects->timer_duration; - } - } + tlcs90SetIRQLine(0, (nStatus) ? TLCS90_IRQSTATUS_ACK : TLCS90_IRQSTATUS_NONE); } -/***************************** - - YM2203 - FM - -*****************************/ - -static void fm_update(INT32 channel) +inline static double NMK004GetTime() { - struct fm_control *fm = &NMK004_state.fm_control[channel]; - - // advance the timers - if (fm->timer1) - fm->timer1--; - - if (fm->timer2) - fm->timer2--; - - if (fm->modulation_timer) - fm->modulation_timer--; - - - if (fm->flags & FM_FLAG_NEED_INITIALIZATION) - { - fm->flags = FM_FLAG_ACTIVE; - fm->timer1 = 0; - } - - - if (fm->flags & FM_FLAG_ACTIVE) - { - if (fm->timer1 == 0) - { - UINT8 token; - - do - { - token = read8(fm->current++); - - if (token == 0x0ef || (token & 0xf0) == 0xf0) - { - INT32 i; - - switch (token) - { - case 0xf0: // slot (for keyon ym2203 command) - fm->flags |= FM_FLAG_MUST_SEND_CONFIGURATION; - fm->slot = read8(fm->current++); - if (channel < 3 || !(NMK004_state.fm_control[channel-3].flags & FM_FLAG_ACTIVE)) - { - ym2203_control_port_w(NMK004_state.ymdevice, 0, 0x28); // keyon/off - ym2203_write_port_w(NMK004_state.ymdevice, 0, channel % 3); - } - break; - - case 0xf1: // sound shape - fm->flags |= FM_FLAG_MUST_SEND_CONFIGURATION; - for (i = 0x00; i < 0x04; i++) - fm->voice_params[i] = read8(fm->current++); - break; - - case 0xf2: // sound shape - fm->flags |= FM_FLAG_MUST_SEND_CONFIGURATION; - for (i = 0; i < 4; i++) - fm->voice_volume[i] = read8(fm->current++); - break; - - case 0xf3: // sound shape - fm->flags |= FM_FLAG_MUST_SEND_CONFIGURATION; - for (i = 0x08; i < 0x18; i++) - fm->voice_params[i] = read8(fm->current++); - break; - - case 0xf4: // set self-feedback - fm->flags |= FM_FLAG_MUST_SEND_CONFIGURATION; - fm->self_feedback = read8(fm->current++); - break; - - case 0xf5: // select note duration table - fm->note_duration_table_select = read8(fm->current++); - break; - - case 0xf6: // jump - fm->current = read16(fm->current); - break; - - case 0xf7: // begin repeat loop - fm->loop_times = read8(fm->current++); - fm->loop_start = fm->current; - break; - - case 0xf8: // end repeat loop - if (--fm->loop_times > 0) - fm->current = fm->loop_start; - break; - - case 0xf9: // call subtable - fm->return_address[fm->return_address_depth++] = fm->current + 2; - fm->current = read16(fm->current); - break; - - case 0xfa: // return from subtable - fm->current = fm->return_address[--fm->return_address_depth]; - break; - - case 0xfb: // set octave - fm->octave = read8(fm->current++); - break; - - case 0xfc: // ??? - fm->flags |= FM_FLAG_UNKNOWN2; - fm->flags |= FM_FLAG_UNKNOWN3; - break; - - case 0xfd: // ??? - fm->flags &= ~FM_FLAG_UNKNOWN2; - break; - - case 0xfe: // set note modulation - fm->modulation_table_number = read8(fm->current++); - if (fm->modulation_table_number == 0) - { - fm->flags &= ~FM_FLAG_MODULATE_NOTE; - } - else - { - UINT16 table_start = read16(FM_MODULATION_TABLE); - - fm->modulation_table = read16(table_start + 2 * (fm->modulation_table_number - 1)); - fm->modulation_timer = read16(fm->modulation_table); - fm->modulation_table_position = fm->modulation_table + 2; - fm->flags |= FM_FLAG_MODULATE_NOTE; - } - break; - - case 0xff: // end - fm->flags = FM_FLAG_MUST_SEND_CONFIGURATION; // disable channel - for (i = 0x04; i < 0x08; i++) - fm->voice_params[i] = 0x7f; - for (i = 0x14; i < 0x18; i++) - fm->voice_params[i] = 0x0f; - return; - - default: - fatalerror("fm channel %d unsupported token %02x",channel,token); - } - } - } while (token == 0xef || (token & 0xf0) == 0xf0); - - fm->current--; - - if ((read8(fm->current) & 0x80) == 0) - { - INT32 note = read8(fm->current++); - - fm->note = note; - if ((note & 0x0f) == NOTE_PAUSE) - fm->flags |= FM_FLAG_NOTE_IS_PAUSE; - else - { - UINT16 table_start = read16(FM_NOTE_TABLE); - UINT16 period = read16(table_start + 2 * (note & 0x0f)); - UINT8 octave = ((fm->octave << 4) + note) & 0xf0; - - fm->flags &= ~FM_FLAG_NOTE_IS_PAUSE; - fm->note_period = period | (octave << 7); - - fm->must_update_voice_params = 1; - } - } - - // optional note length (otherwise use the same length as the previous one) - if (read8(fm->current) & 0x80) - { - UINT16 table_start; - UINT8 duration = read8(fm->current++) & 0x7f; - - table_start = read16(NOTE_LENGTH_TABLE_1); - fm->timer1_duration = read16(table_start + 2 * duration); - - table_start = fm->note_duration_table_select ? read16(NOTE_LENGTH_TABLE_3) : read16(NOTE_LENGTH_TABLE_2); - fm->timer2_duration = read16(table_start + 2 * duration); - } - - fm->timer1 = fm->timer1_duration; - fm->timer2 = fm->timer2_duration; - - - if (!(fm->flags & FM_FLAG_NOTE_IS_PAUSE) && - ((fm->flags & FM_FLAG_UNKNOWN3) || !(fm->flags & FM_FLAG_UNKNOWN2))) - { - fm->flags &= ~FM_FLAG_UNKNOWN3; - fm->flags |= FM_FLAG_MUST_SEND_KEYON; - fm->flags |= FM_FLAG_MUST_SEND_CONFIGURATION; - } - } - } - - if ((fm->flags & FM_FLAG_MODULATE_NOTE) && (fm->flags & FM_FLAG_MUST_SEND_KEYON)) - { - fm->modulation_timer = read16(fm->modulation_table); - fm->modulation_table_position = fm->modulation_table + 2; - } - - if (!(fm->flags & FM_FLAG_MODULATE_NOTE) || (fm->flags & FM_FLAG_MUST_SEND_KEYON) || fm->must_update_voice_params) - { - INT32 i; - - fm->must_update_voice_params = 0; - - for (i = 0; i < 4; i++) - fm->voice_params[0x04 + i] = fm->voice_volume[i]; - - fm->f_number = fm->note_period; - } - else - { - if (fm->modulation_timer == 0) - { - INT32 i; - UINT16 a; - - for (i = 0; i < 4; i++) - fm->voice_params[0x04 + i] = fm->voice_volume[i]; - - fm->modulation_table_position++; - a = read8(fm->modulation_table_position++); - if (a & 0x80) // sign extend - a |= 0xff00; - a *= 4; - - fm->f_number = fm->note_period + a; - - fm->modulation_timer = read8(fm->modulation_table_position++); // modulation_timer is UINT16 but this is just 8-bit - - if (read8(fm->modulation_table_position) == 0x80) // end of table - repeat - { - fm->modulation_table_position = fm->modulation_table + 2; - } - else if (read8(fm->modulation_table_position) == 0x88) // end of table - stop - { - fm->flags &= ~FM_FLAG_MODULATE_NOTE; - } - } - } + return (double)tlcs90TotalCycles() / 8000000; } -static void fm_voices_update(void) +inline static INT32 NMK004SynchroniseStream(INT32 nSoundRate) { - static const INT32 ym2203_registers[0x18] = - { - 0x30,0x38,0x34,0x3C,0x40,0x48,0x44,0x4C,0x50,0x58,0x54,0x5C,0x60,0x68,0x64,0x6C, - 0x70,0x78,0x74,0x7C,0x80,0x88,0x84,0x8C - }; - INT32 channel,i; - - for (channel = 0; channel < 3;channel++) - { - struct fm_control *fm1 = &NMK004_state.fm_control[channel]; - struct fm_control *fm2 = &NMK004_state.fm_control[channel + 3]; - - if (fm1->flags & FM_FLAG_MUST_SEND_CONFIGURATION) - { - fm1->flags &= ~FM_FLAG_MUST_SEND_CONFIGURATION; - - for (i = 0; i < 0x18; i++) - { - ym2203_control_port_w(NMK004_state.ymdevice, 0, ym2203_registers[i] + channel); - ym2203_write_port_w(NMK004_state.ymdevice, 0, fm1->voice_params[i]); - } - } - - if (fm2->flags & FM_FLAG_MUST_SEND_CONFIGURATION) - { - fm2->flags &= ~FM_FLAG_MUST_SEND_CONFIGURATION; - - if (!(fm1->flags & FM_FLAG_ACTIVE)) - { - for (i = 0; i < 0x18; i++) - { - ym2203_control_port_w(NMK004_state.ymdevice, 0, ym2203_registers[i] + channel); - ym2203_write_port_w(NMK004_state.ymdevice, 0, fm2->voice_params[i]); - } - } - } - - if (fm1->flags & FM_FLAG_ACTIVE) - { - ym2203_control_port_w(NMK004_state.ymdevice, 0, 0xb0 + channel); // self-feedback - ym2203_write_port_w(NMK004_state.ymdevice, 0, fm1->self_feedback); - - ym2203_control_port_w(NMK004_state.ymdevice, 0, 0xa4 + channel); // F-number - ym2203_write_port_w(NMK004_state.ymdevice, 0, fm1->f_number >> 8); - - ym2203_control_port_w(NMK004_state.ymdevice, 0, 0xa0 + channel); // F-number - ym2203_write_port_w(NMK004_state.ymdevice, 0, fm1->f_number & 0xff); - } - else - { - ym2203_control_port_w(NMK004_state.ymdevice, 0, 0xb0 + channel); // self-feedback - ym2203_write_port_w(NMK004_state.ymdevice, 0, fm2->self_feedback); - - ym2203_control_port_w(NMK004_state.ymdevice, 0, 0xa4 + channel); // F-number - ym2203_write_port_w(NMK004_state.ymdevice, 0, fm2->f_number >> 8); - - ym2203_control_port_w(NMK004_state.ymdevice, 0, 0xa0 + channel); // F-number - ym2203_write_port_w(NMK004_state.ymdevice, 0, fm2->f_number & 0xff); - } - - if (fm1->flags & FM_FLAG_MUST_SEND_KEYON) - { - fm1->flags &= ~FM_FLAG_MUST_SEND_KEYON; - - ym2203_control_port_w(NMK004_state.ymdevice, 0, 0x28); // keyon/off - ym2203_write_port_w(NMK004_state.ymdevice, 0, fm1->slot | channel); - } - - if (fm2->flags & FM_FLAG_MUST_SEND_KEYON) - { - fm2->flags &= ~FM_FLAG_MUST_SEND_KEYON; - - if (!(fm1->flags & FM_FLAG_ACTIVE)) - { - ym2203_control_port_w(NMK004_state.ymdevice, 0, 0x28); // keyon/off - ym2203_write_port_w(NMK004_state.ymdevice, 0, fm2->slot | channel); - } - } - } -} - -/***************************** - - YM2203 - PSG - -*****************************/ - -static void psg_update(INT32 channel) -{ - struct psg_control *psg = &NMK004_state.psg_control[channel]; - - // advance the timers - if (psg->note_timer) - psg->note_timer--; - - if (psg->volume_timer) - psg->volume_timer--; - - if (psg->flags & PSG_FLAG_NEED_INITIALIZATION) - { - psg->flags &= ~PSG_FLAG_NEED_INITIALIZATION; - psg->flags |= PSG_FLAG_ACTIVE; - - if (psg->flags & PSG_FLAG_NOTE_IS_NOISE) - { - INT32 enable; - - psg->flags &= ~PSG_FLAG_NOTE_IS_NOISE; - psg->flags &= ~PSG_FLAG_NOISE_NOT_ENABLED; - - // enable noise, disable tone on this channel - ym2203_control_port_w(NMK004_state.ymdevice, 0, 0x07); - enable = ym2203_read_port_r(NMK004_state.ymdevice, 0); - enable |= (0x01 << channel); // disable tone - enable &= ~(0x08 << channel); // enable noise - ym2203_write_port_w(NMK004_state.ymdevice, 0, enable); - } - - - psg->note_timer = 0; - psg->volume_timer = 0; - psg->octave = 0; - } - - if (psg->flags & PSG_FLAG_ACTIVE) - { - if (psg->note_timer == 0) - { - UINT8 token; - - do - { - token = read8(psg->current++); - - if ((token & 0xf0) == 0xf0) - { - INT32 enable; - - switch (token) - { - case 0xf0: // noise - psg->flags |= PSG_FLAG_NOTE_IS_NOISE; - break; - - case 0xf1: // note - psg->flags &= ~PSG_FLAG_NOTE_IS_NOISE; - psg->flags &= ~PSG_FLAG_NOISE_NOT_ENABLED; - - // enable noise, disable tone on this channel - ym2203_control_port_w(NMK004_state.ymdevice, 0, 0x07); - enable = ym2203_read_port_r(NMK004_state.ymdevice, 0); - enable |= (0x01 << channel); // disable tone - enable &= ~(0x08 << channel); // enable noise - ym2203_write_port_w(NMK004_state.ymdevice, 0, enable); - break; - - case 0xf2: // set volume shape - case 0xf3: - case 0xf4: - case 0xf5: - psg->volume_shape = read8(psg->current++); - break; - - case 0xf6: // jump - psg->current = read16(psg->current); - break; - - case 0xf7: // begin repeat loop - psg->loop_times = read8(psg->current++); - psg->loop_start = psg->current; - break; - - case 0xf8: // end repeat loop - if (--psg->loop_times > 0) - psg->current = psg->loop_start; - break; - - case 0xf9: // call subtable - psg->return_address[psg->return_address_depth++] = psg->current + 2; - psg->current = read16(psg->current); - break; - - case 0xfa: // return from subtable - psg->current = psg->return_address[--psg->return_address_depth]; - break; - - case 0xfb: // set octave - case 0xfc: - case 0xfd: - case 0xfe: - psg->octave = read8(psg->current++); - break; - - case 0xff: // end - psg->flags = 0; // disable channel - psg->volume_shape = 0; - - // mute channel - ym2203_control_port_w(NMK004_state.ymdevice, 0, 8 + channel); - ym2203_write_port_w(NMK004_state.ymdevice, 0, 0); - return; - } - } - } while ((token & 0xf0) == 0xf0); - - // token is the note to play - psg->note = token; - if ((psg->note & 0x0f) > NOTE_PAUSE) - { - - } - - // optional note length (otherwise use the same length as the previous one) - if (read8(psg->current) & 0x80) - { - UINT16 table_start = read16(NOTE_LENGTH_TABLE_1); - - psg->note_length = read16(table_start + 2 * (read8(psg->current++) & 0x7f)); - } - - psg->note_timer = psg->note_length; - psg->volume_timer = 0; - - psg->flags |= PSG_FLAG_INITIALIZE_VOLUME; - - if (psg->note == NOTE_PAUSE) - psg->flags |= PSG_FLAG_NOTE_IS_PAUSE; - else - { - psg->flags &= ~PSG_FLAG_NOTE_IS_PAUSE; - - if (!(psg->flags & PSG_FLAG_NOTE_IS_NOISE)) - { - UINT16 table_start = read16(PSG_NOTE_TABLE); - UINT16 period = read16(table_start + 2 * (psg->note & 0x0f)); - UINT8 octave = psg->octave + ((psg->note & 0xf0) >> 4); - - period >>= octave; - - ym2203_control_port_w(NMK004_state.ymdevice, 0, 2 * channel + 1); - ym2203_write_port_w(NMK004_state.ymdevice, 0, (period & 0x0f00) >> 8); - ym2203_control_port_w(NMK004_state.ymdevice, 0, 2 * channel + 0); - ym2203_write_port_w(NMK004_state.ymdevice, 0, (period & 0x00ff)); - - psg->note_period_hi_bits = (period & 0x0f00) >> 8; - } - else - { - if (!(psg->flags & PSG_FLAG_NOISE_NOT_ENABLED)) - { - INT32 enable; - - psg->flags |= PSG_FLAG_NOISE_NOT_ENABLED; - - // disable noise, enable tone on this channel - ym2203_control_port_w(NMK004_state.ymdevice, 0, 0x07); - enable = ym2203_read_port_r(NMK004_state.ymdevice, 0); - enable &= ~(0x01 << channel); // enable tone - enable |= (0x08 << channel); // disable noise - ym2203_write_port_w(NMK004_state.ymdevice, 0, enable); - } - - ym2203_control_port_w(NMK004_state.ymdevice, 0, 0x06); // noise period - ym2203_write_port_w(NMK004_state.ymdevice, 0, psg->note); - psg->note_period_hi_bits = psg->note; - } - } - } - - if (psg->volume_timer == 0) - { - UINT16 table_start = read16(PSG_VOLUME_TABLE); - UINT16 vol_table_start = read16(table_start + 2 * psg->volume_shape); - INT32 volume; - - if (psg->flags & PSG_FLAG_INITIALIZE_VOLUME) - { - psg->flags &= ~PSG_FLAG_INITIALIZE_VOLUME; - psg->volume_position = 0; - } - - volume = read8(vol_table_start + psg->volume_position++); - psg->volume_timer = read8(vol_table_start + psg->volume_position++); - - if (psg->flags & PSG_FLAG_NOTE_IS_PAUSE) - volume = 0; - - // set volume - ym2203_control_port_w(NMK004_state.ymdevice, 0, 8 + channel); - ym2203_write_port_w(NMK004_state.ymdevice, 0, volume & 0x0f); - } - } -} - -/***************************** - - Command processing - -*****************************/ - -static void get_command() -{ - static const UINT8 from_main[] = - { - 0x00,0x22,0x62,0x8c,0xc7,0x00,0x00,0x3f,0x7f,0x89,0xc7,0x00,0x00,0x2b,0x6b - }; - static const UINT8 to_main[] = - { - 0x82,0xc7,0x00,0x2c,0x6c,0x00,0x9f,0xc7,0x00,0x29,0x69,0x00,0x8b,0xc7,0x00 - }; - - UINT8 cmd = NMK004_state.from_main; - - if (NMK004_state.protection_check < (INT32)sizeof(to_main)) - { - // startup handshake - if (cmd == from_main[NMK004_state.protection_check]) - { -// logerror("advance handshake to %02x\n",to_main[NMK004_state.protection_check]); - NMK004_state.to_main = to_main[NMK004_state.protection_check++]; - } - } - else - { - // send command back to main CPU to acknowledge reception - NMK004_state.to_main = cmd; - } - - if (NMK004_state.last_command != cmd) - { - UINT16 table_start = read16(COMMAND_TABLE); - UINT16 cmd_table = read16(table_start + 2 * cmd); - - NMK004_state.last_command = cmd; - - if ((cmd_table & 0xff00) == 0) - { - oki_play_sample(cmd_table); - } - else - { - INT32 channel; - - while ((channel = read8(cmd_table++)) != 0xff) - { - table_start = read16(cmd_table); - cmd_table += 2; - - if (channel == 0xef) break; // bioship bug? - - if (channel < FM_CHANNELS) - { - NMK004_state.fm_control[channel].current = table_start; - NMK004_state.fm_control[channel].return_address_depth = 0; - NMK004_state.fm_control[channel].flags |= FM_FLAG_NEED_INITIALIZATION; - } - else - { - channel -= FM_CHANNELS; - if (channel < PSG_CHANNELS) - { - NMK004_state.psg_control[channel].current = table_start; - NMK004_state.psg_control[channel].return_address_depth = 0; - NMK004_state.psg_control[channel].flags |= PSG_FLAG_NEED_INITIALIZATION; - } - else - { - channel -= PSG_CHANNELS; - if (channel >= EFFECTS_CHANNELS) - { - - } - NMK004_state.effects_control[channel].current = table_start; - NMK004_state.effects_control[channel].return_address_depth = 0; - NMK004_state.effects_control[channel].flags |= EFFECTS_FLAG_NEED_INITIALIZATION; - } - } - } - } - } -} - -static void update_music(void) -{ - INT32 channel; - - for (channel = 0; channel < FM_CHANNELS; channel++) - fm_update(channel); - fm_voices_update(); - - for (channel = 0; channel < PSG_CHANNELS; channel++) - psg_update(channel); - - for (channel = 0; channel < EFFECTS_CHANNELS; channel++) - effects_update(channel); -} - -void NMK004_irq(INT32 irq) -{ - if (irq) - { - INT32 status = ym2203_status_port_r(device,0); - - if (status & 1) // timer A expired - { - oki_update_state(); - get_command(); - update_music(); - - // restart timer - ym2203_control_port_w(device, 0, 0x27); - ym2203_write_port_w(device, 0, 0x15); - } - } + return (INT64)(tlcs90TotalCycles() * nSoundRate / 8000000); } void NMK004_init() { - static const UINT8 ym2203_init[] = - { - 0x07,0x38,0x08,0x00,0x09,0x00,0x0A,0x00,0x24,0xB3,0x25,0x00,0x26,0xF9,0x27,0x15, - 0x28,0x00,0x28,0x01,0x28,0x02,0x40,0x00,0x41,0x00,0x42,0x00,0x44,0x00,0x45,0x00, - 0x46,0x00,0x48,0x00,0x49,0x00,0x4A,0x00,0x4C,0x00,0x4D,0x00,0x4E,0x00,0xFF, - }; - INT32 i; + ram = (UINT8*)BurnMalloc(0x900); - memset(&NMK004_state, 0, sizeof(NMK004_state)); + tlcs90Init(0, 8000000); + tlcs90Open(0); + tlcs90MapMemory(NMK004PROGROM, 0x0000, 0xefff, TLCS90_ROM); + tlcs90MapMemory(ram, 0xf000, 0xf7ff, TLCS90_RAM); + tlcs90SetReadHandler(nmk004_tlcs90_read); + tlcs90SetWriteHandler(nmk004_tlcs90_write); + tlcs90SetWritePortHandler(nmk004_tlcs90_write_port); + tlcs90Close(); - NMK004_state.ymdevice = 0; - NMK004_state.oki1device = 0; - NMK004_state.oki2device = 1; - NMK004_state.rom = NMK004PROGROM; + BurnYM2203Init(1, 1500000, &NMK004YM2203IrqHandler, NMK004SynchroniseStream, NMK004GetTime, 0); + BurnTimerAttachTlcs90(8000000); + BurnYM2203SetRoute(0, BURN_SND_YM2203_YM2203_ROUTE, 0.50, BURN_SND_ROUTE_BOTH); + BurnYM2203SetRoute(0, BURN_SND_YM2203_AY8910_ROUTE_1, 0.50, BURN_SND_ROUTE_BOTH); + BurnYM2203SetRoute(0, BURN_SND_YM2203_AY8910_ROUTE_2, 0.50, BURN_SND_ROUTE_BOTH); + BurnYM2203SetRoute(0, BURN_SND_YM2203_AY8910_ROUTE_3, 1.20, BURN_SND_ROUTE_BOTH); - ym2203_control_port_w(NMK004_state.ymdevice, 0, 0x2f); + MSM6295Init(0, 4000000 / 165, 1); + MSM6295Init(1, 4000000 / 165, 1); + MSM6295SetRoute(0, 0.10, BURN_SND_ROUTE_BOTH); + MSM6295SetRoute(1, 0.10, BURN_SND_ROUTE_BOTH); +} - i = 0; - while (ym2203_init[i] != 0xff) - { - ym2203_control_port_w(NMK004_state.ymdevice, 0, ym2203_init[i++]); - ym2203_write_port_w(NMK004_state.ymdevice, 0, ym2203_init[i++]); +void NMK004_exit() +{ + BurnFree(ram); + + tlcs90Exit(); + BurnYM2203Exit(); + MSM6295Exit(0); + MSM6295Exit(1); +} + +INT32 NMK004Scan(INT32 nAction,INT32 *pnMin) +{ + struct BurnArea ba; + + if (nAction & ACB_VOLATILE) { + memset(&ba, 0, sizeof(ba)); + + ba.Data = ram; + ba.nLen = 0x900; + ba.szName = "tlcs90 ram"; + BurnAcb(&ba); + + tlcs90Scan(nAction); + + BurnYM2203Scan(nAction, pnMin); + MSM6295Scan(0, nAction); + MSM6295Scan(1, nAction); + + SCAN_VAR(to_nmk004); + SCAN_VAR(to_main); + SCAN_VAR(bankdata[0]); + SCAN_VAR(bankdata[1]); } - NMK004_state.oki_playing = 0; + if (nAction & ACB_WRITE) + { + oki_bankswitch(0,bankdata[0]); + oki_bankswitch(1,bankdata[1]); + } - oki_play_sample(0); + return 0; +} - NMK004_state.protection_check = 0; +void NMK004NmiWrite(INT32 data) +{ + data ^= 0xff; // hack - no game works properly without this being inverted. + + tlcs90SetIRQLine(0x20 /*nmi*/, (data & 1) ? TLCS90_IRQSTATUS_ACK : TLCS90_IRQSTATUS_NONE); } void NMK004Write(INT32, INT32 data) { - NMK004_state.from_main = data & 0xff; + to_nmk004 = data & 0xff; } UINT8 NMK004Read() { - return NMK004_state.to_main; + return to_main; } diff --git a/src/burn/devices/nmk004.h b/src/burn/devices/nmk004.h index 889afee0c..46b42880d 100644 --- a/src/burn/devices/nmk004.h +++ b/src/burn/devices/nmk004.h @@ -3,9 +3,12 @@ extern UINT8 *NMK004OKIROM1; extern UINT8 *NMK004PROGROM; void NMK004_init(); +void NMK004_reset(); +void NMK004_exit(); + +void NMK004NmiWrite(INT32 data); void NMK004Write(INT32, INT32 data); UINT8 NMK004Read(); -void NMK004_irq(INT32 irq); INT32 NMK004Scan(INT32 nAction, INT32* pnMin); diff --git a/src/burn/drv/pst90s/d_nmk16.cpp b/src/burn/drv/pst90s/d_nmk16.cpp index f4dd4d977..2e178337e 100644 --- a/src/burn/drv/pst90s/d_nmk16.cpp +++ b/src/burn/drv/pst90s/d_nmk16.cpp @@ -11,39 +11,9 @@ #include "nmk004.h" #if 0 - dolmen -- good - blkheart -- good - mustang -- good - acrobatm -- good - manybloc -- good - stagger1 -- good - tharrier -- good - airattck -- good - macross -- good - redhawkb -- good - popspops -- good - spec2k -- good - firehawk -- good - mangchi -- good - bubble2000 -- good - hachamf -- good -- small gfx issues, need to compare to MAME - redhawki -- good - strahl -- good - bioship -- good - nouryoku -- good - tdragon -- good - tdragon2 -- good (input issues?, I can not confirm) - macross2 -- good (input issues?, I can not confirm) - ssmissin -- good - twinactn -- good - gunnail -- good - raphero -- good -- no sound, cpu NOT emulated (input issues?, I can not confirm) - vandyke -- good - vandykeb -- good -- no sound. cpu NOT emulated :) - grdnstrm -- good - grdnstrmk -- good - bjtwin -- good - sabotenb -- good + strahl -- something is wrong with this game... + bioship -- no music... sfx ok? + macross -- bad sound in-game? tdragonb -- bad sound. Seibu sound needs hooked up properly mustangb -- bad sound. Seibu sound needs hooked up properly @@ -557,6 +527,30 @@ static struct BurnDIPInfo HachamfDIPList[]= STDDIPINFO(Hachamf) +static struct BurnDIPInfo HachamfbDIPList[]= +{ + {0x12, 0xff, 0xff, 0xfd, NULL }, + {0x13, 0xff, 0xff, 0xff, NULL }, + + {0 , 0xfe, 0 , 2, "Language" }, + {0x12, 0x01, 0x02, 0x00, "English" }, + {0x12, 0x01, 0x02, 0x02, "Japanese" }, + + {0 , 0xfe, 0 , 4, "Difficulty" }, + {0x12, 0x01, 0x0c, 0x04, "Easy" }, + {0x12, 0x01, 0x0c, 0x0c, "Normal" }, + {0x12, 0x01, 0x0c, 0x08, "Hard" }, + {0x12, 0x01, 0x0c, 0x00, "Hardest" }, + + {0 , 0xfe, 0 , 4, "Lives" }, + {0x12, 0x01, 0xc0, 0x00, "1" }, + {0x12, 0x01, 0xc0, 0x40, "2" }, + {0x12, 0x01, 0xc0, 0xc0, "3" }, + {0x12, 0x01, 0xc0, 0x80, "4" }, +}; + +STDDIPINFO(Hachamfb) + static struct BurnDIPInfo VandykeDIPList[]= { {0x12, 0xff, 0xff, 0xff, NULL }, @@ -2019,7 +2013,7 @@ static void HachaRAMProt(INT32 offset) case 0xe51e/2: PROT_INPUT(0xe51e/2,0x0f82,0xe008/2,0x00080008); break; case 0xe6b4/2: PROT_INPUT(0xe6b4/2,0x79be,0xe00c/2,0x0008000a); break; case 0xe10e/2: PROT_JSR(0xe10e,0x8007,0x870a); //870a not 9d66 - PROT_JSR(0xe10e,0x8000,0xd9c6); break; + PROT_JSR(0xe10e,0x8000,0xd9c6); break; case 0xe11e/2: PROT_JSR(0xe11e,0x8038,0x972a); // 972a PROT_JSR(0xe11e,0x8031,0xd1f8); break; case 0xe12e/2: PROT_JSR(0xe12e,0x8019,0x9642); // OK-9642 @@ -2926,6 +2920,14 @@ UINT8 __fastcall mustangb_main_read_byte(UINT32 address) return 0; } +static void sync_nmk004() +{ +return; + int cycles = (SekTotalCycles() * 8) / (nNMK004CpuSpeed / 1000000); + + if ((cycles - tlcs90TotalCycles()) > 0) BurnTimerUpdate(cycles); +} + UINT8 __fastcall mustang_main_read_byte(UINT32 address) { switch (address) @@ -2944,6 +2946,7 @@ UINT8 __fastcall mustang_main_read_byte(UINT32 address) case 0x08000e: case 0x08000f: + sync_nmk004(); return NMK004Read(); } @@ -2964,6 +2967,7 @@ UINT16 __fastcall mustang_main_read_word(UINT32 address) return (DrvDips[0] << 8) | DrvDips[1]; case 0x08000e: + sync_nmk004(); return NMK004Read(); } @@ -2980,7 +2984,13 @@ void __fastcall mustang_main_write_word(UINT32 address, UINT16 data) // *flipscreen = data & 1; return; + case 0x080016: + sync_nmk004(); + NMK004NmiWrite(data); + return; + case 0x08001e: + sync_nmk004(); NMK004Write(0, data); return; } @@ -3010,6 +3020,10 @@ UINT8 __fastcall acrobatm_main_read_byte(UINT32 address) case 0x0c000a: case 0x0c000b: return DrvDips[1]; + + case 0x0c000e: + sync_nmk004(); + return NMK004Read(); } return 0; @@ -3032,6 +3046,7 @@ UINT16 __fastcall acrobatm_main_read_word(UINT32 address) return DrvDips[1]; case 0x0c000e: + sync_nmk004(); return NMK004Read(); } @@ -3047,6 +3062,10 @@ void __fastcall acrobatm_main_write_word(UINT32 address, UINT16 data) // *flipscreen = data & 1; return; + case 0x0c0016: + NMK004NmiWrite(data); + return; + case 0x0c0018: case 0x0c0019: if ((data & 0xff) != 0xff) { @@ -3056,6 +3075,7 @@ void __fastcall acrobatm_main_write_word(UINT32 address, UINT16 data) case 0x0c001e: case 0x0c001f: + sync_nmk004(); NMK004Write(0, data); return; } @@ -3070,6 +3090,11 @@ void __fastcall acrobatm_main_write_byte(UINT32 address, UINT8 data) // *flipscreen = data & 1; return; + case 0x0c0016: + case 0x0c0017: + NMK004NmiWrite(data); + return; + case 0x0c0018: case 0x0c0019: if (data != 0xff) { @@ -3079,6 +3104,7 @@ void __fastcall acrobatm_main_write_byte(UINT32 address, UINT8 data) case 0x0c001e: case 0x0c001f: + sync_nmk004(); NMK004Write(0, data); return; } @@ -3103,6 +3129,11 @@ UINT8 __fastcall tdragon_main_read_byte(UINT32 address) case 0x0c000a: case 0x0c000b: return DrvDips[1]; + + case 0x0c000e: + case 0x0c000f: + sync_nmk004(); + return NMK004Read(); } return 0; @@ -3125,6 +3156,7 @@ UINT16 __fastcall tdragon_main_read_word(UINT32 address) return DrvDips[1]; case 0x0c000e: + sync_nmk004(); return NMK004Read(); } @@ -3145,6 +3177,12 @@ void __fastcall tdragon_main_write_word(UINT32 address, UINT16 data) // *flipscreen = data & 1; return; + case 0x0c0016: + case 0x0c0017: + sync_nmk004(); + NMK004NmiWrite(data); + return; + case 0x0c0018: if ((data & 0xff) != 0xff) { *tilebank = data; @@ -3152,6 +3190,7 @@ void __fastcall tdragon_main_write_word(UINT32 address, UINT16 data) return; case 0x0c001e: + sync_nmk004(); NMK004Write(0, data); return; } @@ -3172,6 +3211,12 @@ void __fastcall tdragon_main_write_byte(UINT32 address, UINT8 data) // *flipscreen = data & 1; return; + case 0x0c0016: + case 0x0c0017: + sync_nmk004(); + NMK004NmiWrite(data); + return; + case 0x0c0018: case 0x0c0019: if (data != 0xff) { @@ -3181,6 +3226,7 @@ void __fastcall tdragon_main_write_byte(UINT32 address, UINT8 data) case 0x0c001e: case 0x0c001f: + sync_nmk004(); NMK004Write(0, data); return; } @@ -3248,6 +3294,11 @@ void __fastcall macross_main_write_word(UINT32 address, UINT16 data) // *flipscreen = data & 1; return; + case 0x080016: + case 0x080017: + NMK004NmiWrite(data^1); + return; + case 0x080018: if ((data & 0xff) != 0xff) { *tilebank = data; @@ -3276,6 +3327,11 @@ void __fastcall macross_main_write_byte(UINT32 address, UINT8 data) // *flipscreen = data & 1; return; + case 0x080016: + case 0x080017: + NMK004NmiWrite(data^1); + return; + case 0x080018: case 0x080019: if ((data & 0xff) != 0xff) { @@ -3376,12 +3432,17 @@ UINT8 __fastcall hachamf_main_read_byte(UINT32 address) case 0x080003: return DrvInputs[1] >> ((~address & 1) << 3); + case 0x080008: + case 0x080009: + return DrvDips[0]; + case 0x08000a: case 0x08000b: - return 0; // ?? + return DrvDips[1]; case 0x08000e: case 0x08000f: + sync_nmk004(); return NMK004Read(); } @@ -3399,12 +3460,13 @@ UINT16 __fastcall hachamf_main_read_word(UINT32 address) return DrvInputs[1]; case 0x080008: - return (DrvDips[0] << 8) | DrvDips[1]; + return DrvDips[0]; case 0x08000a: - return 0; // ?? + return DrvDips[1]; case 0x08000e: + sync_nmk004(); return NMK004Read(); } @@ -3425,6 +3487,12 @@ void __fastcall hachamf_main_write_word(UINT32 address, UINT16 data) // *flipscreen = data & 1; return; + case 0x080016: + case 0x080017: + sync_nmk004(); + NMK004NmiWrite(data); + return; + case 0x080018: if ((data & 0xff) != 0xff) { *tilebank = data & 0xff; @@ -3432,6 +3500,7 @@ void __fastcall hachamf_main_write_word(UINT32 address, UINT16 data) return; case 0x08001e: + sync_nmk004(); NMK004Write(0, data); return; } @@ -3452,6 +3521,12 @@ void __fastcall hachamf_main_write_byte(UINT32 address, UINT8 data) // *flipscreen = data & 1; return; + case 0x080016: + case 0x080017: + sync_nmk004(); + NMK004NmiWrite(data); + return; + case 0x080018: case 0x080019: if ((data & 0xff) != 0xff) { @@ -3461,6 +3536,7 @@ void __fastcall hachamf_main_write_byte(UINT32 address, UINT8 data) case 0x08001e: case 0x08001f: + sync_nmk004(); NMK004Write(0, data); return; } @@ -3785,21 +3861,6 @@ inline static double Macross2GetTime() return (double)ZetTotalCycles() / 4000000; } -static void NMK004YM2203IrqHandler(INT32, INT32 nStatus) -{ - NMK004_irq(nStatus); -} - -inline static double NMK004GetTime() -{ - return (double)SekTotalCycles() / nNMK004CpuSpeed; -} - -inline static INT32 NMK004SynchroniseStream(INT32 nSoundRate) -{ - return (INT64)(SekTotalCycles() * nSoundRate / nNMK004CpuSpeed); -} - static void MSM6295SetInitialBanks(INT32 chips) { INT32 len = DrvSndROM1 - DrvSndROM0; @@ -3913,12 +3974,7 @@ static INT32 NMK004DoReset() SekReset(); SekClose(); - BurnYM2203Reset(); - - MSM6295Reset(0); - MSM6295Reset(1); - - MSM6295SetInitialBanks(2); + NMK004_reset(); SekOpen(0); NMK004_init(); @@ -3945,7 +4001,6 @@ static INT32 MemIndex() DrvTileROM = Next; Next += 0x020000; MSM6295ROM = Next; - DrvSndROM0 = Next; Next += 0x300000; if (strcmp(BurnDrvGetTextA(DRV_NAME), "raphero") == 0 || strcmp(BurnDrvGetTextA(DRV_NAME), "arcadian") == 0) { @@ -3982,6 +4037,7 @@ static INT32 MemIndex() tilebank = Next; Next += 0x000001; RamEnd = Next; + MemEnd = Next; return 0; @@ -4410,8 +4466,10 @@ static INT32 AfegaInit(INT32 (*pLoadCallback)(), void (*pZ80Callback)(), INT32 p return 0; } -static INT32 NMK004Init(INT32 (*pLoadCallback)(), INT32 nCpuSpeed, INT32 pin7high, INT32 irq2) +static INT32 NMK004Init(INT32 (*pLoadCallback)(), INT32 nCpuSpeed) { + BurnSetRefreshRate(56.00); + AllMem = NULL; MemIndex(); INT32 nLen = MemEnd - (UINT8 *)0; @@ -4419,30 +4477,20 @@ static INT32 NMK004Init(INT32 (*pLoadCallback)(), INT32 nCpuSpeed, INT32 pin7hig memset(AllMem, 0, nLen); MemIndex(); + NMK004OKIROM0 = DrvSndROM0; + NMK004OKIROM1 = DrvSndROM1; + NMK004PROGROM = DrvZ80ROM; + nNMK004CpuSpeed = nCpuSpeed; - nNMK004EnableIrq2 = irq2; if (pLoadCallback) { pLoadCallback(); } - BurnSetRefreshRate(56.00); + if (BurnLoadRom(NMK004PROGROM + 0x0000, 0x80, 1)) return 1; // load nmk004 rom ^^ - BurnYM2203Init(1, 1500000, &NMK004YM2203IrqHandler, NMK004SynchroniseStream, NMK004GetTime, 0); - BurnTimerAttachSek(nNMK004CpuSpeed); - BurnYM2203SetRoute(0, BURN_SND_YM2203_YM2203_ROUTE, 2.00, BURN_SND_ROUTE_BOTH); - BurnYM2203SetRoute(0, BURN_SND_YM2203_AY8910_ROUTE_1, 0.50, BURN_SND_ROUTE_BOTH); - BurnYM2203SetRoute(0, BURN_SND_YM2203_AY8910_ROUTE_2, 0.50, BURN_SND_ROUTE_BOTH); - BurnYM2203SetRoute(0, BURN_SND_YM2203_AY8910_ROUTE_3, 0.50, BURN_SND_ROUTE_BOTH); + NMK004_init(); - MSM6295Init(0, 4000000 / (pin7high ? 132 : 165), 1); - MSM6295Init(1, 4000000 / (pin7high ? 132 : 165), 1); - MSM6295SetRoute(0, 0.20, BURN_SND_ROUTE_BOTH); - MSM6295SetRoute(1, 0.20, BURN_SND_ROUTE_BOTH); - - NMK004OKIROM0 = DrvSndROM0; - NMK004OKIROM1 = DrvSndROM1; - NMK004PROGROM = DrvZ80ROM; no_z80 = 1; NMK004_enabled = 1; @@ -4536,9 +4584,7 @@ static INT32 BjtwinExit() static INT32 NMK004Exit() { - BurnYM2203Exit(); - MSM6295Exit(0); - MSM6295Exit(1); + NMK004_exit(); MSM6295ROM = NULL; no_z80 = 0; NMK004_enabled = 0; @@ -5265,8 +5311,6 @@ static INT32 DrvScan(INT32 nAction, INT32 *pnMin) SCAN_VAR(macross2_sound_enable); if (NMK004_enabled) { - SCAN_VAR(nNMK004CpuSpeed); - SCAN_VAR(nNMK004EnableIrq2); NMK004Scan(nAction, pnMin); } @@ -5607,32 +5651,47 @@ static INT32 NMK004Frame() } SekNewFrame(); + tlcs90NewFrame(); + +#define multiplier 8 INT32 nSegment; - INT32 nInterleave = 200; - INT32 nTotalCycles[1] = { nNMK004CpuSpeed / 56 }; + INT32 nInterleave = 256*multiplier; // extremely high interleave! + INT32 nTotalCycles[2] = { nNMK004CpuSpeed / 56, 8000000 / 56 }; + INT32 nCyclesDone[2] = { 0, 0 }; SekOpen(0); + tlcs90Open(0); for (INT32 i = 0; i < nInterleave; i++) { - nSegment = (nTotalCycles[0] / nInterleave) * (i + 1); - BurnTimerUpdate(nSegment); + nSegment = nTotalCycles[0] / nInterleave; - if (i == (nInterleave-1) || i == ((nInterleave / 2) - 1)) { + nCyclesDone[0] += SekRun(nSegment); + + if (i == (241*multiplier)) { + if (strncmp(BurnDrvGetTextA(DRV_NAME), "strahl", 6) == 0) { + memcpy (DrvSprBuf2, Drv68KRAM + 0xf000, 0x1000); + } else { + memcpy (DrvSprBuf2, Drv68KRAM + 0x8000, 0x1000); + } + } + + if (i == (25*multiplier) || i == (153*multiplier)) { SekSetIRQLine(1, SEK_IRQSTATUS_AUTO); } - if (i == ((nInterleave/2)-1) && nNMK004EnableIrq2) { - SekRun(0); + if (i == 0) { SekSetIRQLine(2, SEK_IRQSTATUS_AUTO); } - if (i == (nInterleave-1)) { - SekRun(0); + if (i == (241*multiplier)) { SekSetIRQLine(4, SEK_IRQSTATUS_AUTO); } + + nSegment = (SekTotalCycles() * 8) / (nNMK004CpuSpeed / 1000000); // sync to 68k? + BurnTimerUpdate(nSegment); } - BurnTimerEndFrame(nTotalCycles[0]); + BurnTimerEndFrame(nTotalCycles[1]); if (pBurnSoundOut) { BurnYM2203Update(pBurnSoundOut, nBurnSoundLen); @@ -5640,18 +5699,13 @@ static INT32 NMK004Frame() MSM6295Render(1, pBurnSoundOut, nBurnSoundLen); } + tlcs90Close(); SekClose(); if (pBurnDraw) { BurnDrvRedraw(); } - if (strncmp(BurnDrvGetTextA(DRV_NAME), "strahl", 6) == 0) { - memcpy (DrvSprBuf2, Drv68KRAM + 0xf000, 0x1000); - } else { - memcpy (DrvSprBuf2, Drv68KRAM + 0x8000, 0x1000); - } - return 0; } @@ -5767,6 +5821,29 @@ static void decode_tdragonb() //------------------------------------------------------------------------------------------------------------- +static struct BurnRomInfo emptyRomDesc[] = { + { "", 0, 0, 0 }, +}; + +// NMK004 Internal ROM + +static struct BurnRomInfo nmk004RomDesc[] = { + { "nmk004.bin", 0x002000, 0x83b6f611, BRF_PRG | BRF_BIOS }, // 0x80 tlcs90 internal rom +}; + +STD_ROM_PICK(nmk004) +STD_ROM_FN(nmk004) + +struct BurnDriver BurnDrvnmk004 = { + "nmk004", NULL, NULL, NULL, "1990", + "NMK004 Internal ROM\0", "internal rom", "N M K Corporation", "NMK16", + NULL, NULL, NULL, NULL, + BDF_BOARDROM, 0, HARDWARE_MISC_POST90S, GBF_BIOS, 0, + NULL, nmk004RomInfo, nmk004RomName, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, 0, + 320, 224, 4, 3 +}; + // Task Force Harrier @@ -7791,7 +7868,7 @@ static struct BurnRomInfo mustangRomDesc[] = { { "90058-11", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 10 }; -STD_ROM_PICK(mustang) +STDROMPICKEXT(mustang, mustang, nmk004) STD_ROM_FN(mustang) static INT32 MustangLoadCallback() @@ -7810,10 +7887,10 @@ static INT32 MustangLoadCallback() if (BurnLoadRom(DrvGfxROM2 + 0x00001, 6, 2)) return 1; if (BurnLoadRom(DrvSndROM0 + 0x20000, 7, 1)) return 1; - memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x20000, 0x20000); + memcpy (DrvSndROM0 + 0x000000, DrvSndROM0 + 0x20000, 0x20000); if (BurnLoadRom(DrvSndROM1 + 0x20000, 8, 1)) return 1; - memcpy (DrvSndROM1 + 0x00000, DrvSndROM1 + 0x20000, 0x20000); + memcpy (DrvSndROM1 + 0x000000, DrvSndROM1 + 0x20000, 0x20000); DrvGfxDecode(0x20000, 0x80000, 0x100000); } @@ -7837,11 +7914,11 @@ static INT32 MustangLoadCallback() static INT32 MustangInit() { - return NMK004Init(MustangLoadCallback, 10000000, 0, 1); + return NMK004Init(MustangLoadCallback, 10000000); } struct BurnDriver BurnDrvMustang = { - "mustang", NULL, NULL, NULL, "1990", + "mustang", NULL, "nmk004", NULL, "1990", "US AAF Mustang (25th May. 1990)\0", NULL, "UPL", "NMK16", NULL, NULL, NULL, NULL, BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, @@ -7874,11 +7951,11 @@ static struct BurnRomInfo mustangsRomDesc[] = { { "90058-11", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 10 }; -STD_ROM_PICK(mustangs) +STDROMPICKEXT(mustangs, mustangs, nmk004) STD_ROM_FN(mustangs) struct BurnDriver BurnDrvMustangs = { - "mustangs", "mustang", NULL, NULL, "1990", + "mustangs", "mustang", "nmk004", NULL, "1990", "US AAF Mustang (25th May. 1990 / Seoul Trading)\0", NULL, "UPL (Seoul Trading license)", "NMK16", NULL, NULL, NULL, NULL, BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, @@ -8048,7 +8125,7 @@ static struct BurnRomInfo tdragonRomDesc[] = { { "91070.10", 0x000100, 0xe6ead349, 0 | BRF_OPT }, // 9 }; -STD_ROM_PICK(tdragon) +STDROMPICKEXT(tdragon, tdragon, nmk004) STD_ROM_FN(tdragon) static INT32 TdragonLoadCallback() @@ -8067,10 +8144,10 @@ static INT32 TdragonLoadCallback() BurnByteswap(DrvGfxROM2, 0x100000); if (BurnLoadRom(DrvSndROM0 + 0x20000, 6, 1)) return 1; - memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x20000, 0x20000); + memcpy (DrvSndROM0 + 0x000000, DrvSndROM0 + 0x20000, 0x20000); if (BurnLoadRom(DrvSndROM1 + 0x20000, 7, 1)) return 1; - memcpy (DrvSndROM1 + 0x00000, DrvSndROM1 + 0x20000, 0x20000); + memcpy (DrvSndROM1 + 0x000000, DrvSndROM1 + 0x20000, 0x20000); DrvGfxDecode(0x20000, 0x100000, 0x100000); } @@ -8099,11 +8176,11 @@ static INT32 TdragonLoadCallback() static INT32 TdragonInit() { - return NMK004Init(TdragonLoadCallback, 8000000, 0, 1); + return NMK004Init(TdragonLoadCallback, 8000000); } struct BurnDriver BurnDrvTdragon = { - "tdragon", NULL, NULL, NULL, "1991", + "tdragon", NULL, "nmk004", NULL, "1991", "Thunder Dragon (9th Jan. 1992)\0", "No sound", "NMK (Tecmo license)", "NMK16", NULL, NULL, NULL, NULL, BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, @@ -8135,11 +8212,11 @@ static struct BurnRomInfo tdragon1RomDesc[] = { { "91070.10", 0x000100, 0xe6ead349, 0 | BRF_OPT }, // 9 }; -STD_ROM_PICK(tdragon1) +STDROMPICKEXT(tdragon1, tdragon1, nmk004) STD_ROM_FN(tdragon1) struct BurnDriver BurnDrvTdragon1 = { - "tdragon1", "tdragon", NULL, NULL, "1991", + "tdragon1", "tdragon", "nmk004", NULL, "1991", "Thunder Dragon (4th Jun. 1991)\0", NULL, "NMK (Tecmo license)", "NMK16", NULL, NULL, NULL, NULL, BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, @@ -8238,7 +8315,7 @@ static struct BurnRomInfo acrobatmRomDesc[] = { { "11_ic80.bin", 0x000100, 0x633ab1c9, 0 | BRF_OPT }, // 10 }; -STD_ROM_PICK(acrobatm) +STDROMPICKEXT(acrobatm, acrobatm, nmk004) STD_ROM_FN(acrobatm) static INT32 AcrobatmLoadCallback() @@ -8257,10 +8334,10 @@ static INT32 AcrobatmLoadCallback() if (BurnLoadRom(DrvGfxROM2 + 0x100000, 6, 1)) return 1; if (BurnLoadRom(DrvSndROM0 + 0x020000, 7, 1)) return 1; - memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x20000, 0x20000); + memcpy (DrvSndROM0 + 0x000000, DrvSndROM0 + 0x20000, 0x20000); if (BurnLoadRom(DrvSndROM1 + 0x020000, 8, 1)) return 1; - memcpy (DrvSndROM1 + 0x00000, DrvSndROM1 + 0x20000, 0x20000); + memcpy (DrvSndROM1 + 0x000000, DrvSndROM1 + 0x20000, 0x20000); DrvGfxDecode(0x10000, 0x100000, 0x200000); } @@ -8284,11 +8361,11 @@ static INT32 AcrobatmLoadCallback() static INT32 AcrobatmInit() { - return NMK004Init(AcrobatmLoadCallback, 10000000, 0, 1); + return NMK004Init(AcrobatmLoadCallback, 10000000); } struct BurnDriver BurnDrvAcrobatm = { - "acrobatm", NULL, NULL, NULL, "1991", + "acrobatm", NULL, "nmk004", NULL, "1991", "Acrobat Mission\0", NULL, "UPL (Taito license)", "NMK16", NULL, NULL, NULL, NULL, BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, @@ -8320,7 +8397,7 @@ static struct BurnRomInfo macrossRomDesc[] = { { "921a10", 0x000020, 0x8371e42d, 0 | BRF_OPT }, // 9 }; -STD_ROM_PICK(macross) +STDROMPICKEXT(macross, macross, nmk004) STD_ROM_FN(macross) static INT32 MacrossLoadCallback() @@ -8338,10 +8415,10 @@ static INT32 MacrossLoadCallback() BurnByteswap(DrvGfxROM2, 0x200000); if (BurnLoadRom(DrvSndROM0 + 0x020000, 5, 1)) return 1; - memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x20000, 0x20000); + memcpy (DrvSndROM0 + 0x000000, DrvSndROM0 + 0x20000, 0x20000); if (BurnLoadRom(DrvSndROM1 + 0x020000, 6, 1)) return 1; - memcpy (DrvSndROM1 + 0x00000, DrvSndROM1 + 0x20000, 0x20000); + memcpy (DrvSndROM1 + 0x000000, DrvSndROM1 + 0x20000, 0x20000); decode_gfx(0x200000, 0x200000); DrvGfxDecode(0x20000, 0x200000, 0x200000); @@ -8367,11 +8444,11 @@ static INT32 MacrossLoadCallback() static INT32 MacrossInit() { Macrossmode = 1; - return NMK004Init(MacrossLoadCallback, 10000000, 0, 0); + return NMK004Init(MacrossLoadCallback, 10000000); } struct BurnDriver BurnDrvMacross = { - "macross", NULL, NULL, NULL, "1992", + "macross", NULL, "nmk004", NULL, "1992", "Super Spacefortress Macross / Chou-Jikuu Yousai Macross\0", NULL, "Banpresto", "NMK16", NULL, NULL, NULL, NULL, BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, @@ -8404,7 +8481,7 @@ static struct BurnRomInfo gunnailRomDesc[] = { { "10.bpr", 0x000020, 0xc60103c8, 0 | BRF_OPT }, // 10 }; -STD_ROM_PICK(gunnail) +STDROMPICKEXT(gunnail, gunnail, nmk004) STD_ROM_FN(gunnail) static INT32 GunnailLoadCallback() @@ -8423,10 +8500,10 @@ static INT32 GunnailLoadCallback() BurnByteswap(DrvGfxROM2, 0x200000); if (BurnLoadRom(DrvSndROM0 + 0x020000, 6, 1)) return 1; - memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x20000, 0x20000); + memcpy (DrvSndROM0 + 0x000000, DrvSndROM0 + 0x20000, 0x20000); if (BurnLoadRom(DrvSndROM1 + 0x020000, 7, 1)) return 1; - memcpy (DrvSndROM1 + 0x00000, DrvSndROM1 + 0x20000, 0x20000); + memcpy (DrvSndROM1 + 0x000000, DrvSndROM1 + 0x20000, 0x20000); decode_gfx(0x100000, 0x200000); DrvGfxDecode(0x20000, 0x100000, 0x200000); @@ -8452,11 +8529,11 @@ static INT32 GunnailLoadCallback() static INT32 GunnailInit() { - return NMK004Init(GunnailLoadCallback, 12000000, 0, 0); + return NMK004Init(GunnailLoadCallback, 12000000); } struct BurnDriver BurnDrvGunnail = { - "gunnail", NULL, NULL, NULL, "1993", + "gunnail", NULL, "nmk004", NULL, "1993", "GunNail (28th May. 1992)\0", NULL, "NMK / Tecmo", "NMK16", NULL, NULL, NULL, NULL, BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_VERSHOOT, 0, @@ -8488,7 +8565,7 @@ static struct BurnRomInfo blkheartRomDesc[] = { { "10.bpr", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 9 }; -STD_ROM_PICK(blkheart) +STDROMPICKEXT(blkheart, blkheart, nmk004) STD_ROM_FN(blkheart) static INT32 BlkheartLoadCallback() @@ -8507,10 +8584,11 @@ static INT32 BlkheartLoadCallback() BurnByteswap(DrvGfxROM2, 0x100000); if (BurnLoadRom(DrvSndROM0 + 0x020000, 6, 1)) return 1; - memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x20000, 0x20000); + memcpy (DrvSndROM0 + 0x000000, DrvSndROM0 + 0x20000, 0x20000); if (BurnLoadRom(DrvSndROM1 + 0x020000, 7, 1)) return 1; - memcpy (DrvSndROM1 + 0x00000, DrvSndROM1 + 0x20000, 0x20000); + memcpy (DrvSndROM1 + 0x000000, DrvSndROM1 + 0x20000, 0x20000); + DrvGfxDecode(0x20000, 0x100000, 0x100000); } @@ -8534,11 +8612,11 @@ static INT32 BlkheartLoadCallback() static INT32 BlkheartInit() { - return NMK004Init(BlkheartLoadCallback, 8000000, 0, 0); + return NMK004Init(BlkheartLoadCallback, 8000000); } struct BurnDriver BurnDrvBlkheart = { - "blkheart", NULL, NULL, NULL, "1991", + "blkheart", NULL, "nmk004", NULL, "1991", "Black Heart\0", NULL, "UPL", "NMK16", NULL, NULL, NULL, NULL, BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, @@ -8570,11 +8648,11 @@ static struct BurnRomInfo blkheartjRomDesc[] = { { "10.bpr", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 9 }; -STD_ROM_PICK(blkheartj) +STDROMPICKEXT(blkheartj, blkheartj, nmk004) STD_ROM_FN(blkheartj) struct BurnDriver BurnDrvBlkheartj = { - "blkheartj", "blkheart", NULL, NULL, "1991", + "blkheartj", "blkheart", "nmk004", NULL, "1991", "Black Heart (Japan)\0", NULL, "UPL", "NMK16", NULL, NULL, NULL, NULL, BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, @@ -8609,7 +8687,7 @@ static struct BurnRomInfo vandykeRomDesc[] = { { "ic101.bpr", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 12 }; -STD_ROM_PICK(vandyke) +STDROMPICKEXT(vandyke, vandyke, nmk004) STD_ROM_FN(vandyke) static INT32 VandykeLoadCallback() @@ -8630,10 +8708,10 @@ static INT32 VandykeLoadCallback() if (BurnLoadRom(DrvGfxROM2 + 0x100001, 8, 2)) return 1; if (BurnLoadRom(DrvSndROM0 + 0x020000, 9, 1)) return 1; - memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x20000, 0x20000); + memcpy (DrvSndROM0 + 0x000000, DrvSndROM0 + 0x20000, 0x20000); if (BurnLoadRom(DrvSndROM1 + 0x020000, 10, 1)) return 1; - memcpy (DrvSndROM1 + 0x00000, DrvSndROM1 + 0x20000, 0x20000); + memcpy (DrvSndROM1 + 0x000000, DrvSndROM1 + 0x20000, 0x20000); DrvGfxDecode(0x10000, 0x80000, 0x200000); } @@ -8657,11 +8735,11 @@ static INT32 VandykeLoadCallback() static INT32 VandykeInit() { - return NMK004Init(VandykeLoadCallback, 10000000, 0, 1); + return NMK004Init(VandykeLoadCallback, 10000000); } struct BurnDriver BurnDrvVandyke = { - "vandyke", NULL, NULL, NULL, "1990", + "vandyke", NULL, "nmk004", NULL, "1990", "Vandyke (Japan)\0", NULL, "UPL", "NMK16", NULL, NULL, NULL, NULL, BDF_GAME_WORKING | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, @@ -8696,11 +8774,11 @@ static struct BurnRomInfo vandykejalRomDesc[] = { { "ic101.bpr", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 12 }; -STD_ROM_PICK(vandykejal) +STDROMPICKEXT(vandykejal, vandykejal, nmk004) STD_ROM_FN(vandykejal) struct BurnDriver BurnDrvVandykejal = { - "vandykejal", "vandyke", NULL, NULL, "1990", + "vandykejal", "vandyke", "nmk004", NULL, "1990", "Vandyke (Jaleco, Set 1)\0", NULL, "UPL (Jaleco license)", "NMK16", NULL, NULL, NULL, NULL, BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, @@ -8735,11 +8813,11 @@ static struct BurnRomInfo vandykejal2RomDesc[] = { { "ic101.bpr", 0x000100, 0xcfdbb86c, 0 | BRF_OPT }, // 12 }; -STD_ROM_PICK(vandykejal2) +STDROMPICKEXT(vandykejal2, vandykejal2, nmk004) STD_ROM_FN(vandykejal2) struct BurnDriver BurnDrvVandykejal2 = { - "vandykejal2", "vandyke", NULL, NULL, "1990", + "vandykejal2", "vandyke", "nmk004", NULL, "1990", "Vandyke (Jaleco, Set 2)\0", NULL, "UPL (Jaleco license)", "NMK16", NULL, NULL, NULL, NULL, BDF_GAME_WORKING | BDF_CLONE | BDF_ORIENTATION_VERTICAL, 2, HARDWARE_MISC_POST90S, GBF_SCRFIGHT, 0, @@ -8831,7 +8909,7 @@ static INT32 VandykebInit() { input_high[0] = 0x0040; // or it locks up - return NMK004Init(VandykebLoadCallback, 10000000, 0, 1); + return NMK004Init(VandykebLoadCallback, 10000000); } struct BurnDriver BurnDrvVandykeb = { @@ -8864,7 +8942,7 @@ static struct BurnRomInfo hachamfRomDesc[] = { { "91076-3.45", 0x080000, 0xb25ed93b, 7 | BRF_SND }, // 7 OKI2 Samples }; -STD_ROM_PICK(hachamf) +STDROMPICKEXT(hachamf, hachamf, nmk004) STD_ROM_FN(hachamf) static INT32 HachamfLoadCallback() @@ -8883,10 +8961,10 @@ static INT32 HachamfLoadCallback() BurnByteswap(DrvGfxROM2, 0x100000); if (BurnLoadRom(DrvSndROM0 + 0x020000, 6, 1)) return 1; - memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x20000, 0x20000); + memcpy (DrvSndROM0 + 0x000000, DrvSndROM0 + 0x20000, 0x20000); if (BurnLoadRom(DrvSndROM1 + 0x020000, 7, 1)) return 1; - memcpy (DrvSndROM1 + 0x00000, DrvSndROM1 + 0x20000, 0x20000); + memcpy (DrvSndROM1 + 0x000000, DrvSndROM1 + 0x20000, 0x20000); DrvGfxDecode(0x20000, 0x100000, 0x100000); } @@ -8915,11 +8993,11 @@ static INT32 HachamfLoadCallback() static INT32 HachamfInit() { - return NMK004Init(HachamfLoadCallback, 10000000, 0, 0); + return NMK004Init(HachamfLoadCallback, 10000000); } struct BurnDriver BurnDrvHachamf = { - "hachamf", NULL, NULL, NULL, "1991", + "hachamf", NULL, "nmk004", NULL, "1991", "Hacha Mecha Fighter (19th Sep. 1991)\0", NULL, "NMK", "NMK16", NULL, NULL, NULL, NULL, BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, @@ -8929,6 +9007,85 @@ struct BurnDriver BurnDrvHachamf = { }; +// Hacha Mecha Fighter (19th Sep. 1991, unprotected, bootleg Thunder Dragon conversion) + +static struct BurnRomInfo hachamfbRomDesc[] = { + { "8", 0x020000, 0x14845B65, 1 | BRF_PRG | BRF_ESS }, // 0 68k code + { "7", 0x020000, 0x069CA579, 1 | BRF_PRG | BRF_ESS }, // 1 + + { "1.70", 0x010000, 0x9e6f48fc, 2 | BRF_PRG | BRF_ESS }, // 2 NMK004 data + + { "5.95", 0x020000, 0x29fb04a2, 3 | BRF_GRA }, // 3 Characters + + { "91076-4.101", 0x100000, 0xdf9653a4, 4 | BRF_GRA }, // 4 Tiles + + { "91076-8.57", 0x100000, 0x7fd0f556, 5 | BRF_GRA }, // 5 Sprites + + { "91076-2.46", 0x080000, 0x3f1e67f2, 6 | BRF_SND }, // 6 OKI1 Samples + + { "91076-3.45", 0x080000, 0xb25ed93b, 7 | BRF_SND }, // 7 OKI2 Samples +}; + +STDROMPICKEXT(hachamfb, hachamfb, nmk004) +STD_ROM_FN(hachamfb) + +static INT32 HachamfbLoadCallback() +{ + { + if (BurnLoadRom(Drv68KROM + 0x000001, 0, 2)) return 1; + if (BurnLoadRom(Drv68KROM + 0x000000, 1, 2)) return 1; + + if (BurnLoadRom(DrvZ80ROM + 0x000000, 2, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM0 + 0x000000, 3, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM1 + 0x000000, 4, 1)) return 1; + + if (BurnLoadRom(DrvGfxROM2 + 0x000000, 5, 1)) return 1; + BurnByteswap(DrvGfxROM2, 0x100000); + + if (BurnLoadRom(DrvSndROM0 + 0x020000, 6, 1)) return 1; + memcpy (DrvSndROM0 + 0x000000, DrvSndROM0 + 0x20000, 0x20000); + + if (BurnLoadRom(DrvSndROM1 + 0x020000, 7, 1)) return 1; + memcpy (DrvSndROM1 + 0x000000, DrvSndROM1 + 0x20000, 0x20000); + + DrvGfxDecode(0x20000, 0x100000, 0x100000); + } + + SekInit(0, 0x68000); + SekOpen(0); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(DrvPalRAM, 0x088000, 0x0887ff, SM_RAM); + SekMapMemory(DrvScrollRAM, 0x08c000, 0x08c3ff, SM_WRITE); + SekMapMemory(DrvBgRAM0, 0x090000, 0x093fff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x09c000, 0x09c7ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x0f0000, 0x0fffff, SM_RAM); + SekSetWriteWordHandler(0, hachamf_main_write_word); + SekSetWriteByteHandler(0, hachamf_main_write_byte); + SekSetReadWordHandler(0, hachamf_main_read_word); + SekSetReadByteHandler(0, hachamf_main_read_byte); + SekClose(); + + return 0; +} + +static INT32 HachamfbInit() +{ + return NMK004Init(HachamfbLoadCallback, 10000000); +} + +struct BurnDriver BurnDrvHachamfb = { + "hachamfb", "hachamf", "nmk004", NULL, "1991", + "Hacha Mecha Fighter (19th Sep. 1991, unprotected, bootleg Thunder Dragon conversion)\0", NULL, "bootleg", "NMK16", + NULL, NULL, NULL, NULL, + BDF_GAME_WORKING | BDF_CLONE | BDF_BOOTLEG, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, + NULL, hachamfbRomInfo, hachamfbRomName, NULL, NULL, CommonInputInfo, HachamfbDIPInfo, + HachamfbInit, NMK004Exit, NMK004Frame, HachamfDraw, DrvScan, NULL, 0x400, + 256, 224, 4, 3 +}; + + // Koutetsu Yousai Strahl (Japan set 1) static struct BurnRomInfo strahlRomDesc[] = { @@ -8952,7 +9109,7 @@ static struct BurnRomInfo strahlRomDesc[] = { { "str9pew1.639", 0x080000, 0x6bb3eb9f, 7 | BRF_SND }, // 10 OKI2 Samples }; -STD_ROM_PICK(strahl) +STDROMPICKEXT(strahl, strahl, nmk004) STD_ROM_FN(strahl) static INT32 StrahlLoadCallback() @@ -8973,39 +9130,35 @@ static INT32 StrahlLoadCallback() if (BurnLoadRom(DrvGfxROM1 + 0x080000, 8, 1)) return 1; - if (BurnLoadRom(DrvSndROM0 + 0x020000, 9, 1)) return 1; - memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x20000, 0x20000); + if (BurnLoadRom(DrvSndROM0 + 0x100000, 9, 1)) return 1; + memcpy (DrvSndROM0 + 0x000000, DrvSndROM0 + 0x100000, 0x20000); + memcpy (DrvSndROM0 + 0x080000, DrvSndROM0 + 0x120000, 0x20000); + memcpy (DrvSndROM0 + 0x060000, DrvSndROM0 + 0x140000, 0x20000); + memcpy (DrvSndROM0 + 0x040000, DrvSndROM0 + 0x160000, 0x20000); - if (BurnLoadRom(DrvSndROM1 + 0x020000, 10, 1)) return 1; - memcpy (DrvSndROM1 + 0x00000, DrvSndROM1 + 0x20000, 0x20000); + if (BurnLoadRom(DrvSndROM1 + 0x100000, 10, 1)) return 1; + memcpy (DrvSndROM1 + 0x000000, DrvSndROM1 + 0x100000, 0x20000); + memcpy (DrvSndROM1 + 0x080000, DrvSndROM1 + 0x120000, 0x20000); + memcpy (DrvSndROM1 + 0x060000, DrvSndROM1 + 0x140000, 0x20000); + memcpy (DrvSndROM1 + 0x040000, DrvSndROM1 + 0x160000, 0x20000); DrvGfxDecode(0x10000, 0x100000, 0x200000); } - { - *((UINT16*)(Drv68KROM + 0x79e)) = 0x4e71; // remove protection - *((UINT16*)(Drv68KROM + 0x7a0)) = 0x4e71; - *((UINT16*)(Drv68KROM + 0x7a2)) = 0x4e71; - *((UINT16*)(Drv68KROM + 0x8e0)) = 0x4e71; // force pass rom check - *((UINT16*)(Drv68KROM + 0x8e2)) = 0x4e71; - *((UINT16*)(Drv68KROM + 0x968)) = 0x4e71; - *((UINT16*)(Drv68KROM + 0x96a)) = 0x4e71; - } - SekInit(0, 0x68000); SekOpen(0); - SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); + SekMapMemory(Drv68KROM, 0x000000, 0x03ffff, SM_ROM); SekMapMemory(DrvScrollRAM, 0x084000, 0x0843ff, SM_RAM); SekMapMemory(DrvScrollRAM + 0x400, 0x088000, 0x0883ff, SM_RAM); - SekMapMemory(DrvPalRAM, 0x08c000, 0x08c7ff, SM_RAM); - SekMapMemory(DrvBgRAM0, 0x090000, 0x093fff, SM_RAM); - SekMapMemory(DrvBgRAM1, 0x094000, 0x097fff, SM_RAM); - SekMapMemory(DrvTxRAM, 0x09c000, 0x09c7ff, SM_RAM); - SekMapMemory(Drv68KRAM, 0x0f0000, 0x0fffff, SM_RAM); - SekSetWriteWordHandler(0, macross_main_write_word); - SekSetWriteByteHandler(0, macross_main_write_byte); - SekSetReadWordHandler(0, macross_main_read_word); - SekSetReadByteHandler(0, macross_main_read_byte); + SekMapMemory(DrvPalRAM, 0x08c000, 0x08c7ff, SM_RAM); + SekMapMemory(DrvBgRAM0, 0x090000, 0x093fff, SM_RAM); + SekMapMemory(DrvBgRAM1, 0x094000, 0x097fff, SM_RAM); + SekMapMemory(DrvTxRAM, 0x09c000, 0x09c7ff, SM_RAM); + SekMapMemory(Drv68KRAM, 0x0f0000, 0x0fffff, SM_RAM); + SekSetWriteWordHandler(0, macross_main_write_word); + SekSetWriteByteHandler(0, macross_main_write_byte); + SekSetReadWordHandler(0, macross_main_read_word); + SekSetReadByteHandler(0, macross_main_read_byte); SekClose(); return 0; @@ -9013,11 +9166,11 @@ static INT32 StrahlLoadCallback() static INT32 StrahlInit() { - return NMK004Init(StrahlLoadCallback, 12000000, 0, 1); + return NMK004Init(StrahlLoadCallback, 12000000); } struct BurnDriver BurnDrvStrahl = { - "strahl", NULL, NULL, NULL, "1992", + "strahl", NULL, "nmk004", NULL, "1992", "Koutetsu Yousai Strahl (Japan set 1)\0", NULL, "UPL", "NMK16", NULL, NULL, NULL, NULL, BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, @@ -9050,11 +9203,11 @@ static struct BurnRomInfo strahlaRomDesc[] = { { "str9pew1.639", 0x080000, 0x6bb3eb9f, 7 | BRF_SND }, // 10 OKI2 Samples }; -STD_ROM_PICK(strahla) +STDROMPICKEXT(strahla, strahla, nmk004) STD_ROM_FN(strahla) struct BurnDriver BurnDrvStrahla = { - "strahla", "strahl", NULL, NULL, "1992", + "strahla", "strahl", "nmk004", NULL, "1992", "Koutetsu Yousai Strahl (Japan set 2)\0", NULL, "UPL", "NMK16", NULL, NULL, NULL, NULL, BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, @@ -9092,7 +9245,7 @@ static struct BurnRomInfo bioshipRomDesc[] = { { "82s123.ic154", 0x000020, 0x0f789fc7, 0 | BRF_OPT }, // 13 }; -STD_ROM_PICK(bioship) +STDROMPICKEXT(bioship, bioship, nmk004) STD_ROM_FN(bioship) static INT32 BioshipLoadCallback() @@ -9115,10 +9268,10 @@ static INT32 BioshipLoadCallback() if (BurnLoadRom(DrvTileROM + 0x000000, 8, 2)) return 1; if (BurnLoadRom(DrvSndROM0 + 0x020000, 9, 1)) return 1; - memcpy (DrvSndROM0 + 0x00000, DrvSndROM0 + 0x20000, 0x20000); + memcpy (DrvSndROM0 + 0x000000, DrvSndROM0 + 0x20000, 0x20000); if (BurnLoadRom(DrvSndROM1 + 0x020000, 10, 1)) return 1; - memcpy (DrvSndROM1 + 0x00000, DrvSndROM1 + 0x20000, 0x20000); + memcpy (DrvSndROM1 + 0x000000, DrvSndROM1 + 0x20000, 0x20000); DrvGfxDecode(0x10000, 0x100000, 0x80000); } @@ -9142,11 +9295,11 @@ static INT32 BioshipLoadCallback() static INT32 BioshipInit() { - return NMK004Init(BioshipLoadCallback, 10000000, 1, 1); + return NMK004Init(BioshipLoadCallback, 10000000); } struct BurnDriver BurnDrvBioship = { - "bioship", NULL, NULL, NULL, "1990", + "bioship", NULL, "nmk004", NULL, "1990", "Bio-ship Paladin\0", NULL, "UPL (American Sammy license)", "NMK16", NULL, NULL, NULL, NULL, BDF_GAME_WORKING, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, @@ -9184,11 +9337,11 @@ static struct BurnRomInfo sbsgomoRomDesc[] = { { "82s123.ic154", 0x000020, 0x0f789fc7, 0 | BRF_OPT }, // 13 }; -STD_ROM_PICK(sbsgomo) +STDROMPICKEXT(sbsgomo, sbsgomo, nmk004) STD_ROM_FN(sbsgomo) struct BurnDriver BurnDrvSbsgomo = { - "sbsgomo", "bioship", NULL, NULL, "1990", + "sbsgomo", "bioship", "nmk004", NULL, "1990", "Space Battle Ship Gomorrah\0", NULL, "UPL", "NMK16", NULL, NULL, NULL, NULL, BDF_GAME_WORKING | BDF_CLONE, 2, HARDWARE_MISC_POST90S, GBF_HORSHOOT, 0, @@ -9227,7 +9380,6 @@ static struct BurnRomInfo rapheroRomDesc[] = { STD_ROM_PICK(raphero) STD_ROM_FN(raphero) - void __fastcall raphero_main_write_byte(UINT32 address, UINT8 data) { switch (address) @@ -9326,8 +9478,6 @@ UINT16 __fastcall raphero_main_read_word(UINT32 address) return 0; } - - static void raphero_sound_bankswitch(INT32 data) { INT32 nBank = ((data & 0x07) * 0x4000) + 0x10000; @@ -9409,7 +9559,6 @@ inline static INT32 RapheroSynchroniseStream(INT32 nSoundRate) return (INT64)(tlcs90TotalCycles() * nSoundRate / 8000000); } - static INT32 RapheroDoReset() { memset (AllRam, 0, RamEnd - AllRam); diff --git a/src/cpu/tlcs90/tlcs90.cpp b/src/cpu/tlcs90/tlcs90.cpp index ad9a0d3f9..7084f8798 100644 --- a/src/cpu/tlcs90/tlcs90.cpp +++ b/src/cpu/tlcs90/tlcs90.cpp @@ -1328,16 +1328,22 @@ static void take_interrupt(t90_Regs *cpustate, e_irq irq) static void check_interrupts(t90_Regs *cpustate) { // e_irq irq; + INT32 mask; if (!(F & IF)) return; -#define check_irq_state_mask(num) \ - if ( cpustate->irq_state & cpustate->irq_mask & (1 << (num)) ) { \ - take_interrupt( cpustate, (num) ); \ - return; \ +#define check_irq_state_mask(num) \ + mask = (1 << num); \ + if (num >= INT0) mask &= cpustate->irq_mask; \ + if ( cpustate->irq_state & mask) { \ + take_interrupt( cpustate, (num) ); \ + return; \ } + check_irq_state_mask(INTSWI) + check_irq_state_mask(INTNMI) + check_irq_state_mask(INTWD) check_irq_state_mask(INT0) check_irq_state_mask(INTT0) check_irq_state_mask(INTT1) @@ -1349,7 +1355,7 @@ static void check_interrupts(t90_Regs *cpustate) check_irq_state_mask(INT2) check_irq_state_mask(INTRX) check_irq_state_mask(INTTX) - check_irq_state_mask(INTMAX) // iq_132, include this one? +// check_irq_state_mask(INTMAX) // include this one? // for (irq = INT0; irq < INTMAX; irq++) // { @@ -2446,12 +2452,6 @@ static void t90_start_timer(t90_Regs *cpustate, int i) // 8-bit mode break; case 1: - // 16-bit mode - if (i & 1) - { - // logerror("%04X: CPU Timer %d clocked by Timer %d overflow signal\n", cpustate->pc.w.l, i,i-1); - return; - } break; case 2: // logerror("%04X: CPU Timer %d, unsupported PPG mode\n", cpustate->pc.w.l, i); @@ -2475,8 +2475,6 @@ static void t90_start_timer(t90_Regs *cpustate, int i) period = cpustate->timer_period * prescaler; - bprintf (0, _T("Timer enable\n")); - cpustate->timer_periods[i] = cpustate->timer_periods_full[i] = period; cpustate->timer_enable[i] = 1; @@ -2500,8 +2498,6 @@ static void t90_start_timer4(t90_Regs *cpustate) period = cpustate->timer_period * prescaler; - bprintf (0, _T("Timer enable\n")); - cpustate->timer_periods[4]= cpustate->timer_periods_full[4] = period; cpustate->timer_enable[4] = 1; @@ -2523,71 +2519,62 @@ static void t90_stop_timer4(t90_Regs *cpustate) void t90_timer_callback(INT32 param) { - t90_Regs *cpustate = &tlcs90_data[0]; //(t90_Regs *)ptr; - int is16bit; + t90_Regs *cpustate = &tlcs90_data[0]; + + int mode, timer_fired; int i = param; if ( (cpustate->internal_registers[ T90_TRUN - T90_IOBASE ] & (1 << i)) == 0 ) return; -// logerror("CPU Timer %d fired! value = %d\n", i,(unsigned)cpustate->timer_value[i]); - - cpustate->timer_value[i]++; - - is16bit = ((cpustate->internal_registers[ T90_TMOD - T90_IOBASE ] >> (i/2 * 2 + 2)) & 0x03) == 1; + timer_fired = 0; + mode = (cpustate->internal_registers[ T90_TMOD - T90_IOBASE ] >> ((i & ~1) + 2)) & 0x03; // Match - - if ( cpustate->timer_value[i] == cpustate->internal_registers[ T90_TREG0+i - T90_IOBASE ] ) + switch (mode) { -// logerror("CPU Timer %d match\n", i); + case 0x02: // 8bit PPG + case 0x03: // 8bit PWM + // TODO: hmm... + case 0x00: // 8bit + cpustate->timer_value[i]++; + if ( cpustate->timer_value[i] == cpustate->internal_registers[ T90_TREG0+i - T90_IOBASE ] ) + timer_fired = 1; + break; - if (is16bit) - { - if (i & 1) - { - if ( cpustate->timer_value[i-1] == cpustate->internal_registers[ T90_TREG0+i-1 - T90_IOBASE ] ) - { - cpustate->timer_value[i] = 0; - cpustate->timer_value[i-1] = 0; - - tlcs90_set_irq_line(INTT0 + i, 1); - } - } - else - tlcs90_set_irq_line(INTT0 + i, 1); - } - else - { - cpustate->timer_value[i] = 0; - tlcs90_set_irq_line(INTT0 + i, 1); - } - - switch (i) - { - case 0: - case 2: - if ( !is16bit ) - if ( (cpustate->internal_registers[ T90_TCLK - T90_IOBASE ] & (0x03 << (i * 2 + 2))) == 0 ) // T0/T1 match signal clocks T1/T3 - t90_timer_callback(i+1); + case 0x01: // 16bit + if(i & 1) break; - } + cpustate->timer_value[i]++; + if(cpustate->timer_value[i] == 0) cpustate->timer_value[i+1]++; + if(cpustate->timer_value[i+1] == cpustate->internal_registers[ T90_TREG0+i+1 - T90_IOBASE ]) + if(cpustate->timer_value[i] == cpustate->internal_registers[ T90_TREG0+i - T90_IOBASE ]) + timer_fired = 1; + break; } - // Overflow - - if ( cpustate->timer_value[i] == 0 ) - { -// logerror("CPU Timer %d overflow\n", i); - - switch (i) - { - case 0: - case 2: - if ( is16bit ) // T0/T1 overflow signal clocks T1/T3 + if(timer_fired) { + // special stuff handling + switch(mode) { + case 0x02: // 8bit PPG + case 0x03: // 8bit PWM + // TODO: hmm... + case 0x00: // 8bit + if(i & 1) + break; + if ( (cpustate->internal_registers[ T90_TCLK - T90_IOBASE ] & (0x0C << (i * 2))) == 0 ) // T0/T1 match signal clocks T1/T3 t90_timer_callback(i+1); - break; + break; + + case 0x01: // 16bit, only can happen for i=0,2 + cpustate->timer_value[i+1] = 0; + tlcs90_set_irq_line(INTT0 + i+1, 1); + break; } + + // regular handling + cpustate->timer_value[i] = 0; + tlcs90_set_irq_line(INTT0 + i, 1); } } @@ -2638,8 +2625,8 @@ void t90_internal_registers_w(UINT16 offset, UINT8 data) { if ( (old ^ data) & (0x20 | (1 << i)) ) // if timer bit or prescaler bit changed { - if ( data == (0x20 | (1 << i)) ) t90_start_timer(cpustate, i); - else t90_stop_timer(cpustate, i); + if ( (data & (1 << i)) && (data & 0x20) ) t90_start_timer(cpustate, i); + else t90_stop_timer(cpustate, i); } } // Timer 4