From 550175d8b8ec9739c5e7810bbdba789cf6b49158 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sun, 12 Jun 2016 09:09:58 +0200 Subject: [PATCH] More work on gameking 3 [PeT] --- scripts/src/cpu.lua | 4 + src/devices/cpu/m6502/om65c02gk.lst | 88 +++++ src/devices/cpu/m6502/r65c02gk.cpp | 109 ++++++ src/devices/cpu/m6502/r65c02gk.h | 74 ++++ src/mame/drivers/gameking.cpp | 525 +++++++++++++++++++++++----- src/mame/layout/gameking.lay | 13 + src/mame/mame.lst | 2 +- 7 files changed, 718 insertions(+), 97 deletions(-) create mode 100644 src/devices/cpu/m6502/om65c02gk.lst create mode 100644 src/devices/cpu/m6502/r65c02gk.cpp create mode 100644 src/devices/cpu/m6502/r65c02gk.h create mode 100644 src/mame/layout/gameking.lay diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index b06797009ea..0254d7498d8 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -1247,6 +1247,8 @@ if (CPUS["M6502"]~=null) then MAME_DIR .. "src/devices/cpu/m6502/n2a03.h", MAME_DIR .. "src/devices/cpu/m6502/r65c02.cpp", MAME_DIR .. "src/devices/cpu/m6502/r65c02.h", + MAME_DIR .. "src/devices/cpu/m6502/r65c02gk.cpp", + MAME_DIR .. "src/devices/cpu/m6502/r65c02gk.h", MAME_DIR .. "src/devices/cpu/m6502/m740.cpp", MAME_DIR .. "src/devices/cpu/m6502/m740.h", MAME_DIR .. "src/devices/cpu/m6502/m3745x.cpp", @@ -1265,6 +1267,7 @@ if (CPUS["M6502"]~=null) then { MAME_DIR .. "src/devices/cpu/m6502/m6510.cpp", GEN_DIR .. "emu/cpu/m6502/m6510.hxx" }, { MAME_DIR .. "src/devices/cpu/m6502/n2a03.cpp", GEN_DIR .. "emu/cpu/m6502/n2a03.hxx" }, { MAME_DIR .. "src/devices/cpu/m6502/r65c02.cpp", GEN_DIR .. "emu/cpu/m6502/r65c02.hxx" }, + { MAME_DIR .. "src/devices/cpu/m6502/r65c02gk.cpp", GEN_DIR .. "emu/cpu/m6502/r65c02gk.hxx" }, { MAME_DIR .. "src/devices/cpu/m6502/m740.cpp", GEN_DIR .. "emu/cpu/m6502/m740.hxx" }, } @@ -1273,6 +1276,7 @@ if (CPUS["M6502"]~=null) then { MAME_DIR .. "src/devices/cpu/m6502/om4510.lst", GEN_DIR .. "emu/cpu/m6502/m4510.hxx", { MAME_DIR .. "src/devices/cpu/m6502/m6502make.py", MAME_DIR .. "src/devices/cpu/m6502/dm4510.lst" }, {"@echo Generating m4510 source file...", PYTHON .. " $(1) m4510_device $(<) $(2) $(@)" }}, { MAME_DIR .. "src/devices/cpu/m6502/om6502.lst", GEN_DIR .. "emu/cpu/m6502/m6502.hxx", { MAME_DIR .. "src/devices/cpu/m6502/m6502make.py", MAME_DIR .. "src/devices/cpu/m6502/dm6502.lst" }, {"@echo Generating m6502 source file...", PYTHON .. " $(1) m6502_device $(<) $(2) $(@)" }}, { MAME_DIR .. "src/devices/cpu/m6502/om65c02.lst", GEN_DIR .. "emu/cpu/m6502/m65c02.hxx", { MAME_DIR .. "src/devices/cpu/m6502/m6502make.py", MAME_DIR .. "src/devices/cpu/m6502/dm65c02.lst" }, {"@echo Generating m65c02 source file...", PYTHON .. " $(1) m65c02_device $(<) $(2) $(@)" }}, + { MAME_DIR .. "src/devices/cpu/m6502/om65c02gk.lst", GEN_DIR .. "emu/cpu/m6502/r65c02gk.hxx", { MAME_DIR .. "src/devices/cpu/m6502/m6502make.py", MAME_DIR .. "src/devices/cpu/m6502/dm65c02.lst" }, {"@echo Generating r65c02gk source file...", PYTHON .. " $(1) r65c02gk_device $(<) $(2) $(@)" }}, { MAME_DIR .. "src/devices/cpu/m6502/om65ce02.lst",GEN_DIR .. "emu/cpu/m6502/m65ce02.hxx",{ MAME_DIR .. "src/devices/cpu/m6502/m6502make.py", MAME_DIR .. "src/devices/cpu/m6502/dm65ce02.lst" }, {"@echo Generating m65ce02 source file...", PYTHON .. " $(1) m65ce02_device $(<) $(2) $(@)" }}, { MAME_DIR .. "src/devices/cpu/m6502/om6509.lst", GEN_DIR .. "emu/cpu/m6502/m6509.hxx", { MAME_DIR .. "src/devices/cpu/m6502/m6502make.py", MAME_DIR .. "src/devices/cpu/m6502/dm6509.lst" }, {"@echo Generating m6509 source file...", PYTHON .. " $(1) m6509_device $(<) $(2) $(@)" }}, { MAME_DIR .. "src/devices/cpu/m6502/om6510.lst", GEN_DIR .. "emu/cpu/m6502/m6510.hxx", { MAME_DIR .. "src/devices/cpu/m6502/m6502make.py", MAME_DIR .. "src/devices/cpu/m6502/dm6510.lst" }, {"@echo Generating m6510 source file...", PYTHON .. " $(1) m6510_device $(<) $(2) $(@)" }}, diff --git a/src/devices/cpu/m6502/om65c02gk.lst b/src/devices/cpu/m6502/om65c02gk.lst new file mode 100644 index 00000000000..9c2d732f062 --- /dev/null +++ b/src/devices/cpu/m6502/om65c02gk.lst @@ -0,0 +1,88 @@ +# license:BSD-3-Clause +# copyright-holders:Peter Trauner +# r65c02gk opcodes + +brk_c_imp + if(irq_taken || nmi_state) { + read_pc_noinc(); + } else { + read_pc(); + } + write(SP, PC >> 8); + dec_SP(); + write(SP, PC); + dec_SP(); + write(SP, irq_taken || nmi_state ? P & ~F_B : P); + dec_SP(); + if(irq_taken && nmi_state) { + PC = read_arg(0x7ffa); + PC = set_h(PC, read_arg(0x7ffb)); + nmi_state = false; + standard_irq_callback(NMI_LINE); + } else { + static int level=interrupt_controller.getlevel(); // !no gameking dual core expected + if (level==IRQ_GK3A) { + PC = read_arg(0x7fe2); + PC = set_h(PC, read_arg(0x7fe3)); + } else if (level==IRQ_GK3B) { + PC = read_arg(0x7fe4); + PC = set_h(PC, read_arg(0x7fe5)); + } else if (level==IRQ_TIMERUSER) { + m_bank4000->set_base(bank4000_irq); + PC = read_arg(0x7fee); + PC = set_h(PC, read_arg(0x7fef)); + } else if (level==IRQ_INPUTS) { + m_bank4000->set_base(bank4000_irq); + PC = read_arg(0x7ff0); + PC = set_h(PC, read_arg(0x7ff1)); + } else if (level==IRQ_USER) { + m_bank4000->set_base(bank4000_irq); + PC = read_arg(0x7ff2); + PC = set_h(PC, read_arg(0x7ff3)); + } else if (level==IRQ_TIMER/*INPUT_LINE_IRQ9*/) { + m_bank4000->set_base(bank4000_irq); + PC = read_arg(0x7ff4); + PC = set_h(PC, read_arg(0x7ff5)); + } else if (level==IRQ_6606) { + PC = read_arg(0x7ff6); + PC = set_h(PC, read_arg(0x7ff7)); + } else { + PC = read_arg(0x7ffe); + PC = set_h(PC, read_arg(0x7fff)); + if(irq_taken) + standard_irq_callback(IRQ_LINE); + } + } + irq_taken = false; + P = (P | F_I) & ~F_D; // Do *not* move after the prefetch + prefetch(); + inst_state = -1; + + +rti_imp + read_pc_noinc(); + read(SP); + inc_SP(); + P = read(SP) | (F_B|F_E); + inc_SP(); + PC = read(SP); + inc_SP(); + PC = set_h(PC, read(SP)); + m_bank4000->set_base(bank4000_normal); + prefetch(); + +wai_imp + read_pc_noinc(); /* same as m65c02 version, seams to be right*/ + read_pc_noinc(); + while(!nmi_state && !irq_state) { + eat-all-cycles; + } + prefetch(); + +# exceptions +reset + PC = read_arg(0x7ffc); + PC = set_h(PC, read_arg(0x7ffd)); + prefetch(); + inst_state = -1; + \ No newline at end of file diff --git a/src/devices/cpu/m6502/r65c02gk.cpp b/src/devices/cpu/m6502/r65c02gk.cpp new file mode 100644 index 00000000000..6ffecf92934 --- /dev/null +++ b/src/devices/cpu/m6502/r65c02gk.cpp @@ -0,0 +1,109 @@ +// license:BSD-3-Clause +// copyright-holders:Peter Trauner +/*************************************************************************** + + r65c02gk.c + + Rockwell 65c02gb, additional interrupts, interrupt bankswitching + +***************************************************************************/ + +#include "emu.h" +#include "r65c02gk.h" + +const device_type R65C02GK = &device_creator; + +r65c02gk_device::r65c02gk_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + r65c02_device(mconfig, R65C02GK, "R65C02GK", tag, owner, clock, "r65c02gk", __FILE__) +{ +} + +r65c02gk_device::r65c02gk_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) : + r65c02_device(mconfig, type, name, tag, owner, clock, shortname, source) +{ +} + +offs_t r65c02gk_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) +{ + return disassemble_generic(buffer, pc, oprom, opram, options, disasm_entries); +} + +void r65c02gk_device::device_reset() +{ + r65c02_device::device_reset(); + interrupt_controller.Reset(); +} + +void r65c02gk_device::set_irq_bank(memory_bank *m_bank4000_, UINT8 *bank4000_normal_, UINT8 *bank4000_irq_) { + m_bank4000 = m_bank4000_; + bank4000_normal=bank4000_normal_; + bank4000_irq=bank4000_irq_; +} + +void r65c02gk_device::execute_set_input(int inputnum, int state) +{ + switch(inputnum) { + case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 10: case 11: case 12: + interrupt_controller.states[inputnum]=state; + irq_state= interrupt_controller.getlevel()>=0; + break; + case R65C02GK_NMI_LINE: nmi_state = nmi_state || (state == ASSERT_LINE); break; +#if 0 + case APU_IRQ_LINE: apu_irq_state = state == ASSERT_LINE; break; + case V_LINE: + if(!v_state && state == ASSERT_LINE) + P |= F_V; + v_state = state == ASSERT_LINE; + break; +#endif + } +// logerror("%.6f irq num:%d state:%d irq:%x level:%x\n",machine().time().as_double(), inputnum, state, irq_state, interrupt_controller.getlevel()); +} + +#if 0 +void r65c02gk_device::prefetch() +{ + sync = true; + sync_w(ASSERT_LINE); + NPC = PC; + IR = mintf->read_decrypted(PC); + sync = false; + sync_w(CLEAR_LINE); + + if((nmi_state || ((irq_state || apu_irq_state) && !(P & F_I))) && !inhibit_interrupts) { + irq_taken = true; + IR = 0x00; + } else + PC++; +} + +void r65c02gk_device::prefetch_wai() +{ + sync = true; + sync_w(ASSERT_LINE); + NPC = PC; + IR = mintf->read_decrypted(PC); + sync = false; + sync_w(CLEAR_LINE); + + if (irq_state || nmi_state) + PC++; + if((nmi_state || ((irq_state || apu_irq_state) && !(P & F_I))) && !inhibit_interrupts) { + irq_taken = true; + IR = 0x00; + } +} + +void r65c02gk_device::prefetch_noirq() +{ + sync = true; + sync_w(ASSERT_LINE); + NPC = PC; + IR = mintf->read_decrypted(PC); + sync = false; + sync_w(CLEAR_LINE); + PC++; +} +#endif + +#include "cpu/m6502/r65c02gk.hxx" diff --git a/src/devices/cpu/m6502/r65c02gk.h b/src/devices/cpu/m6502/r65c02gk.h new file mode 100644 index 00000000000..878c0ab43f7 --- /dev/null +++ b/src/devices/cpu/m6502/r65c02gk.h @@ -0,0 +1,74 @@ +// license:BSD-3-Clause +// copyright-holders:Peter Trauner +/*************************************************************************** + + r65c02gk.h + + gameking 65c02 with bitwise instructions and wai instruction, additional + interrupt vectors, special vector address base + + +***************************************************************************/ + +#ifndef __R65C02GK_H__ +#define __R65C02GK_H__ + +#include "r65c02.h" + +class r65c02gk_device : public r65c02_device { +public: + r65c02gk_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + r65c02gk_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source); + + static const disasm_entry disasm_entries[0x100]; + + virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) override; + virtual void do_exec_full() override; + virtual void do_exec_partial() override; + enum { + IRQ_GK3A=INPUT_LINE_IRQ0, + IRQ_GK3B, + IRQ_TIMERUSER=INPUT_LINE_IRQ6, + IRQ_INPUTS, //449C, + IRQ_USER, //=INPUT_LINE_IRQ8, + IRQ_TIMER, //=INPUT_LINE_IRQ9, + IRQ_6606, + R65C02GK_IRQ_LINE12 = IRQ_GK3A/*R65C02GK_IRQ_LINE0*/+12, + R65C02GK_NMI_LINE = INPUT_LINE_NMI // >12 +// R65C02GK_SET_OVERFLOW = m6502_device::V_LINE, + }; + + void set_irq_bank(memory_bank *m_bank4000, UINT8 *bank4000_normal, UINT8 *bank4000_irq); +protected: + UINT8 *bank4000_normal, *bank4000_irq; + virtual void device_reset() override; + virtual void execute_set_input(int inputnum, int state) override; + memory_bank *m_bank4000; + +#if 0 + void prefetch(); + void prefetch_noirq(); + void prefetch_wai(); +#endif + + struct InterruptController { // nearly nothing known about it, only enough to get bios working + bool states[13]; + int getlevel() { for (int i=12; i>=0; --i) { if (states[i]) return i; } return -1; } + void Reset() { memset(states, 0, sizeof(states)); } + } interrupt_controller; + + #define O(o) void o ## _full(); void o ## _partial() + + O(brk_c_imp); + O(rti_imp); + O(wai_imp); + + // exceptions + O(reset); + +}; + + +extern const device_type R65C02GK; + +#endif diff --git a/src/mame/drivers/gameking.cpp b/src/mame/drivers/gameking.cpp index 96366b2bf02..cafb6d52a1c 100644 --- a/src/mame/drivers/gameking.cpp +++ b/src/mame/drivers/gameking.cpp @@ -2,22 +2,21 @@ // copyright-holders:Peter Trauner /* TimeTop - GameKing */ /* - PeT mess@utanet.at 2015 + PeT mess@utanet.at 2015, 2016 + Thanks to Deathadder, Judge, Porchy, Klaus Sommer, James Brolly & Brian Provinciano - hopefully my work (reverse engineerung, cartridge+bios backup, emulation) will be honored in future and my name will not be removed entirely, especially by simple code rewrites of working emulation - flashcard, handheld, programmer, assembler ready to do some test on real hardware - todo: - !back up gameking3 bios so emulation of gameking3 gets possible; my gameking bios backup solution should work - search for rockwell r65c02 variant (cb:wai instruction) and several more exceptions, and implement it + search for rockwell r65c02 variant (cb:wai instruction) and several more exceptions (with luck microcontroller peripherals match those in gameking) - work out bankswitching and exceptions - (improove emulation) + incomplete interrupt controller causes hangs + protection!? prevents 4in1 carts from working + (improve emulation, timer) (add audio) + work out gameking3 problems (lcd position, additional interrupts/lcd emulation; audio expected to be the same) use gameking3 cartridge to get illegal cartridge scroller @@ -27,11 +26,16 @@ #include #include "emu.h" -#include "cpu/m6502/r65c02.h" +#include "cpu/m6502/r65c02gk.h" #include "bus/generic/slot.h" #include "bus/generic/carts.h" #include "softlist.h" +#include "gameking.lh" +//#include "gking3.lh" + +//#define GK3_PIXEL // color pixel are too large, color part red green blue visible, even lines: red left, green top right blue bottom right; odd lines: red right, green left top, blue bottom left + class gameking_state : public driver_device { public: @@ -47,125 +51,282 @@ public: virtual void machine_start() override; virtual void machine_reset() override; DECLARE_PALETTE_INIT(gameking); + DECLARE_PALETTE_INIT(gameking3); DECLARE_READ8_MEMBER(io_r); DECLARE_WRITE8_MEMBER(io_w); - DECLARE_READ8_MEMBER(lcd_r); - DECLARE_WRITE8_MEMBER(lcd_w); + DECLARE_READ8_MEMBER(io2_r); + DECLARE_WRITE8_MEMBER(io2_w); + DECLARE_WRITE8_MEMBER(gk3_lcd_w); INTERRUPT_GEN_MEMBER(gameking_frame_int); TIMER_CALLBACK_MEMBER(gameking_timer); TIMER_CALLBACK_MEMBER(gameking_timer2); + TIMER_CALLBACK_MEMBER(gameking_timeruser); + TIMER_CALLBACK_MEMBER(gameking_timeruser2); UINT32 screen_update_gameking(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + UINT32 screen_update_gameking3(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); DECLARE_DEVICE_IMAGE_LOAD_MEMBER(gameking_cart); struct Gkio { UINT8 input, input2; - UINT8 timer; - UINT8 res3[0x2f]; + UINT8 timer; // bit 5 red power led + UINT8 res3[0x1d]; + UINT8 timeruser_on; + UINT8 timeruser_quit; + UINT8 res4[0x6]; + UINT8 dma_src_low, dma_src_high, dma_dest_low, dma_dest_high, dma_length_low, dma_length_high; + UINT8 res5[2+1]; + UINT8 bank4000_irq; //? UINT8 bank4000_address; // 32 UINT8 bank4000_cart; //33 bit 0 only? UINT8 bank8000_cart; //34 bit 7; bits 0,1,.. a15,a16,.. - UINT8 res2[0x4c]; + UINT8 bank8000_control; + UINT8 bank8000_dma_addr; + UINT8 bank8000_dma_control; + UINT8 res1[6]; + UINT8 interrupt_enable; // bit 2 irq timer, bit 5 timeruser + UINT8 res2[1]; + UINT8 lcd_pos_low, lcd_pos_high; + UINT8 res2a[0xe +0x30]; }; protected: - required_device m_maincpu; + void gk3_pixel(bitmap_ind16 &bitmap, int y, int x, int color); + + UINT8 Bank8000AddrRead(UINT8 bank, UINT8 control, UINT16 addr) { + if (addr<0x8000) + m_maincpu->space(AS_PROGRAM).read_byte(addr); + + memory_region *maincpu_rom = memregion("maincpu"); + if (control==1) + return maincpu_rom->base()[addr]; + return 0; + } + + void Bank8000AddrWrite(UINT8 bank, UINT8 control, UINT16 addr, UINT8 data) { + memory_region *maincpu_rom = memregion("maincpu"); + if (addr<0x8000) + m_maincpu->space(AS_PROGRAM).write_byte(addr, data); + else + if (control==1) + maincpu_rom->base()[addr]=data; + } + required_device m_maincpu; required_device m_cart; required_ioport m_io_joy; required_device m_palette; + UINT8 *bank4000_normal, *bank4000_irq; memory_region *m_cart_rom; memory_bank *m_bank4000; memory_bank *m_bank8000; emu_timer *timer1; emu_timer *timer2; + emu_timer *timeruser; + emu_timer *timeruser2; + bool timeruser_expired, timer_expired; + UINT8 inputs0, inputs1; }; - -WRITE8_MEMBER(gameking_state::io_w) +WRITE8_MEMBER( gameking_state::io_w ) { - if (offset != offsetof(Gkio, bank8000_cart)) - logerror("%.6f io w %x %x\n", machine().time().as_double(), offset, data); - + if (offset!=offsetof(Gkio, bank8000_cart)) + logerror("%.6f io w %x %x\n",machine().time().as_double(), offset, data); memory_region *maincpu_rom = memregion("maincpu"); - maincpu_rom->base()[offset] = data; - if (offset == offsetof(Gkio, timer)) { - m_maincpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE); - timer1->enable(TRUE); - timer1->reset(m_maincpu->cycles_to_attotime(data * 300/*?*/)); - } + maincpu_rom->base()[offset]=data; + Gkio *io=reinterpret_cast(maincpu_rom->base()); + switch (offset) { + case offsetof(Gkio, dma_length_low): + { + UINT16 src=io->dma_src_low|(io->dma_src_high<<8); + UINT16 dst=io->dma_dest_low|(io->dma_dest_high<<8); + UINT16 len=io->dma_length_low|(io->dma_length_high<<8); + logerror("%.6f dma src:%x dst:%x len:%x\n",machine().time().as_double(), src, dst, len); + for (; len>0; len--, src++, dst++) { // in reality consumes times, on 6502 probably in the 2nd part of the cpu cycle + Bank8000AddrWrite(io->bank8000_dma_addr, io->bank8000_dma_control, dst, Bank8000AddrRead(io->bank8000_dma_addr, io->bank8000_dma_control, src)); + } + } + break; + case offsetof(Gkio, timer): + m_maincpu->set_input_line(r65c02gk_device::IRQ_TIMER, CLEAR_LINE); // most likely wrong, removed until real interrupt start lokalized (or permanent active + timer1->enable(TRUE); + timer1->reset(m_maincpu->cycles_to_attotime(70000/*?*/)); // something like 64 hz + break; + case offsetof(Gkio, timeruser_on): + case offsetof(Gkio, timeruser_quit): + // m_maincpu->set_input_line(r65c02gk_device::IRQ_TIMERUSER, CLEAR_LINE); + // timeruser_expired=false; + timeruser->enable(io->timeruser_on!=0); + if (io->timeruser_on&0x1f) + timeruser->reset(m_maincpu->cycles_to_attotime(2000000/(io->timeruser_on&0x1f)/*?*/)); // 1 somethink like 1.5 hz + break; + case offsetof(Gkio, bank4000_irq): + { + UINT8 bank=io->bank4000_irq^1; + bool cart=false; //m_cart_rom; + if (cart) { + // m_bank4000->set_base(m_cart_rom->base() + (bank*0x4000&(m_cart_rom->get_size()-1) ); + bank4000_irq=m_cart_rom->base() + (bank*0x4000&(0x80000-1)); + } else { + if (bank*0x4000>=0x80000) + bank4000_irq=maincpu_rom->base()+0x4000; + else + bank4000_irq=maincpu_rom->base()+0x10000 + (bank*0x4000&(0x80000-1)); + } + } + m_maincpu->set_irq_bank(m_bank4000, bank4000_normal, bank4000_irq); + break; + case offsetof(Gkio, bank4000_address): case offsetof(Gkio, bank4000_cart): + { + UINT8 bank=io->bank4000_address^1; + bool cart=io->bank4000_cart&1/*?*/ && m_cart_rom; + if (cart) { + // m_bank4000->set_base(m_cart_rom->base() + (bank*0x4000&(m_cart_rom->get_size()-1) ); + bank4000_normal=m_cart_rom->base() + (bank*0x4000&(0x80000-1)); + } else { + if (bank*0x4000>=0x80000) + bank4000_normal=maincpu_rom->base()+0x4000; + else + bank4000_normal=maincpu_rom->base()+0x10000 + (bank*0x4000&(0x80000-1)); + } + } + m_bank4000->set_base(bank4000_normal); + m_maincpu->set_irq_bank(m_bank4000, bank4000_normal, bank4000_irq); + break; + case offsetof(Gkio, bank8000_cart): + case offsetof(Gkio, bank8000_control): - Gkio *io = reinterpret_cast(maincpu_rom->base()); - if (offset == offsetof(Gkio, bank4000_address) || offset == offsetof(Gkio, bank4000_cart)) { - UINT8 bank = io->bank4000_address ^ 1; - UINT8 *base = io->bank4000_cart & 1/*?*/ && m_cart_rom ? m_cart_rom->base() : maincpu_rom->base() + 0x10000; - m_bank4000->set_base(base + bank * 0x4000); - } - if (offset == offsetof(Gkio, bank8000_cart)) { - UINT8 *base = io->bank8000_cart & 0x80/*?*/ && m_cart_rom ? m_cart_rom->base() : maincpu_rom->base() + 0x10000; - UINT8 bank = io->bank8000_cart & 0x7f; - m_bank8000->set_base(base + bank * 0x8000); - } + { + bool cart=io->bank8000_cart&0x80/*?*/ && m_cart_rom; + UINT8 bank=io->bank8000_cart&0x7f; + if ((io->bank8000_control&7)!=0) { + m_bank8000->set_base(maincpu_rom->base()+0x8000); + } else if (cart) { + // m_bank8000->set_base(m_cart_rom->base() + (bank*0x8000&(m_cart_rom->get_size()-1) ); + m_bank8000->set_base(m_cart_rom->base() + (bank*0x8000&(0x80000-1)) ); + } else { + if (bank*0x8000>=0x80000) + m_bank8000->set_base(maincpu_rom->base()+0x8000); + else + m_bank8000->set_base(maincpu_rom->base()+0x10000+ (bank*0x8000&(0x80000-1)) ); + } + } + break; + case offsetof(Gkio, interrupt_enable): + m_maincpu->set_input_line(r65c02gk_device::IRQ_TIMER, timer_expired && (io->interrupt_enable&4)?ASSERT_LINE:CLEAR_LINE); + m_maincpu->set_input_line(r65c02gk_device::IRQ_TIMERUSER, timeruser_expired && (io->interrupt_enable&0x20)?ASSERT_LINE:CLEAR_LINE); + break; + }; } -READ8_MEMBER(gameking_state::io_r) +READ8_MEMBER( gameking_state::io_r ) { memory_region *maincpu_rom = memregion("maincpu"); - UINT8 data = maincpu_rom->base()[offset]; + UINT8 data=maincpu_rom->base()[offset]; switch (offset) { case offsetof(Gkio, input): - data = m_io_joy->read() | ~3; + m_maincpu->set_input_line(r65c02gk_device::IRQ_INPUTS, CLEAR_LINE); + data=m_io_joy->read()>>8; break; case offsetof(Gkio, input2): - data = m_io_joy->read() | 3; + m_maincpu->set_input_line(r65c02gk_device::IRQ_USER, CLEAR_LINE); + data=m_io_joy->read(); break; - case 0x4c: data = 6; - break; // bios protection endless loop + case 0x4c: + data=6; break; // bios protection endless loop } - if (offset != offsetof(Gkio, bank8000_cart)) - logerror("%.6f io r %x %x\n", machine().time().as_double(), offset, data); - + if (offset!=offsetof(Gkio, bank8000_cart) && offset!=offsetof(Gkio, input) ) + logerror("%.6f io r %x %x\n",machine().time().as_double(), offset, data); return data; } -WRITE8_MEMBER( gameking_state::lcd_w ) +WRITE8_MEMBER( gameking_state::io2_w ) { + if (offset>=4 && offset<=7) + logerror("%.6f protection w %x %x\n",machine().time().as_double(), offset, data); + else + logerror("%.6f io2 w %x %x\n",machine().time().as_double(), offset, data); memory_region *maincpu_rom = memregion("maincpu"); - maincpu_rom->base()[offset+0x600]=data; + + maincpu_rom->base()[0x100+offset]=data; } -READ8_MEMBER(gameking_state::lcd_r) +READ8_MEMBER( gameking_state::io2_r ) { memory_region *maincpu_rom = memregion("maincpu"); - UINT8 data = maincpu_rom->base()[offset + 0x600]; + UINT8 data=maincpu_rom->base()[0x100+offset]; + + if (offset>=4 && offset<=7) { + UINT8 d=data; + if (offset==4) { +// if (data==0xc) data=0x95; +// if (data==0xce) data=0xd2; // no real improvement, but much slower + } + logerror("%.6f protection r %x %x (written %x)\n",machine().time().as_double(), offset, data, d); + } + else + logerror("%.6f io2 r %x %x\n",machine().time().as_double(), offset, data); return data; } +WRITE8_MEMBER( gameking_state::gk3_lcd_w ) +{ + memory_region *maincpu_rom = memregion("maincpu"); + Gkio *io=reinterpret_cast(maincpu_rom->base()); + if (io->bank8000_cart==0 && io->bank8000_control==1) + maincpu_rom->base()[offset+0x8000]=data; + else + logerror("%.6f gk3 lcd w %x %x\n",machine().time().as_double(), offset, data); +} + static ADDRESS_MAP_START( gameking_mem , AS_PROGRAM, 8, gameking_state ) AM_RANGE(0x0000, 0x007f) AM_READWRITE(io_r, io_w) - AM_RANGE(0x0080, 0x01ff) AM_RAM - AM_RANGE(0x0200, 0x03ff) AM_RAM // lcd 2nd copy - - AM_RANGE(0x0600, 0x077f) AM_READWRITE(lcd_r, lcd_w) - AM_RANGE(0x0d00, 0x0fff) AM_RAM // d00, e00, f00 prooved on handheld -// AM_RANGE(0x1000, 0x1fff) AM_RAM // sthero writes to $19xx - -// AM_RANGE(0x3000, 0x3fff) AM_ROMBANK("bank3000") + AM_RANGE(0x0080, 0x00ff) AM_RAM + AM_RANGE(0x0100, 0x017f) AM_READWRITE(io2_r, io2_w) + AM_RANGE(0x0180, 0x27ff) AM_RAM + AM_RANGE(0x2800, 0x2fff) AM_ROMBANK("bank2800") // proove if also write access like on 3000 + AM_RANGE(0x3000, 0x3fff) AM_ROMBANK("bank3000") AM_RANGE(0x4000, 0x7fff) AM_ROMBANK("bank4000") - AM_RANGE(0x8000, 0xffaf) AM_ROMBANK("bank8000") - AM_RANGE(0xffb0, 0xffff) AM_ROMBANK("bankboot") // cpu seems to read from 8000 bank, and for exceptions ignore bank + AM_RANGE(0x8000, 0xffff) AM_READ_BANK("bank8000") AM_WRITE(gk3_lcd_w) ADDRESS_MAP_END static INPUT_PORTS_START( gameking ) +#if 1 PORT_START("JOY") - PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_START) PORT_NAME("Start") - PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SELECT) PORT_NAME("Select") //? - PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("A") //? + PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_START) PORT_NAME("Start") // gk3 1 on address 0 + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_SELECT) PORT_NAME("Select") // ! 2 on address 1; gk3 2 on address 0 PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("B") - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) //? - PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) //? + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("A") + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) + PORT_BIT( 0xfd01, IP_ACTIVE_LOW, IPT_UNUSED ) +#else + PORT_START("JOY") + PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_START) PORT_NAME("Start") // gk3 1 on address 0 + PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_SELECT) PORT_NAME("Select") // ! 2 on address 1; gk3 2 on address 0 + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("B") + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("A") + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) + PORT_BIT( 0xfc03, IP_ACTIVE_LOW, IPT_UNUSED ) +#endif +INPUT_PORTS_END + +static INPUT_PORTS_START( gameking3 ) + PORT_START("JOY") + PORT_BIT( 0xfc03, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_START) PORT_NAME("Start") + PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_SELECT) PORT_NAME("Select") + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("B") + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("A") + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) INPUT_PORTS_END @@ -178,21 +339,50 @@ static const unsigned char gameking_palette[] = 0, 0, 0 }; +static const unsigned char gameking3_palette[64*3] = +{ + 255, 255, 255, + 127, 127, 127, + 63, 63, 63, + 0, 0, 0, + 255, 0, 0, + 127, 0, 0, + 63, 0, 0, + 31, 0, 0, + 0, 255, 0, + 0, 127, 127, + 0, 63, 0, + 0, 31, 0, + 0, 0, 255, + 0, 0, 127, + 0, 0, 63, + 0, 0, 31 +}; + PALETTE_INIT_MEMBER(gameking_state, gameking) { for (int i = 0; i < sizeof(gameking_palette) / 3; i++) palette.set_pen_color(i, gameking_palette[i*3], gameking_palette[i*3+1], gameking_palette[i*3+2]); } +PALETTE_INIT_MEMBER(gameking_state, gameking3) +{ + for (int i = 0; i < sizeof(gameking3_palette) / 3; i++) + palette.set_pen_color(i, ((i&0xc)>>2)*(255/3), (i&3)*(255/3), ((i&0x30)>>4)*(255/3) ); // not quite as contrast rich on the real handheld, but not bad +} + UINT32 gameking_state::screen_update_gameking(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { + memory_region *maincpu_rom = memregion("maincpu"); + Gkio *io=reinterpret_cast(maincpu_rom->base()); + UINT16 pos=io->lcd_pos_low|(io->lcd_pos_high<<8); + for (int y=31, i=0;i<32;i++,y--) { for (int x=0, j=0;j<48/4;x+=4, j++) { - memory_region *maincpu_rom = memregion("maincpu"); - UINT8 data=maincpu_rom->base()[0x600+j+i*12]; + UINT8 data=machine().device("maincpu")->memory().space(AS_PROGRAM).read_byte(pos+j+i*12); bitmap.pix16(y, x+3)=data&3; bitmap.pix16(y, x+2)=(data>>2)&3; bitmap.pix16(y, x+1)=(data>>4)&3; @@ -202,16 +392,87 @@ UINT32 gameking_state::screen_update_gameking(screen_device &screen, bitmap_ind1 return 0; } +void gameking_state::gk3_pixel(bitmap_ind16 &bitmap, int y, int x, int color) +{ + if (!(y&1)) { + bitmap.pix16(y*2+1, x*2)=(color&0xc)==color? color: 0; // red + bitmap.pix16(y*2, x*2+1)=color&3? color: 0; // 0x3 green + bitmap.pix16(y*2+1, x*2+1)=color&0x30? color: 0; // 0x30 blue + } else { + bitmap.pix16(y*2+1, x*2+1)=(color&0xc)==color? color: 0; + bitmap.pix16(y*2, x*2)=color&3? color: 0; + bitmap.pix16(y*2+1, x*2)=color&0x30? color: 0; + } +} + +UINT32 gameking_state::screen_update_gameking3(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + memory_region *maincpu_rom = memregion("maincpu"); + for (int y=0, i=0;y<56;i+=40*6,y+=4) + { + for (int j=0, x=0;x<80;j++, x+=2) + { +#if 1 + UINT8 d1=maincpu_rom->base()[0x8000+i+j]; + UINT8 d2=maincpu_rom->base()[0x8000+i+j+40]; + UINT8 d3=maincpu_rom->base()[0x8000+i+j+80]; + UINT8 d4=maincpu_rom->base()[0x8000+i+j+120]; + UINT8 d5=maincpu_rom->base()[0x8000+i+j+160]; + UINT8 d6=maincpu_rom->base()[0x8000+i+j+200]; +#else // galaxy crisis stopped working + Gkio *io=reinterpret_cast(maincpu_rom->base()); + UINT16 pos=io->lcd_pos_low|(io->lcd_pos_high<<8); + UINT8 d1=m_maincpu->space(AS_PROGRAM).read_byte(pos+i+j); + UINT8 d2=m_maincpu->space(AS_PROGRAM).read_byte(pos+i+j+40); + UINT8 d3=m_maincpu->space(AS_PROGRAM).read_byte(pos+i+j+80); + UINT8 d4=m_maincpu->space(AS_PROGRAM).read_byte(pos+i+j+120); + UINT8 d5=m_maincpu->space(AS_PROGRAM).read_byte(pos+i+j+160); + UINT8 d6=m_maincpu->space(AS_PROGRAM).read_byte(pos+i+j+200); +#endif + UINT32 data=((d1&0xf0)>>4)|(d2&0xf0)|((d3&0xf0)<<4)|((d4&0xf0)<<8)|((d5&0xf0)<<12)|((d6&0xf0)<<16); +#ifdef GK3_PIXEL + gk3_pixel(bitmap, y+0, x, data&0x3f); + gk3_pixel(bitmap, y+1, x, (data>>6)&0x3f); + gk3_pixel(bitmap, y+2, x, (data>>12)&0x3f); + gk3_pixel(bitmap, y+3, x, (data>>18)&0x3f); +#else + bitmap.pix16(y+0, x)=data&0x3f; + bitmap.pix16(y+1, x)=(data>>6)&0x3f; + bitmap.pix16(y+2, x)=(data>>12)&0x3f; + bitmap.pix16(y+3, x)=(data>>18)&0x3f; +#endif + data=(d1&0xf)|((d2&0xf)<<4)|((d3&0xf)<<8)|((d4&0xf)<<12)|((d5&0xf)<<16)|((d6&0xf)<<20); +#ifdef GK3_PIXEL + gk3_pixel(bitmap, y+0, x+1, data&0x3f); + gk3_pixel(bitmap, y+1, x+1, (data>>6)&0x3f); + gk3_pixel(bitmap, y+2, x+1, (data>>12)&0x3f); + gk3_pixel(bitmap, y+3, x+1, (data>>18)&0x3f); +#else + bitmap.pix16(y+0, x+1)=data&0x3f; + bitmap.pix16(y+1, x+1)=(data>>6)&0x3f; + bitmap.pix16(y+2, x+1)=(data>>12)&0x3f; + bitmap.pix16(y+3, x+1)=(data>>18)&0x3f; +#endif + } + } + return 0; +} DRIVER_INIT_MEMBER(gameking_state, gameking) { - timer1 = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gameking_state::gameking_timer), this)); - timer2 = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gameking_state::gameking_timer2), this)); + timer1 = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gameking_state::gameking_timer),this)); + timer2 = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gameking_state::gameking_timer2),this)); + timeruser = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gameking_state::gameking_timeruser),this)); + timeruser2 = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gameking_state::gameking_timeruser2),this)); } TIMER_CALLBACK_MEMBER(gameking_state::gameking_timer) { - m_maincpu->set_input_line(M6502_IRQ_LINE, ASSERT_LINE); // in reality int for vector at fff4 +// m_maincpu->set_input_line(M6502_IRQ_LINE, ASSERT_LINE); // in reality int for vector at fff4 + memory_region *maincpu_rom = memregion("maincpu"); + Gkio *io=reinterpret_cast(maincpu_rom->base()); + timer_expired=true; + m_maincpu->set_input_line(r65c02gk_device::IRQ_TIMER, io->interrupt_enable&4?ASSERT_LINE:CLEAR_LINE); timer1->enable(FALSE); timer2->enable(TRUE); timer2->reset(m_maincpu->cycles_to_attotime(10/*?*/)); @@ -219,12 +480,37 @@ TIMER_CALLBACK_MEMBER(gameking_state::gameking_timer) TIMER_CALLBACK_MEMBER(gameking_state::gameking_timer2) { - memory_region *maincpu_rom = memregion("maincpu"); - m_maincpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE); // in reality int for vector at fff4 +// memory_region *maincpu_rom = memregion("maincpu"); +// m_maincpu->set_input_line(M6502_IRQ_LINE, CLEAR_LINE); // in reality int for vector at fff4 + m_maincpu->set_input_line(r65c02gk_device::IRQ_TIMER, CLEAR_LINE); + timer_expired=false; timer2->enable(FALSE); timer1->enable(TRUE); - Gkio *io = reinterpret_cast(maincpu_rom->base()); - timer1->reset(m_maincpu->cycles_to_attotime(io->timer * 300/*?*/)); + //Gkio *io=reinterpret_cast(maincpu_rom->base()); + timer1->reset(m_maincpu->cycles_to_attotime(50000/*?*/)); +} + +TIMER_CALLBACK_MEMBER(gameking_state::gameking_timeruser) +{ + memory_region *maincpu_rom = memregion("maincpu"); + Gkio *io=reinterpret_cast(maincpu_rom->base()); + timeruser_expired=true; + m_maincpu->set_input_line(r65c02gk_device::IRQ_TIMERUSER, io->interrupt_enable&0x20?ASSERT_LINE:CLEAR_LINE); + timeruser->enable(FALSE); + timeruser2->enable(TRUE); + timeruser2->reset(m_maincpu->cycles_to_attotime(30/*?*/)); // 10 to few +} + +TIMER_CALLBACK_MEMBER(gameking_state::gameking_timeruser2) +{ + memory_region *maincpu_rom = memregion("maincpu"); + Gkio *io=reinterpret_cast(maincpu_rom->base()); + timeruser_expired=false; + m_maincpu->set_input_line(r65c02gk_device::IRQ_TIMERUSER, CLEAR_LINE); + timeruser->enable(io->timeruser_on!=0); + if (io->timeruser_on&0x1f) + timeruser->reset(m_maincpu->cycles_to_attotime(2000000/(io->timeruser_on&0x1f)/*?*/)); // 1 somethink like 1.5 hz + timeruser->enable(FALSE); } DEVICE_IMAGE_LOAD_MEMBER( gameking_state, gameking_cart ) @@ -250,33 +536,52 @@ void gameking_state::machine_start() m_bank4000 = membank("bank4000"); m_bank8000 = membank("bank8000"); - - memory_region *maincpu_rom = memregion("maincpu"); - memory_bank *bankboot=membank("bankboot"); - maincpu_rom->base()[0x10000+0x7ffe]=0xcf; // routing irq to timerint until r65c02gk hooked up - bankboot->set_base(maincpu_rom->base()+0x10000+0x7fb0); + timeruser_expired=false; + timer_expired=false; } void gameking_state::machine_reset() { memory_region *maincpu_rom = memregion("maincpu"); + + maincpu_rom->base()[0x32] = 0; // neccessary to boot correctly maincpu_rom->base()[0x33] = 0; - m_bank4000->set_base(maincpu_rom->base() + 0x10000 + 0x4000); + maincpu_rom->base()[0x3e] = 0; + m_bank4000->set_base(maincpu_rom->base() + 0x10000+0x4000); + bank4000_normal=bank4000_irq=maincpu_rom->base() + 0x10000+0x4000; + m_maincpu->set_irq_bank(m_bank4000, bank4000_normal, bank4000_irq); + //m_bank8000->set_base(maincpu_rom->base()+0x10000); //? no reason to enforce this yet + memory_bank *bank2800=membank("bank2800"); + memory_bank *bank3000=membank("bank3000"); + if (m_cart_rom) { + bank2800->set_base(m_cart_rom->base()+0x2800); + bank3000->set_base(m_cart_rom->base()+0x3000); + } else { + bank2800->set_base(maincpu_rom->base()+0x10000+0x2800); // most likely access to cartridge space/antenne + bank3000->set_base(maincpu_rom->base()+0x10000+0x3000); + } } INTERRUPT_GEN_MEMBER(gameking_state::gameking_frame_int) // guess to get over bios wai { - // static int line=0; - // line++; - // m_maincpu->set_input_line(M6502_IRQ_LINE, line&1? ASSERT_LINE: CLEAR_LINE); // in reality int for vector at fff4 + memory_region *maincpu_rom = memregion("maincpu"); + Gkio *io=reinterpret_cast(maincpu_rom->base()); + UINT8 i=inputs0; + inputs1=m_io_joy->read()>>8; + if (i!=inputs0 && inputs0!=0xff) + m_maincpu->set_input_line(r65c02gk_device::IRQ_INPUTS, io->interrupt_enable&0x10?ASSERT_LINE:CLEAR_LINE); //? 4in1 popper depends on some effects on $90 bits effected by protection + i=inputs1; + inputs1=m_io_joy->read(); + if (i!=inputs1 && inputs1!=0xff) + m_maincpu->set_input_line(r65c02gk_device::IRQ_USER, io->interrupt_enable&8?ASSERT_LINE:CLEAR_LINE); //? 4in1 popper depends on some effects on $90 bits effected by protection } static MACHINE_CONFIG_START( gameking, gameking_state ) /* basic machine hardware */ - MCFG_CPU_ADD("maincpu", R65C02, 6000000) + MCFG_CPU_ADD("maincpu", R65C02GK, 6000000) MCFG_CPU_PROGRAM_MAP(gameking_mem) MCFG_CPU_VBLANK_INT_DRIVER("screen", gameking_state, gameking_frame_int) @@ -291,36 +596,64 @@ static MACHINE_CONFIG_START( gameking, gameking_state ) MCFG_PALETTE_ADD("palette", ARRAY_LENGTH(gameking_palette) * 3) MCFG_PALETTE_INIT_OWNER(gameking_state, gameking ) + MCFG_DEFAULT_LAYOUT(layout_gameking) + /* cartridge */ MCFG_GENERIC_CARTSLOT_ADD("cartslot", generic_plain_slot, "gameking_cart") MCFG_GENERIC_EXTENSIONS("bin") MCFG_GENERIC_LOAD(gameking_state, gameking_cart) -MACHINE_CONFIG_END -static MACHINE_CONFIG_DERIVED( gameking1, gameking ) + /* Software lists */ MCFG_SOFTWARE_LIST_ADD("cart_list", "gameking") MACHINE_CONFIG_END -static MACHINE_CONFIG_DERIVED( gameking3, gameking ) - MCFG_SOFTWARE_LIST_ADD("cart_list", "gameking") - MCFG_SOFTWARE_LIST_ADD("cart_list_3", "gameking3") -MACHINE_CONFIG_END +static MACHINE_CONFIG_START( gameking3, gameking_state ) + /* basic machine hardware */ + MCFG_CPU_ADD("maincpu", R65C02GK, 6000000) + MCFG_CPU_PROGRAM_MAP(gameking_mem) + MCFG_CPU_VBLANK_INT_DRIVER("screen", gameking_state, gameking_frame_int) + /* video hardware */ + MCFG_SCREEN_ADD("screen", LCD) + MCFG_SCREEN_REFRESH_RATE(60) +#ifdef GK3_PIXEL + MCFG_SCREEN_SIZE(80*2, 56*2) + MCFG_SCREEN_VISIBLE_AREA(0, 80*2-1, 0, 53*2-1) +#else + MCFG_SCREEN_SIZE(80, 56) + MCFG_SCREEN_VISIBLE_AREA(0, 80-1, 0, 53-1) +#endif + MCFG_SCREEN_UPDATE_DRIVER(gameking_state, screen_update_gameking3) + MCFG_SCREEN_PALETTE("palette") + + MCFG_PALETTE_ADD("palette", ARRAY_LENGTH(gameking3_palette) * 3) + MCFG_PALETTE_INIT_OWNER(gameking_state, gameking3 ) + +// MCFG_DEFAULT_LAYOUT(layout_gking3) + MCFG_DEFAULT_LAYOUT(layout_gameking) + + /* cartridge */ + MCFG_GENERIC_CARTSLOT_ADD("cartslot", generic_plain_slot, "gameking_cart") + MCFG_GENERIC_EXTENSIONS("bin") + MCFG_GENERIC_LOAD(gameking_state, gameking_cart) + + /* Software lists */ + MCFG_SOFTWARE_LIST_ADD("cart_list", "gameking") +MACHINE_CONFIG_END ROM_START(gameking) - ROM_REGION(0x10000+0x80000, "maincpu", ROMREGION_ERASE00) + ROM_REGION(0x10000+0x80000, "maincpu", ROMREGION_ERASEVAL(0x0d)) // ROM_LOAD("gm218.bin", 0x10000, 0x80000, CRC(8f52a928) SHA1(2e791fc7b642440d36820d2c53e1bb732375eb6e) ) // a14 inversed ROM_LOAD("gm218.bin", 0x10000, 0x80000, CRC(5a1ade3d) SHA1(e0d056f8ebfdf52ef6796d0375eba7fcc4a6a9d3) ) ROM_END -ROM_START(gamekin3) - ROM_REGION(0x10000+0x80000, "maincpu", ROMREGION_ERASE00) +ROM_START(gking3) + ROM_REGION(0x10000+0x80000, "maincpu", ROMREGION_ERASEVAL(0x0D)) ROM_LOAD("gm220.bin", 0x10000, 0x80000, CRC(1dc43bd5) SHA1(f9dcd3cb76bb7cb10565a1acb070ab375c082b4c) ) ROM_END -CONS(2003, gameking, 0, 0, gameking1, gameking, gameking_state, gameking, "TimeTop", "GameKing GM-218", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) +CONS(2003, gameking, 0, 0, gameking, gameking, gameking_state, gameking, "TimeTop", "GameKing GM-218", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // the GameKing 2 (GM-219) is probably identical HW -CONS(2003, gamekin3, 0, 0, gameking3, gameking, gameking_state, gameking, "TimeTop", "GameKing 3", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) +CONS(2005, gking3, 0, gameking, gameking3, gameking3, gameking_state, gameking, "TimeTop", "GameKing III", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // gameking 3: similiar cartridges, accepts gameking cartridges, gameking3 cartridges not working on gameking (illegal cartridge scroller) -// my gameking bios backup solution might work on it diff --git a/src/mame/layout/gameking.lay b/src/mame/layout/gameking.lay new file mode 100644 index 00000000000..fdc5a985d5a --- /dev/null +++ b/src/mame/layout/gameking.lay @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/mame/mame.lst b/src/mame/mame.lst index 3d0b0427a05..8d065640c09 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -12813,7 +12813,7 @@ gamecst2 // MAME based bootleg, version 2.613 gamecstl // MAME based bootleg @source:gameking.cpp -gamekin3 // +gking3 // gameking // @source:gameplan.cpp