summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author MetalliC <0vetal0@gmail.com>2017-11-17 21:12:55 +0200
committer GitHub <noreply@github.com>2017-11-17 21:12:55 +0200
commit1455e465fd8590d2910c84fd572b582e2782d9a9 (patch)
treed37ff02c7e95581ee3a7b1c84120dbc3ee30afad
parent26af85dc45a18c4532df355abb9e91a4b6d7bd19 (diff)
parent7d0279601f8c0877b5ff7ffcc8cbbde5b7615525 (diff)
Merge pull request #2817 from DavidHaywood/131117
-rw-r--r--scripts/src/machine.lua12
-rw-r--r--scripts/target/mame/arcade.lua3
-rw-r--r--src/devices/machine/atmel_arm_aic.cpp93
-rw-r--r--src/devices/machine/atmel_arm_aic.h63
-rw-r--r--src/mame/drivers/pgm2.cpp634
-rw-r--r--src/mame/includes/pgm2.h114
-rw-r--r--src/mame/video/pgm2.cpp340
7 files changed, 652 insertions, 607 deletions
diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua
index 085d59d01c6..d254c010116 100644
--- a/scripts/src/machine.lua
+++ b/scripts/src/machine.lua
@@ -675,6 +675,18 @@ end
---------------------------------------------------
--
+--@src/devices/machine/atmel_arm_aic.h,MACHINES["ARM_AIC"] = true
+---------------------------------------------------
+
+if (MACHINES["ARM_AIC"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/machine/atmel_arm_aic.cpp",
+ MAME_DIR .. "src/devices/machine/atmel_arm_aic.h",
+ }
+end
+
+---------------------------------------------------
+--
--@src/devices/machine/ay31015.h,MACHINES["AY31015"] = true
---------------------------------------------------
diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua
index 31f39fd5d82..3c2a6242558 100644
--- a/scripts/target/mame/arcade.lua
+++ b/scripts/target/mame/arcade.lua
@@ -397,6 +397,7 @@ MACHINES["AT28C16"] = true
MACHINES["AT29X"] = true
MACHINES["AT45DBXX"] = true
MACHINES["ATAFLASH"] = true
+MACHINES["ARM_AIC"] = true
MACHINES["AY31015"] = true
MACHINES["BANKDEV"] = true
--MACHINES["BIM68153"] = true
@@ -1943,6 +1944,8 @@ files {
MAME_DIR .. "src/mame/machine/pgmprot_orlegend.cpp",
MAME_DIR .. "src/mame/machine/pgmprot_orlegend.h",
MAME_DIR .. "src/mame/drivers/pgm2.cpp",
+ MAME_DIR .. "src/mame/video/pgm2.cpp",
+ MAME_DIR .. "src/mame/includes/pgm2.h",
MAME_DIR .. "src/mame/drivers/pgm3.cpp",
MAME_DIR .. "src/mame/drivers/spoker.cpp",
MAME_DIR .. "src/mame/machine/igs036crypt.cpp",
diff --git a/src/devices/machine/atmel_arm_aic.cpp b/src/devices/machine/atmel_arm_aic.cpp
new file mode 100644
index 00000000000..2013e038cb8
--- /dev/null
+++ b/src/devices/machine/atmel_arm_aic.cpp
@@ -0,0 +1,93 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+/*
+ ARM AIC (Advanced Interrupt Controller) from Atmel
+ typically integrated into the AM91SAM series of chips
+
+ see http://sam7-ex256.narod.ru/include/HTML/AT91SAM7X256_AIC.html
+ current implementation only handles basics needed for pgm2 (pgm2.cpp)
+ if this peripheral is not available as a standalone chip it could also be moved to
+ the CPU folder alongside the ARM instead
+*/
+
+#include "emu.h"
+#include "atmel_arm_aic.h"
+
+DEFINE_DEVICE_TYPE(ARM_AIC, arm_aic_device, "arm_aic", "ARM Advanced Interrupt Controller")
+
+
+DEVICE_ADDRESS_MAP_START( regs_map, 32, arm_aic_device )
+ AM_RANGE(0x000, 0x07f) AM_READWRITE(aic_smr_r, aic_smr_w) // AIC_SMR[32] (AIC_SMR) Source Mode Register
+ AM_RANGE(0x080, 0x0ff) AM_READWRITE(aic_svr_r, aic_svr_w) // AIC_SVR[32] (AIC_SVR) Source Vector Register
+ AM_RANGE(0x100, 0x103) AM_READ(irq_vector_r) // AIC_IVR IRQ Vector Register
+ AM_RANGE(0x104, 0x107) AM_READ(firq_vector_r) // AIC_FVR FIQ Vector Register
+// 0x108 AIC_ISR Interrupt Status Register
+// 0x10C AIC_IPR Interrupt Pending Register
+// 0x110 AIC_IMR Interrupt Mask Register
+// 0x114 AIC_CISR Core Interrupt Status Register
+ AM_RANGE(0x120, 0x123) AM_WRITE(aic_iecr_w) // 0x120 AIC_IECR Interrupt Enable Command Register
+ AM_RANGE(0x124, 0x127) AM_WRITE(aic_idcr_w) // 0x124 AIC_IDCR Interrupt Disable Command Register
+ AM_RANGE(0x128, 0x12b) AM_WRITE(aic_iccr_w) // 0x128 AIC_ICCR Interrupt Clear Command Register
+// 0x12C AIC_ISCR Interrupt Set Command Register
+ AM_RANGE(0x130, 0x133) AM_WRITE(aic_eoicr_w) // 0x130 AIC_EOICR End of Interrupt Command Register
+// 0x134 AIC_SPU Spurious Vector Register
+// 0x138 AIC_DCR Debug Control Register (Protect)
+// 0x140 AIC_FFER Fast Forcing Enable Register
+// 0x144 AIC_FFDR Fast Forcing Disable Register
+// 0x148 AIC_FFSR Fast Forcing Status Register
+ADDRESS_MAP_END
+
+READ32_MEMBER(arm_aic_device::irq_vector_r)
+{
+ return m_current_irq_vector;
+}
+
+READ32_MEMBER(arm_aic_device::firq_vector_r)
+{
+ return m_current_firq_vector;
+}
+
+void arm_aic_device::device_start()
+{
+ m_irq_out.resolve_safe();
+
+ save_item(NAME(m_irqs_enabled));
+ save_item(NAME(m_current_irq_vector));
+ save_item(NAME(m_current_firq_vector));
+
+ save_item(NAME(m_aic_smr));
+ save_item(NAME(m_aic_svr));
+}
+
+void arm_aic_device::device_reset()
+{
+ m_irqs_enabled = 0;
+ m_current_irq_vector = 0;
+ m_current_firq_vector = 0;
+
+ for(auto & elem : m_aic_smr) { elem = 0; }
+ for(auto & elem : m_aic_svr) { elem = 0; }
+}
+
+void arm_aic_device::set_irq(int identity)
+{
+ for (int i = 0;i < 32;i++)
+ {
+ if (m_aic_smr[i] == identity)
+ {
+ if ((m_irqs_enabled >> i) & 1)
+ {
+ m_current_irq_vector = m_aic_svr[i];
+ m_irq_out(ASSERT_LINE);
+ return;
+ }
+ }
+ }
+}
+
+WRITE32_MEMBER(arm_aic_device::aic_iccr_w)
+{
+ //logerror("%s: aic_iccr_w %08x (Interrupt Clear Command Register)\n", machine().describe_context().c_str(), data);
+ m_irq_out(CLEAR_LINE);
+};
diff --git a/src/devices/machine/atmel_arm_aic.h b/src/devices/machine/atmel_arm_aic.h
new file mode 100644
index 00000000000..5b34cde30ac
--- /dev/null
+++ b/src/devices/machine/atmel_arm_aic.h
@@ -0,0 +1,63 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+#ifndef MAME_MACHINE_ATMEL_ARM_AIC_H
+#define MAME_MACHINE_ATMEL_ARM_AIC_H
+
+#pragma once
+
+DECLARE_DEVICE_TYPE(ARM_AIC, arm_aic_device)
+
+#define MCFG_ARM_AIC_ADD(_tag) \
+ MCFG_DEVICE_ADD(_tag, ARM_AIC, 0)
+
+#define MCFG_IRQ_LINE_CB(_devcb) \
+ devcb = &arm_aic_device::set_line_callback(*device, DEVCB_##_devcb);
+
+class arm_aic_device : public device_t
+{
+public:
+ // construction/destruction
+ arm_aic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, ARM_AIC, tag, owner, clock),
+ m_irq_out(*this)
+ {
+ }
+
+ // configuration
+ template <class Object> static devcb_base &set_line_callback(device_t &device, Object &&cb) { return downcast<arm_aic_device &>(device).m_irq_out.set_callback(std::forward<Object>(cb)); }
+
+ DECLARE_ADDRESS_MAP(regs_map, 32);
+
+ DECLARE_READ32_MEMBER(irq_vector_r);
+ DECLARE_READ32_MEMBER(firq_vector_r);
+
+ // can't use AM_RAM and AM_SHARE in device submaps
+ DECLARE_READ32_MEMBER(aic_smr_r) { return m_aic_smr[offset]; };
+ DECLARE_READ32_MEMBER(aic_svr_r) { return m_aic_svr[offset]; };
+ DECLARE_WRITE32_MEMBER(aic_smr_w) { COMBINE_DATA(&m_aic_smr[offset]); };
+ DECLARE_WRITE32_MEMBER(aic_svr_w) { COMBINE_DATA(&m_aic_svr[offset]); };
+
+ DECLARE_WRITE32_MEMBER(aic_iecr_w) { /*logerror("%s: aic_iecr_w %08x (Interrupt Enable Command Register)\n", machine().describe_context().c_str(), data);*/ COMBINE_DATA(&m_irqs_enabled); };
+ DECLARE_WRITE32_MEMBER(aic_idcr_w) { /*logerror("%s: aic_idcr_w %08x (Interrupt Disable Command Register)\n", machine().describe_context().c_str(), data);*/ };
+ DECLARE_WRITE32_MEMBER(aic_iccr_w);
+ DECLARE_WRITE32_MEMBER(aic_eoicr_w){ /*logerror("%s: aic_eoicr_w (End of Interrupt Command Register)\n", machine().describe_context().c_str());*/ }; // value doesn't matter
+
+ void set_irq(int identity);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ uint32_t m_irqs_enabled;
+ uint32_t m_current_irq_vector;
+ uint32_t m_current_firq_vector;
+
+ uint32_t m_aic_smr[32];
+ uint32_t m_aic_svr[32];
+
+ devcb_write_line m_irq_out;
+};
+
+#endif
diff --git a/src/mame/drivers/pgm2.cpp b/src/mame/drivers/pgm2.cpp
index 50e31b52d7b..51a8f7c6386 100644
--- a/src/mame/drivers/pgm2.cpp
+++ b/src/mame/drivers/pgm2.cpp
@@ -45,260 +45,23 @@
Support remaining games (need IGS036 dumps)
Identify which regions each game was released in and either dump alt. internal ROMs for each region, or
create them until that can be done.
- RTC
+ RTC (integrated into the CPU with the SRAM?)
Memory Card system (there's an MCU on the motherboard that will need simulating or dumping somehow)
- Sprite Zoom (Dodonpachi Daioujou Tamashii will likely provide test case for this)
+ Verify Sprite Zoom (check exactly which pixels are doubled / missed on hardware for flipped , non-flipped cases etc.)
Simplify IGS036 encryption based on tables in internal roms
- Fix ARM? bug that means Oriental Legend 2 needs a patch
+ Fix ARM? bug that means Oriental Legend 2 needs a patch (might also be that it needs the card reader, and is running a
+ codepath that would not exist in a real environment at the moment)
Fix Save States (is this a driver problem or an ARM core problem, they don't work unless you get through the startup tests)
*/
-#include "emu.h"
-#include "cpu/arm7/arm7.h"
-#include "cpu/arm7/arm7core.h"
-#include "sound/ymz770.h"
-#include "machine/igs036crypt.h"
-#include "screen.h"
-#include "speaker.h"
-#include "machine/nvram.h"
-#include "machine/timer.h"
-
-// see http://sam7-ex256.narod.ru/include/HTML/AT91SAM7X256_AIC.html
-DECLARE_DEVICE_TYPE(ARM_AIC, arm_aic_device)
-
-#define MCFG_ARM_AIC_ADD(_tag) \
- MCFG_DEVICE_ADD(_tag, ARM_AIC, 0)
-
-#define MCFG_IRQ_LINE_CB(_devcb) \
- devcb = &arm_aic_device::set_line_callback(*device, DEVCB_##_devcb);
-
-class arm_aic_device : public device_t
-{
-public:
- // construction/destruction
- arm_aic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- device_t(mconfig, ARM_AIC, tag, owner, clock),
- m_irq_out(*this)
- {
- }
-
- // configuration
- template <class Object> static devcb_base &set_line_callback(device_t &device, Object &&cb) { return downcast<arm_aic_device &>(device).m_irq_out.set_callback(std::forward<Object>(cb)); }
-
- DECLARE_ADDRESS_MAP(regs_map, 32);
-
- DECLARE_READ32_MEMBER(irq_vector_r);
- DECLARE_READ32_MEMBER(firq_vector_r);
-
- // can't use AM_RAM and AM_SHARE in device submaps
- DECLARE_READ32_MEMBER(aic_smr_r) { return m_aic_smr[offset]; };
- DECLARE_READ32_MEMBER(aic_svr_r) { return m_aic_svr[offset]; };
- DECLARE_WRITE32_MEMBER(aic_smr_w) { COMBINE_DATA(&m_aic_smr[offset]); };
- DECLARE_WRITE32_MEMBER(aic_svr_w) { COMBINE_DATA(&m_aic_svr[offset]); };
-
- DECLARE_WRITE32_MEMBER(aic_iecr_w) { /*logerror("%s: aic_iecr_w %08x (Interrupt Enable Command Register)\n", machine().describe_context().c_str(), data);*/ COMBINE_DATA(&m_irqs_enabled); };
- DECLARE_WRITE32_MEMBER(aic_idcr_w) { /*logerror("%s: aic_idcr_w %08x (Interrupt Disable Command Register)\n", machine().describe_context().c_str(), data);*/ };
- DECLARE_WRITE32_MEMBER(aic_iccr_w);
- DECLARE_WRITE32_MEMBER(aic_eoicr_w){ /*logerror("%s: aic_eoicr_w (End of Interrupt Command Register)\n", machine().describe_context().c_str());*/ }; // value doesn't matter
-
- void set_irq(int identity);
-
-protected:
- virtual void device_start() override;
- virtual void device_reset() override;
-
-private:
- uint32_t m_irqs_enabled;
- uint32_t m_current_irq_vector;
- uint32_t m_current_firq_vector;
-
- uint32_t m_aic_smr[32];
- uint32_t m_aic_svr[32];
-
- devcb_write_line m_irq_out;
-};
-
-DEFINE_DEVICE_TYPE(ARM_AIC, arm_aic_device, "arm_aic", "ARM Advanced Interrupt Controller")
-
-DEVICE_ADDRESS_MAP_START( regs_map, 32, arm_aic_device )
- AM_RANGE(0x000, 0x07f) AM_READWRITE(aic_smr_r, aic_smr_w) // AIC_SMR[32] (AIC_SMR) Source Mode Register
- AM_RANGE(0x080, 0x0ff) AM_READWRITE(aic_svr_r, aic_svr_w) // AIC_SVR[32] (AIC_SVR) Source Vector Register
- AM_RANGE(0x100, 0x103) AM_READ(irq_vector_r) // AIC_IVR IRQ Vector Register
- AM_RANGE(0x104, 0x107) AM_READ(firq_vector_r) // AIC_FVR FIQ Vector Register
-// 0x108 AIC_ISR Interrupt Status Register
-// 0x10C AIC_IPR Interrupt Pending Register
-// 0x110 AIC_IMR Interrupt Mask Register
-// 0x114 AIC_CISR Core Interrupt Status Register
- AM_RANGE(0x120, 0x123) AM_WRITE(aic_iecr_w) // 0x120 AIC_IECR Interrupt Enable Command Register
- AM_RANGE(0x124, 0x127) AM_WRITE(aic_idcr_w) // 0x124 AIC_IDCR Interrupt Disable Command Register
- AM_RANGE(0x128, 0x12b) AM_WRITE(aic_iccr_w) // 0x128 AIC_ICCR Interrupt Clear Command Register
-// 0x12C AIC_ISCR Interrupt Set Command Register
- AM_RANGE(0x130, 0x133) AM_WRITE(aic_eoicr_w) // 0x130 AIC_EOICR End of Interrupt Command Register
-// 0x134 AIC_SPU Spurious Vector Register
-// 0x138 AIC_DCR Debug Control Register (Protect)
-// 0x140 AIC_FFER Fast Forcing Enable Register
-// 0x144 AIC_FFDR Fast Forcing Disable Register
-// 0x148 AIC_FFSR Fast Forcing Status Register
-ADDRESS_MAP_END
-
-
-READ32_MEMBER(arm_aic_device::irq_vector_r)
-{
- return m_current_irq_vector;
-}
-
-READ32_MEMBER(arm_aic_device::firq_vector_r)
-{
- return m_current_firq_vector;
-}
-
-void arm_aic_device::device_start()
-{
- m_irq_out.resolve_safe();
-
- save_item(NAME(m_irqs_enabled));
- save_item(NAME(m_current_irq_vector));
- save_item(NAME(m_current_firq_vector));
-
- save_item(NAME(m_aic_smr));
- save_item(NAME(m_aic_svr));
-
-}
-
-void arm_aic_device::device_reset()
-{
- m_irqs_enabled = 0;
- m_current_irq_vector = 0;
- m_current_firq_vector = 0;
-
- for(auto & elem : m_aic_smr) { elem = 0; }
- for(auto & elem : m_aic_svr) { elem = 0; }
-}
-
-void arm_aic_device::set_irq(int identity)
-{
- for (int i = 0;i < 32;i++)
- {
- if (m_aic_smr[i] == identity)
- {
- if ((m_irqs_enabled >> i) & 1)
- {
- m_current_irq_vector = m_aic_svr[i];
- m_irq_out(ASSERT_LINE);
- return;
- }
- }
- }
-}
-
-WRITE32_MEMBER(arm_aic_device::aic_iccr_w)
-{
- //logerror("%s: aic_iccr_w %08x (Interrupt Clear Command Register)\n", machine().describe_context().c_str(), data);
- m_irq_out(CLEAR_LINE);
-};
-
-
-
-class pgm2_state : public driver_device
-{
-public:
- pgm2_state(const machine_config &mconfig, device_type type, const char *tag)
- : driver_device(mconfig, type, tag),
- m_maincpu(*this, "maincpu"),
- m_screen(*this, "screen"),
- m_lineram(*this, "lineram"),
- m_sp_zoom(*this, "sp_zoom"),
- m_mainram(*this, "mainram"),
- m_fg_videoram(*this, "fg_videoram"),
- m_bg_videoram(*this, "bg_videoram"),
- m_sp_videoram(*this, "sp_videoram"),
- m_vid_regs(*this, "vid_regs"),
- m_gfxdecode2(*this, "gfxdecode2"),
- m_gfxdecode3(*this, "gfxdecode3"),
- m_arm_aic(*this, "arm_aic"),
- m_sprites_mask(*this, "sprites_mask"),
- m_sprites_colour(*this, "sprites_colour"),
- m_sp_palette(*this, "sp_palette"),
- m_bg_palette(*this, "bg_palette"),
- m_tx_palette(*this, "tx_palette")
- { }
-
- DECLARE_READ32_MEMBER(unk_startup_r);
- DECLARE_WRITE32_MEMBER(fg_videoram_w);
- DECLARE_WRITE32_MEMBER(bg_videoram_w);
-
- DECLARE_READ32_MEMBER(orleg2_speedup_r);
- DECLARE_READ32_MEMBER(kov2nl_speedup_r);
-
- DECLARE_DRIVER_INIT(kov2nl);
- DECLARE_DRIVER_INIT(orleg2);
- DECLARE_DRIVER_INIT(ddpdojh);
- DECLARE_DRIVER_INIT(kov3);
- DECLARE_DRIVER_INIT(kov3_104);
- DECLARE_DRIVER_INIT(kov3_102);
- DECLARE_DRIVER_INIT(kov3_100);
-
- uint32_t screen_update_pgm2(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
- DECLARE_WRITE_LINE_MEMBER(screen_vblank_pgm2);
- DECLARE_WRITE_LINE_MEMBER(irq);
-
- INTERRUPT_GEN_MEMBER(igs_interrupt);
- TIMER_DEVICE_CALLBACK_MEMBER(igs_interrupt2);
-
-private:
- virtual void machine_start() override;
- virtual void machine_reset() override;
- virtual void video_start() override;
-
- TILE_GET_INFO_MEMBER(get_fg_tile_info);
- TILE_GET_INFO_MEMBER(get_bg_tile_info);
-
- void pgm_create_dummy_internal_arm_region();
- void decrypt_kov3_module(uint32_t addrxor, uint16_t dataxor);
-
- tilemap_t *m_fg_tilemap;
- tilemap_t *m_bg_tilemap;
-
- std::unique_ptr<uint32_t[]> m_spritebufferram; // buffered spriteram
-
- bitmap_ind16 m_sprite_bitmap;
-
- void skip_sprite_chunk(int &palette_offset, uint32_t maskdata, int reverse);
- void draw_sprite_pixel(const rectangle &cliprect, int palette_offset, int realx, int realy, int pal);
- void draw_sprite_chunk(const rectangle &cliprect, int &palette_offset, int x, int realy, int sizex, int xdraw, int pal, uint32_t maskdata, uint32_t zoomx_bits, int growx, int &realxdraw, int realdraw_inc, int palette_inc);
- void draw_sprite_line(const rectangle &cliprect, int &mask_offset, int &palette_offset, int x, int realy, int flipx, int reverse, int sizex, int pal, int zoomybit, int zoomx_bits, int growx);
- void draw_sprites(screen_device &screen, const rectangle &cliprect, uint32_t* spriteram);
- void copy_sprites_from_bitmap(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int pri);
-
- uint32_t m_sprites_mask_mask;
- uint32_t m_sprites_colour_mask;
-
- // devices
- required_device<cpu_device> m_maincpu;
- required_device<screen_device> m_screen;
- required_shared_ptr<uint32_t> m_lineram;
- required_shared_ptr<uint32_t> m_sp_zoom;
- required_shared_ptr<uint32_t> m_mainram;
- required_shared_ptr<uint32_t> m_fg_videoram;
- required_shared_ptr<uint32_t> m_bg_videoram;
- required_shared_ptr<uint32_t> m_sp_videoram;
- required_shared_ptr<uint32_t> m_vid_regs;
- required_device<gfxdecode_device> m_gfxdecode2;
- required_device<gfxdecode_device> m_gfxdecode3;
- required_device<arm_aic_device> m_arm_aic;
- required_region_ptr<uint8_t> m_sprites_mask;
- required_region_ptr<uint8_t> m_sprites_colour;
- required_device<palette_device> m_sp_palette;
- required_device<palette_device> m_bg_palette;
- required_device<palette_device> m_tx_palette;
-};
+#include "includes/pgm2.h"
// checked on startup, or doesn't boot
READ32_MEMBER(pgm2_state::unk_startup_r)
{
logerror("%s: unk_startup_r\n", machine().describe_context().c_str());
- return 0xffffffff;
+ return 0x00000180;
}
INTERRUPT_GEN_MEMBER(pgm2_state::igs_interrupt)
@@ -317,8 +80,9 @@ TIMER_DEVICE_CALLBACK_MEMBER(pgm2_state::igs_interrupt2)
static ADDRESS_MAP_START( pgm2_map, AS_PROGRAM, 32, pgm2_state )
AM_RANGE(0x00000000, 0x00003fff) AM_ROM //AM_REGION("user1", 0x00000) // internal ROM
- AM_RANGE(0x02000000, 0x0200ffff) AM_RAM AM_SHARE("sram") // 'battery ram'
+ AM_RANGE(0x02000000, 0x0200ffff) AM_RAM AM_SHARE("sram") // 'battery ram' (in CPU?)
+ // could be the card reader, looks a bit like a standard IGS MCU comms protocol going on here
AM_RANGE(0x03600000, 0x03600003) AM_WRITENOP
AM_RANGE(0x03620000, 0x03620003) AM_WRITENOP
AM_RANGE(0x03640000, 0x03640003) AM_WRITENOP
@@ -330,7 +94,7 @@ static ADDRESS_MAP_START( pgm2_map, AS_PROGRAM, 32, pgm2_state )
AM_RANGE(0x03a00000, 0x03a00003) AM_READ_PORT("INPUTS1")
AM_RANGE(0x10000000, 0x107fffff) AM_ROM AM_REGION("user1", 0) // external ROM
- AM_RANGE(0x20000000, 0x207fffff) AM_RAM AM_SHARE("mainram")
+ AM_RANGE(0x20000000, 0x2007ffff) AM_RAM AM_SHARE("mainram")
AM_RANGE(0x30000000, 0x30001fff) AM_RAM AM_SHARE("sp_videoram") // spriteram ('move' ram in test mode)
@@ -351,15 +115,16 @@ static ADDRESS_MAP_START( pgm2_map, AS_PROGRAM, 32, pgm2_state )
what is the real size? */
AM_RANGE(0x300e0000, 0x300e03ff) AM_RAM AM_SHARE("lineram") AM_MIRROR(0x000fc00)
- AM_RANGE(0x30100000, 0x301000ff) AM_RAM // unknown
+ AM_RANGE(0x30100000, 0x301000ff) AM_RAM // unknown mask 00ff00ff, seems to be banked with 0x30120030 too?
- AM_RANGE(0x30120000, 0x3012003f) AM_RAM AM_SHARE("vid_regs") // scroll etc.?
+ AM_RANGE(0x30120000, 0x30120003) AM_RAM AM_SHARE("bgscroll") // scroll
+ // there are other 0x301200xx regs
AM_RANGE(0x40000000, 0x40000003) AM_DEVREADWRITE8("ymz774", ymz774_device, read, write, 0xffffffff)
- // internal to IGS036? - various other writes down here on startup too
- AM_RANGE(0xffffec00, 0xffffec5f) AM_RAM // other encryption data?
- AM_RANGE(0xfffffc00, 0xfffffcff) AM_RAM // encryption table (see code at 3950)
+ // internal to IGS036? - various other writes down here on startup too - could be other standard ATMEL peripherals like the ARM_AIC mixed with custom bits
+ AM_RANGE(0xffffec00, 0xffffec5f) AM_RAM
+ AM_RANGE(0xfffffc00, 0xfffffcff) AM_RAM // confirmed as encryption table for main program rom (see code at 3950)
AM_RANGE(0xfffff000, 0xfffff14b) AM_DEVICE("arm_aic", arm_aic_device, regs_map)
@@ -372,17 +137,14 @@ static ADDRESS_MAP_START( pgm2_map, AS_PROGRAM, 32, pgm2_state )
AM_RANGE(0xfffffa0c, 0xfffffa0f) AM_READ(unk_startup_r)
ADDRESS_MAP_END
-
-
-
static INPUT_PORTS_START( pgm2 )
// probably not inputs
PORT_START("UNK1")
- PORT_BIT( 0xffffffff, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0xffffffff, IP_ACTIVE_HIGH, IPT_UNKNOWN )
// probably not inputs
PORT_START("UNK2")
- PORT_BIT( 0xffffffff, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0xffffffff, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_START("INPUTS0")
PORT_BIT( 0x00000001, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1)
@@ -438,9 +200,9 @@ static INPUT_PORTS_START( pgm2 )
PORT_BIT( 0x00010000, IP_ACTIVE_LOW, IPT_COIN3 )
PORT_BIT( 0x00020000, IP_ACTIVE_LOW, IPT_COIN4 )
PORT_BIT( 0x00040000, IP_ACTIVE_LOW, IPT_SERVICE1 ) // test key p1+p2
- PORT_BIT( 0x00080000, IP_ACTIVE_LOW, IPT_UNUSED ) // should be test key p3+p4 but doesn't work in test mode?
+ PORT_BIT( 0x00080000, IP_ACTIVE_LOW, IPT_SERVICE2 ) // test key p3+p4
PORT_BIT( 0x00100000, IP_ACTIVE_LOW, IPT_SERVICE3 ) // service key p1+p2
- PORT_BIT( 0x00200000, IP_ACTIVE_LOW, IPT_SERVICE2 ) // service key p3+p4
+ PORT_BIT( 0x00200000, IP_ACTIVE_LOW, IPT_SERVICE4 ) // service key p3+p4
PORT_BIT( 0x00400000, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x00800000, IP_ACTIVE_LOW, IPT_UNUSED )
@@ -468,354 +230,12 @@ static INPUT_PORTS_START( pgm2 )
PORT_DIPSETTING( 0x00000000, DEF_STR( On ) )
INPUT_PORTS_END
-inline void pgm2_state::draw_sprite_pixel(const rectangle &cliprect, int palette_offset, int realx, int realy, int pal)
-{
- if (cliprect.contains(realx, realy))
- {
- uint16_t pix = m_sprites_colour[palette_offset] & 0x3f; // there are some stray 0xff bytes in some roms, so mask
- uint16_t pendat = pix + (pal * 0x40);
- uint16_t* dstptr_bitmap = &m_sprite_bitmap.pix16(realy);
- dstptr_bitmap[realx] = pendat;
- }
-}
-
-inline void pgm2_state::draw_sprite_chunk(const rectangle &cliprect, int &palette_offset, int x, int realy, int sizex, int xdraw, int pal, uint32_t maskdata, uint32_t zoomx_bits, int growx, int &realxdraw, int realdraw_inc, int palette_inc)
-{
- for (int xchunk = 0; xchunk < 32; xchunk++)
- {
- int pix, xzoombit;
- if (palette_inc == -1)
- {
- pix = (maskdata >> xchunk) & 1;
- xzoombit = (zoomx_bits >> xchunk) & 1;
- }
- else
- {
- pix = (maskdata >> (31 - xchunk)) & 1;
- xzoombit = (zoomx_bits >> (31 - xchunk)) & 1;
- }
-
- if (growx)
- {
- if (pix)
- {
- draw_sprite_pixel(cliprect, palette_offset, x + realxdraw, realy, pal);
- realxdraw += realdraw_inc;
-
- if (xzoombit)
- {
- draw_sprite_pixel(cliprect, palette_offset, x + realxdraw, realy, pal);
- realxdraw += realdraw_inc;
- }
-
- palette_offset += palette_inc;
- palette_offset &= m_sprites_colour_mask;
- }
- else
- {
- realxdraw += realdraw_inc;
- if (xzoombit) realxdraw += realdraw_inc;
- }
- }
- else
- {
- if (pix)
- {
- if (xzoombit) draw_sprite_pixel(cliprect, palette_offset, x + realxdraw, realy, pal);
-
- palette_offset += palette_inc;
- palette_offset &= m_sprites_colour_mask;
- }
-
- if (xzoombit) realxdraw += realdraw_inc;
- }
- }
-}
-
-
-
-inline void pgm2_state::skip_sprite_chunk(int &palette_offset, uint32_t maskdata, int reverse)
-{
- int bits = population_count_32(maskdata);
-
- if (!reverse)
- {
- palette_offset+=bits;
- }
- else
- {
- palette_offset-=bits;
- }
-
- palette_offset &= m_sprites_colour_mask;
-
-}
-
-
-
-inline void pgm2_state::draw_sprite_line(const rectangle &cliprect, int &mask_offset, int &palette_offset, int x, int realy, int flipx, int reverse, int sizex, int pal, int zoomybit, int zoomx_bits, int growx)
-{
- int realxdraw = 0;
-
- if (flipx ^ reverse)
- realxdraw = (population_count_32(zoomx_bits) * sizex) - 1;
-
- for (int xdraw = 0; xdraw < sizex; xdraw++)
- {
- uint32_t maskdata = m_sprites_mask[mask_offset + 0] << 24;
- maskdata |= m_sprites_mask[mask_offset + 1] << 16;
- maskdata |= m_sprites_mask[mask_offset + 2] << 8;
- maskdata |= m_sprites_mask[mask_offset + 3] << 0;
-
- if (reverse)
- {
- mask_offset -= 4;
- }
- else if (!reverse)
- {
- mask_offset += 4;
- }
-
-
- mask_offset &= m_sprites_mask_mask;
-
- if (zoomybit)
- {
- if (!flipx)
- {
- if (!reverse) draw_sprite_chunk(cliprect, palette_offset, x, realy, sizex, xdraw, pal, maskdata, zoomx_bits, growx, realxdraw, 1, 1);
- else draw_sprite_chunk(cliprect, palette_offset, x, realy, sizex, xdraw, pal, maskdata, zoomx_bits, growx, realxdraw, -1, -1);
- }
- else
- {
- if (!reverse) draw_sprite_chunk(cliprect, palette_offset, x, realy, sizex, xdraw, pal, maskdata, zoomx_bits, growx, realxdraw, -1, 1);
- else draw_sprite_chunk(cliprect, palette_offset, x, realy, sizex, xdraw, pal, maskdata, zoomx_bits, growx, realxdraw, 1, -1);
-
- }
- }
- else skip_sprite_chunk(palette_offset, maskdata, reverse);
- }
-}
-
-void pgm2_state::draw_sprites(screen_device &screen, const rectangle &cliprect, uint32_t* spriteram)
-{
- m_sprite_bitmap.fill(0x8000, cliprect);
-
- int endoflist = -1;
-
- //printf("frame\n");
-
- for (int i = 0;i < 0x2000 / 4;i++)
- {
- if (spriteram[i] == 0x80000000)
- {
- endoflist = i;
- break;
- }
- }
-
- if (endoflist != -1)
- {
- for (int i = 0; i < endoflist-2; i += 4)
- {
- //printf("sprite with %08x %08x %08x %08x\n", spriteram[i + 0], spriteram[i + 1], spriteram[i + 2], spriteram[i + 3]);
-
- int x = (spriteram[i + 0] & 0x000007ff) >> 0;
- int y = (spriteram[i + 0] & 0x003ff800) >> 11;
- int pal = (spriteram[i + 0] & 0x0fc00000) >> 22;
- int pri = (spriteram[i + 0] & 0x80000000) >> 31;
-
- int unk0 = (spriteram[i + 0] & 0x70000000) >> 0;
-
- int sizex = (spriteram[i + 1] & 0x0000003f) >> 0;
- int sizey = (spriteram[i + 1] & 0x00007fc0) >> 6;
- int flipx = (spriteram[i + 1] & 0x00800000) >> 23;
- int reverse = (spriteram[i + 1] & 0x80000000) >> 31; // more of a 'reverse entire drawing' flag than y-flip, but used for that purpose
- int zoomx = (spriteram[i + 1] & 0x001f0000) >> 16;
- int growx = (spriteram[i + 1] & 0x00200000) >> 21;
- int zoomy = (spriteram[i + 1] & 0x1f000000) >> 24;
- int growy = (spriteram[i + 1] & 0x20000000) >> 29;
- int unk1 = (spriteram[i + 1] & 0x40408000) >> 0;
-
- if (unk0 || unk1)
- {
- // unk0 & 0x40000000 set during gameplay on kov2nl, why? more pri bits?
- //popmessage("sprite rendering unused bits set unk0 %08x unk1 %08x\n", unk0, unk1);
- }
-
- int mask_offset = (spriteram[i + 2]<<1);
- int palette_offset = (spriteram[i + 3]);
-
- uint32_t zoomy_bits = m_sp_zoom[zoomy];
- uint32_t zoomx_bits = m_sp_zoom[zoomx];
-
- if (x & 0x400) x -=0x800;
- if (y & 0x400) y -=0x800;
-
- if (reverse)
- mask_offset -= 2;
-
- mask_offset &= m_sprites_mask_mask;
- palette_offset &= m_sprites_colour_mask;
-
- pal |= (pri << 6); // encode priority with the palette for manual mixing later
-
- int realy = y;
-
- int sourceline = 0;
- for (int ydraw = 0; ydraw < sizey;sourceline++)
- {
- int zoomy_bit = (zoomy_bits >> (sourceline & 0x1f)) & 1;
-
- // store these for when we need to draw a line twice
- uint32_t pre_palette_offset = palette_offset;
- uint32_t pre_mask_offset = mask_offset;
-
- if (!growy) // skipping lines
- {
- draw_sprite_line(cliprect, mask_offset, palette_offset, x, realy, flipx, reverse, sizex, pal, zoomy_bit, zoomx_bits, growx);
- if (zoomy_bit) realy++;
-
- ydraw++;
- }
- else // doubling lines
- {
- draw_sprite_line(cliprect, mask_offset, palette_offset, x, realy, flipx, reverse, sizex, pal, 1, zoomx_bits, growx);
- realy++;
-
- if (zoomy_bit)
- {
- palette_offset = pre_palette_offset;
- mask_offset = pre_mask_offset;
- }
- else ydraw++;
- }
- }
- }
-
- }
-}
-
-void pgm2_state::copy_sprites_from_bitmap(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int pri)
-{
- pri <<= 12;
-
- const pen_t *paldata = m_sp_palette->pens();
- uint16_t* srcptr_bitmap;
- uint32_t* dstptr_bitmap;
-
- for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
- {
- srcptr_bitmap = &m_sprite_bitmap.pix16(y);
- dstptr_bitmap = &bitmap.pix32(y);
-
- for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
- {
- uint16_t pix = srcptr_bitmap[x];
-
- if (pix != 0x8000)
- {
- if ((pix&0x1000) == pri)
- dstptr_bitmap[x] = paldata[pix & 0xfff];
- }
- }
-
- }
-}
-
-
-
-uint32_t pgm2_state::screen_update_pgm2(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
-{
- m_bg_tilemap->set_scrolly(0, (m_vid_regs[0x0/4] & 0xffff0000)>>16 );
-
- for (int y = 0; y < 224; y++)
- {
- uint16_t linescroll = (y & 1) ? ((m_lineram[(y >> 1)] & 0xffff0000) >> 16) : (m_lineram[(y >> 1)] & 0x0000ffff);
- m_bg_tilemap->set_scrollx((y + ((m_vid_regs[0x0 / 4] & 0xffff0000) >> 16)) & 0x3ff, ((m_vid_regs[0x0 / 4] & 0x0000ffff) >> 0) + linescroll);
- }
-
- const pen_t *paldata = m_bg_palette->pens();
-
- bitmap.fill(paldata[0], cliprect); // are there any places bg pen is showing so we know what it should be?
-
- draw_sprites(screen, cliprect, m_spritebufferram.get());
-
- copy_sprites_from_bitmap(screen, bitmap, cliprect, 1);
-
- m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
-
- copy_sprites_from_bitmap(screen, bitmap, cliprect, 0);
-
- m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
- return 0;
-}
-
-WRITE_LINE_MEMBER(pgm2_state::screen_vblank_pgm2)
-{
- // rising edge
- if (state)
- {
- memcpy(m_spritebufferram.get(), m_sp_videoram, 0x2000);
- }
-}
WRITE_LINE_MEMBER(pgm2_state::irq)
{
// printf("irq\n");
if (state == ASSERT_LINE) m_maincpu->set_input_line(ARM7_IRQ_LINE, ASSERT_LINE);
else m_maincpu->set_input_line(ARM7_IRQ_LINE, CLEAR_LINE);
-
-}
-
-WRITE32_MEMBER(pgm2_state::fg_videoram_w)
-{
- COMBINE_DATA(&m_fg_videoram[offset]);
- m_fg_tilemap->mark_tile_dirty(offset);
-}
-
-TILE_GET_INFO_MEMBER(pgm2_state::get_fg_tile_info)
-{
- int tileno = (m_fg_videoram[tile_index] & 0x0003ffff) >> 0;
- int colour = (m_fg_videoram[tile_index] & 0x007c0000) >> 18; // 5 bits
- int flipxy = (m_fg_videoram[tile_index] & 0x01800000) >> 23;
-
- SET_TILE_INFO_MEMBER(0, tileno, colour, TILE_FLIPXY(flipxy));
-}
-
-
-WRITE32_MEMBER(pgm2_state::bg_videoram_w)
-{
- COMBINE_DATA(&m_bg_videoram[offset]);
- m_bg_tilemap->mark_tile_dirty(offset);
-}
-
-TILE_GET_INFO_MEMBER(pgm2_state::get_bg_tile_info)
-{
- int tileno = (m_bg_videoram[tile_index] & 0x0003ffff) >> 0;
- int colour = (m_bg_videoram[tile_index] & 0x003c0000) >> 18; // 4 bits
- int flipxy = (m_bg_videoram[tile_index] & 0x01800000) >> 23;
-
- SET_TILE_INFO_MEMBER(0, tileno, colour, TILE_FLIPXY(flipxy));
-}
-
-void pgm2_state::video_start()
-{
- m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode2, tilemap_get_info_delegate(FUNC(pgm2_state::get_fg_tile_info), this), TILEMAP_SCAN_ROWS, 8, 8, 96, 48); // 0x4800 bytes
- m_fg_tilemap->set_transparent_pen(0);
-
- m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode3, tilemap_get_info_delegate(FUNC(pgm2_state::get_bg_tile_info), this), TILEMAP_SCAN_ROWS, 32, 32, 64, 32); // 0x2000 bytes
- m_bg_tilemap->set_transparent_pen(0);
- m_bg_tilemap->set_scroll_rows(32 * 32);
-
- m_spritebufferram = make_unique_clear<uint32_t[]>(0x2000 / 4);
-
- m_screen->register_screen_bitmap(m_sprite_bitmap);
-
- save_pointer(NAME(m_spritebufferram.get()), 0x2000 / 4);
-
- m_sprites_mask_mask = memregion("sprites_mask")->bytes() - 1;
- m_sprites_colour_mask = memregion("sprites_colour")->bytes() - 1;
}
void pgm2_state::machine_start()
@@ -949,7 +369,6 @@ static MACHINE_CONFIG_START( pgm2 )
MCFG_CPU_VBLANK_INT_DRIVER("screen", pgm2_state, igs_interrupt)
MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", pgm2_state, igs_interrupt2, "screen", 0, 1)
-
MCFG_ARM_AIC_ADD("arm_aic")
MCFG_IRQ_LINE_CB(WRITELINE(pgm2_state, irq))
@@ -987,6 +406,8 @@ MACHINE_CONFIG_END
we're going to have a LOT of clones to cover all the internal rom regions and external rom revision
combinations, so it keeps things readable */
+// Oriental Legend 2
+
#define ORLEG2_VIDEO_SOUND_ROMS \
ROM_REGION( 0x200000, "tiles", ROMREGION_ERASEFF ) \
ROM_LOAD( "ig-a_text.u4", 0x00000000, 0x0200000, CRC(fa444c32) SHA1(31e5e3efa92d52bf9ab97a0ece51e3b77f52ce8a) ) \
@@ -1044,6 +465,8 @@ ROM_START( orleg2_101 )
ORLEG2_VIDEO_SOUND_ROMS
ROM_END
+// Knights of Valour 2 New Legend
+
#define KOV2NL_VIDEO_SOUND_ROMS \
ROM_REGION( 0x200000, "tiles", ROMREGION_ERASEFF ) \
ROM_LOAD( "ig-a3_text.u4", 0x00000000, 0x0200000, CRC(214530ff) SHA1(4231a02054b0345392a077042b95779fd45d6c22) ) \
@@ -1066,9 +489,6 @@ ROM_END
ROM_REGION(0x10000, "sram", 0) \
ROM_LOAD("gsyx_nvram", 0x00000000, 0x10000, CRC(22400c16) SHA1(f775a16299c30f2ce23d683161b910e06eff37c1) )
-
-
-
#define KOV2NL_PROGRAM_302 \
ROM_REGION( 0x800000, "user1", 0 ) \
ROM_LOAD("gsyx_v302cn.u7", 0x00000000, 0x0800000, CRC(b19cf540) SHA1(25da5804bbfd7ef2cdf5cc5aabaa803d18b98929) )
@@ -1085,7 +505,6 @@ ROM_END
ROM_REGION( 0x04000, "maincpu", 0 ) \
ROM_LOAD( "gsyx_igs036_china.rom", 0x00000000, 0x0004000, CRC(e09fe4ce) SHA1(c0cac64ef8727cbe79d503ec4df66ddb6f2c925e) )
-
ROM_START( kov2nl )
KOV2NL_INTERNAL_CHINA
KOV2NL_PROGRAM_302
@@ -1104,6 +523,8 @@ ROM_START( kov2nl_300 )
KOV2NL_VIDEO_SOUND_ROMS
ROM_END
+// Dodonpachi Daioujou Tamashii
+
#define DDPDOJH_VIDEO_SOUND_ROMS \
ROM_REGION( 0x200000, "tiles", ROMREGION_ERASEFF ) \
ROM_LOAD( "ddpdoj_text.u1", 0x00000000, 0x0200000, CRC(f18141d1) SHA1(a16e0a76bc926a158bb92dfd35aca749c569ef50) ) \
@@ -1123,8 +544,6 @@ ROM_END
ROM_REGION( 0x1000000, "ymz774", ROMREGION_ERASEFF ) /* ymz770 */ \
ROM_LOAD16_WORD_SWAP( "ddpdoj_wave0.u12", 0x00000000, 0x1000000, CRC(2b71a324) SHA1(f69076cc561f40ca564d804bc7bd455066f8d77c) )
-
-
ROM_START( ddpdojh )
ROM_REGION( 0x04000, "maincpu", 0 )
ROM_LOAD( "ddpdoj_igs036.rom", 0x00000000, 0x0004000, NO_DUMP )
@@ -1135,6 +554,8 @@ ROM_START( ddpdojh )
DDPDOJH_VIDEO_SOUND_ROMS
ROM_END
+// Knights of Valour 3
+
/*
The Kov3 Program rom is a module consisting of a NOR flash and a FPGA, this provides an extra layer of encryption on top of the usual
that is only unlocked when the correct sequence is recieved from the ARM MCU (IGS036)
@@ -1161,7 +582,6 @@ ROM_END
ROM_REGION( 0x4000000, "ymz774", ROMREGION_ERASEFF ) /* ymz770 */ \
ROM_LOAD16_WORD_SWAP( "kov3_wave0.u13", 0x00000000, 0x4000000, CRC(aa639152) SHA1(2314c6bd05524525a31a2a4668a36a938b924ba4) )
-
ROM_START( kov3 )
ROM_REGION( 0x04000, "maincpu", 0 )
ROM_LOAD( "kov3_igs036.rom", 0x00000000, 0x0004000, NO_DUMP )
diff --git a/src/mame/includes/pgm2.h b/src/mame/includes/pgm2.h
new file mode 100644
index 00000000000..107c04600ac
--- /dev/null
+++ b/src/mame/includes/pgm2.h
@@ -0,0 +1,114 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+#ifndef MAME_INCLUDES_PGM2_H
+#define MAME_INCLUDES_PGM2_H
+
+#pragma once
+
+#include "emu.h"
+#include "cpu/arm7/arm7.h"
+#include "cpu/arm7/arm7core.h"
+#include "sound/ymz770.h"
+#include "machine/igs036crypt.h"
+#include "screen.h"
+#include "speaker.h"
+#include "machine/nvram.h"
+#include "machine/timer.h"
+#include "machine/atmel_arm_aic.h"
+
+class pgm2_state : public driver_device
+{
+public:
+ pgm2_state(const machine_config &mconfig, device_type type, const char *tag)
+ : driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu"),
+ m_screen(*this, "screen"),
+ m_lineram(*this, "lineram"),
+ m_sp_zoom(*this, "sp_zoom"),
+ m_mainram(*this, "mainram"),
+ m_fg_videoram(*this, "fg_videoram"),
+ m_bg_videoram(*this, "bg_videoram"),
+ m_sp_videoram(*this, "sp_videoram"),
+ m_bgscroll(*this, "bgscroll"),
+ m_gfxdecode2(*this, "gfxdecode2"),
+ m_gfxdecode3(*this, "gfxdecode3"),
+ m_arm_aic(*this, "arm_aic"),
+ m_sprites_mask(*this, "sprites_mask"),
+ m_sprites_colour(*this, "sprites_colour"),
+ m_sp_palette(*this, "sp_palette"),
+ m_bg_palette(*this, "bg_palette"),
+ m_tx_palette(*this, "tx_palette")
+ { }
+
+ DECLARE_READ32_MEMBER(unk_startup_r);
+ DECLARE_WRITE32_MEMBER(fg_videoram_w);
+ DECLARE_WRITE32_MEMBER(bg_videoram_w);
+
+ DECLARE_READ32_MEMBER(orleg2_speedup_r);
+ DECLARE_READ32_MEMBER(kov2nl_speedup_r);
+
+ DECLARE_DRIVER_INIT(kov2nl);
+ DECLARE_DRIVER_INIT(orleg2);
+ DECLARE_DRIVER_INIT(ddpdojh);
+ DECLARE_DRIVER_INIT(kov3);
+ DECLARE_DRIVER_INIT(kov3_104);
+ DECLARE_DRIVER_INIT(kov3_102);
+ DECLARE_DRIVER_INIT(kov3_100);
+
+ uint32_t screen_update_pgm2(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
+ DECLARE_WRITE_LINE_MEMBER(screen_vblank_pgm2);
+ DECLARE_WRITE_LINE_MEMBER(irq);
+
+ INTERRUPT_GEN_MEMBER(igs_interrupt);
+ TIMER_DEVICE_CALLBACK_MEMBER(igs_interrupt2);
+
+private:
+ virtual void machine_start() override;
+ virtual void machine_reset() override;
+ virtual void video_start() override;
+
+ TILE_GET_INFO_MEMBER(get_fg_tile_info);
+ TILE_GET_INFO_MEMBER(get_bg_tile_info);
+
+ void pgm_create_dummy_internal_arm_region();
+ void decrypt_kov3_module(uint32_t addrxor, uint16_t dataxor);
+
+ tilemap_t *m_fg_tilemap;
+ tilemap_t *m_bg_tilemap;
+
+ std::unique_ptr<uint32_t[]> m_spritebufferram; // buffered spriteram
+
+ bitmap_ind16 m_sprite_bitmap;
+
+ void skip_sprite_chunk(int &palette_offset, uint32_t maskdata, int reverse);
+ void draw_sprite_pixel(const rectangle &cliprect, int palette_offset, int realx, int realy, int pal);
+ void draw_sprite_chunk(const rectangle &cliprect, int &palette_offset, int x, int realy, int sizex, int xdraw, int pal, uint32_t maskdata, uint32_t zoomx_bits, int growx, int &realxdraw, int realdraw_inc, int palette_inc);
+ void draw_sprite_line(const rectangle &cliprect, int &mask_offset, int &palette_offset, int x, int realy, int flipx, int reverse, int sizex, int pal, int zoomybit, int zoomx_bits, int growx);
+ void draw_sprites(screen_device &screen, const rectangle &cliprect, uint32_t* spriteram);
+ void copy_sprites_from_bitmap(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int pri);
+
+ uint32_t m_sprites_mask_mask;
+ uint32_t m_sprites_colour_mask;
+
+ // devices
+ required_device<cpu_device> m_maincpu;
+ required_device<screen_device> m_screen;
+ required_shared_ptr<uint32_t> m_lineram;
+ required_shared_ptr<uint32_t> m_sp_zoom;
+ required_shared_ptr<uint32_t> m_mainram;
+ required_shared_ptr<uint32_t> m_fg_videoram;
+ required_shared_ptr<uint32_t> m_bg_videoram;
+ required_shared_ptr<uint32_t> m_sp_videoram;
+ required_shared_ptr<uint32_t> m_bgscroll;
+ required_device<gfxdecode_device> m_gfxdecode2;
+ required_device<gfxdecode_device> m_gfxdecode3;
+ required_device<arm_aic_device> m_arm_aic;
+ required_region_ptr<uint8_t> m_sprites_mask;
+ required_region_ptr<uint8_t> m_sprites_colour;
+ required_device<palette_device> m_sp_palette;
+ required_device<palette_device> m_bg_palette;
+ required_device<palette_device> m_tx_palette;
+};
+
+#endif
diff --git a/src/mame/video/pgm2.cpp b/src/mame/video/pgm2.cpp
new file mode 100644
index 00000000000..9e1627f3cd4
--- /dev/null
+++ b/src/mame/video/pgm2.cpp
@@ -0,0 +1,340 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+#include "includes/pgm2.h"
+
+inline void pgm2_state::draw_sprite_pixel(const rectangle &cliprect, int palette_offset, int realx, int realy, int pal)
+{
+ if (cliprect.contains(realx, realy))
+ {
+ uint16_t pix = m_sprites_colour[palette_offset] & 0x3f; // there are some stray 0xff bytes in some roms, so mask
+ uint16_t pendat = pix + (pal * 0x40);
+ uint16_t* dstptr_bitmap = &m_sprite_bitmap.pix16(realy);
+ dstptr_bitmap[realx] = pendat;
+ }
+}
+
+inline void pgm2_state::draw_sprite_chunk(const rectangle &cliprect, int &palette_offset, int x, int realy, int sizex, int xdraw, int pal, uint32_t maskdata, uint32_t zoomx_bits, int growx, int &realxdraw, int realdraw_inc, int palette_inc)
+{
+ for (int xchunk = 0; xchunk < 32; xchunk++)
+ {
+ int pix, xzoombit;
+ if (palette_inc == -1)
+ {
+ pix = (maskdata >> xchunk) & 1;
+ xzoombit = (zoomx_bits >> xchunk) & 1;
+ }
+ else
+ {
+ pix = (maskdata >> (31 - xchunk)) & 1;
+ xzoombit = (zoomx_bits >> (31 - xchunk)) & 1;
+ }
+
+ if (growx)
+ {
+ if (pix)
+ {
+ draw_sprite_pixel(cliprect, palette_offset, x + realxdraw, realy, pal);
+ realxdraw += realdraw_inc;
+
+ if (xzoombit)
+ {
+ draw_sprite_pixel(cliprect, palette_offset, x + realxdraw, realy, pal);
+ realxdraw += realdraw_inc;
+ }
+
+ palette_offset += palette_inc;
+ palette_offset &= m_sprites_colour_mask;
+ }
+ else
+ {
+ realxdraw += realdraw_inc;
+ if (xzoombit) realxdraw += realdraw_inc;
+ }
+ }
+ else
+ {
+ if (pix)
+ {
+ if (xzoombit) draw_sprite_pixel(cliprect, palette_offset, x + realxdraw, realy, pal);
+
+ palette_offset += palette_inc;
+ palette_offset &= m_sprites_colour_mask;
+ }
+
+ if (xzoombit) realxdraw += realdraw_inc;
+ }
+ }
+}
+
+inline void pgm2_state::skip_sprite_chunk(int &palette_offset, uint32_t maskdata, int reverse)
+{
+ int bits = population_count_32(maskdata);
+
+ if (!reverse)
+ {
+ palette_offset+=bits;
+ }
+ else
+ {
+ palette_offset-=bits;
+ }
+
+ palette_offset &= m_sprites_colour_mask;
+
+}
+
+inline void pgm2_state::draw_sprite_line(const rectangle &cliprect, int &mask_offset, int &palette_offset, int x, int realy, int flipx, int reverse, int sizex, int pal, int zoomybit, int zoomx_bits, int growx)
+{
+ int realxdraw = 0;
+
+ if (flipx ^ reverse)
+ realxdraw = (population_count_32(zoomx_bits) * sizex) - 1;
+
+ for (int xdraw = 0; xdraw < sizex; xdraw++)
+ {
+ uint32_t maskdata = m_sprites_mask[mask_offset + 0] << 24;
+ maskdata |= m_sprites_mask[mask_offset + 1] << 16;
+ maskdata |= m_sprites_mask[mask_offset + 2] << 8;
+ maskdata |= m_sprites_mask[mask_offset + 3] << 0;
+
+ if (reverse)
+ {
+ mask_offset -= 4;
+ }
+ else if (!reverse)
+ {
+ mask_offset += 4;
+ }
+
+
+ mask_offset &= m_sprites_mask_mask;
+
+ if (zoomybit)
+ {
+ if (!flipx)
+ {
+ if (!reverse) draw_sprite_chunk(cliprect, palette_offset, x, realy, sizex, xdraw, pal, maskdata, zoomx_bits, growx, realxdraw, 1, 1);
+ else draw_sprite_chunk(cliprect, palette_offset, x, realy, sizex, xdraw, pal, maskdata, zoomx_bits, growx, realxdraw, -1, -1);
+ }
+ else
+ {
+ if (!reverse) draw_sprite_chunk(cliprect, palette_offset, x, realy, sizex, xdraw, pal, maskdata, zoomx_bits, growx, realxdraw, -1, 1);
+ else draw_sprite_chunk(cliprect, palette_offset, x, realy, sizex, xdraw, pal, maskdata, zoomx_bits, growx, realxdraw, 1, -1);
+
+ }
+ }
+ else skip_sprite_chunk(palette_offset, maskdata, reverse);
+ }
+}
+
+void pgm2_state::draw_sprites(screen_device &screen, const rectangle &cliprect, uint32_t* spriteram)
+{
+ m_sprite_bitmap.fill(0x8000, cliprect);
+
+ int endoflist = -1;
+
+ //printf("frame\n");
+
+ for (int i = 0;i < 0x2000 / 4;i++)
+ {
+ if (spriteram[i] == 0x80000000)
+ {
+ endoflist = i;
+ break;
+ }
+ }
+
+ if (endoflist != -1)
+ {
+ for (int i = 0; i < endoflist-2; i += 4)
+ {
+ //printf("sprite with %08x %08x %08x %08x\n", spriteram[i + 0], spriteram[i + 1], spriteram[i + 2], spriteram[i + 3]);
+
+ int x = (spriteram[i + 0] & 0x000007ff) >> 0;
+ int y = (spriteram[i + 0] & 0x003ff800) >> 11;
+ int pal = (spriteram[i + 0] & 0x0fc00000) >> 22;
+ int pri = (spriteram[i + 0] & 0x80000000) >> 31;
+
+ int unk0 = (spriteram[i + 0] & 0x70000000) >> 0;
+
+ int sizex = (spriteram[i + 1] & 0x0000003f) >> 0;
+ int sizey = (spriteram[i + 1] & 0x00007fc0) >> 6;
+ int flipx = (spriteram[i + 1] & 0x00800000) >> 23;
+ int reverse = (spriteram[i + 1] & 0x80000000) >> 31; // more of a 'reverse entire drawing' flag than y-flip, but used for that purpose
+ int zoomx = (spriteram[i + 1] & 0x001f0000) >> 16;
+ int growx = (spriteram[i + 1] & 0x00200000) >> 21;
+ int zoomy = (spriteram[i + 1] & 0x1f000000) >> 24;
+ int growy = (spriteram[i + 1] & 0x20000000) >> 29;
+ int unk1 = (spriteram[i + 1] & 0x40408000) >> 0;
+
+ if (unk0 || unk1)
+ {
+ // unk0 & 0x40000000 set during gameplay on kov2nl, why? more pri bits?
+ //popmessage("sprite rendering unused bits set unk0 %08x unk1 %08x\n", unk0, unk1);
+ }
+
+ int mask_offset = (spriteram[i + 2]<<1);
+ int palette_offset = (spriteram[i + 3]);
+
+ uint32_t zoomy_bits = m_sp_zoom[zoomy];
+ uint32_t zoomx_bits = m_sp_zoom[zoomx];
+
+ if (x & 0x400) x -=0x800;
+ if (y & 0x400) y -=0x800;
+
+ if (reverse)
+ mask_offset -= 2;
+
+ mask_offset &= m_sprites_mask_mask;
+ palette_offset &= m_sprites_colour_mask;
+
+ pal |= (pri << 6); // encode priority with the palette for manual mixing later
+
+ int realy = y;
+
+ int sourceline = 0;
+ for (int ydraw = 0; ydraw < sizey;sourceline++)
+ {
+ int zoomy_bit = (zoomy_bits >> (sourceline & 0x1f)) & 1;
+
+ // store these for when we need to draw a line twice
+ uint32_t pre_palette_offset = palette_offset;
+ uint32_t pre_mask_offset = mask_offset;
+
+ if (!growy) // skipping lines
+ {
+ draw_sprite_line(cliprect, mask_offset, palette_offset, x, realy, flipx, reverse, sizex, pal, zoomy_bit, zoomx_bits, growx);
+ if (zoomy_bit) realy++;
+
+ ydraw++;
+ }
+ else // doubling lines
+ {
+ draw_sprite_line(cliprect, mask_offset, palette_offset, x, realy, flipx, reverse, sizex, pal, 1, zoomx_bits, growx);
+ realy++;
+
+ if (zoomy_bit)
+ {
+ palette_offset = pre_palette_offset;
+ mask_offset = pre_mask_offset;
+ }
+ else ydraw++;
+ }
+ }
+ }
+
+ }
+}
+
+void pgm2_state::copy_sprites_from_bitmap(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect, int pri)
+{
+ pri <<= 12;
+
+ const pen_t *paldata = m_sp_palette->pens();
+ uint16_t* srcptr_bitmap;
+ uint32_t* dstptr_bitmap;
+
+ for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
+ {
+ srcptr_bitmap = &m_sprite_bitmap.pix16(y);
+ dstptr_bitmap = &bitmap.pix32(y);
+
+ for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
+ {
+ uint16_t pix = srcptr_bitmap[x];
+
+ if (pix != 0x8000)
+ {
+ if ((pix&0x1000) == pri)
+ dstptr_bitmap[x] = paldata[pix & 0xfff];
+ }
+ }
+
+ }
+}
+
+uint32_t pgm2_state::screen_update_pgm2(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
+{
+ m_bg_tilemap->set_scrolly(0, (m_bgscroll[0x0/4] & 0xffff0000)>>16 );
+
+ for (int y = 0; y < 224; y++)
+ {
+ uint16_t linescroll = (y & 1) ? ((m_lineram[(y >> 1)] & 0xffff0000) >> 16) : (m_lineram[(y >> 1)] & 0x0000ffff);
+ m_bg_tilemap->set_scrollx((y + ((m_bgscroll[0x0 / 4] & 0xffff0000) >> 16)) & 0x3ff, ((m_bgscroll[0x0 / 4] & 0x0000ffff) >> 0) + linescroll);
+ }
+
+ const pen_t *paldata = m_bg_palette->pens();
+
+ bitmap.fill(paldata[0], cliprect); // are there any places bg pen is showing so we know what it should be?
+
+ draw_sprites(screen, cliprect, m_spritebufferram.get());
+
+ copy_sprites_from_bitmap(screen, bitmap, cliprect, 1);
+
+ m_bg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
+
+ copy_sprites_from_bitmap(screen, bitmap, cliprect, 0);
+
+ m_fg_tilemap->draw(screen, bitmap, cliprect, 0, 0);
+ return 0;
+}
+
+WRITE_LINE_MEMBER(pgm2_state::screen_vblank_pgm2)
+{
+ // rising edge
+ if (state)
+ {
+ memcpy(m_spritebufferram.get(), m_sp_videoram, 0x2000);
+ }
+}
+
+WRITE32_MEMBER(pgm2_state::fg_videoram_w)
+{
+ COMBINE_DATA(&m_fg_videoram[offset]);
+ m_fg_tilemap->mark_tile_dirty(offset);
+}
+
+TILE_GET_INFO_MEMBER(pgm2_state::get_fg_tile_info)
+{
+ int tileno = (m_fg_videoram[tile_index] & 0x0003ffff) >> 0;
+ int colour = (m_fg_videoram[tile_index] & 0x007c0000) >> 18; // 5 bits
+ int flipxy = (m_fg_videoram[tile_index] & 0x01800000) >> 23;
+
+ SET_TILE_INFO_MEMBER(0, tileno, colour, TILE_FLIPXY(flipxy));
+}
+
+WRITE32_MEMBER(pgm2_state::bg_videoram_w)
+{
+ COMBINE_DATA(&m_bg_videoram[offset]);
+ m_bg_tilemap->mark_tile_dirty(offset);
+}
+
+TILE_GET_INFO_MEMBER(pgm2_state::get_bg_tile_info)
+{
+ int tileno = (m_bg_videoram[tile_index] & 0x0003ffff) >> 0;
+ int colour = (m_bg_videoram[tile_index] & 0x003c0000) >> 18; // 4 bits
+ int flipxy = (m_bg_videoram[tile_index] & 0x01800000) >> 23;
+
+ SET_TILE_INFO_MEMBER(0, tileno, colour, TILE_FLIPXY(flipxy));
+}
+
+void pgm2_state::video_start()
+{
+ m_fg_tilemap = &machine().tilemap().create(*m_gfxdecode2, tilemap_get_info_delegate(FUNC(pgm2_state::get_fg_tile_info), this), TILEMAP_SCAN_ROWS, 8, 8, 96, 48); // 0x4800 bytes
+ m_fg_tilemap->set_transparent_pen(0);
+
+ m_bg_tilemap = &machine().tilemap().create(*m_gfxdecode3, tilemap_get_info_delegate(FUNC(pgm2_state::get_bg_tile_info), this), TILEMAP_SCAN_ROWS, 32, 32, 64, 32); // 0x2000 bytes
+ m_bg_tilemap->set_transparent_pen(0);
+ m_bg_tilemap->set_scroll_rows(32 * 32);
+
+ m_spritebufferram = make_unique_clear<uint32_t[]>(0x2000 / 4);
+
+ m_screen->register_screen_bitmap(m_sprite_bitmap);
+
+ save_pointer(NAME(m_spritebufferram.get()), 0x2000 / 4);
+
+ m_sprites_mask_mask = memregion("sprites_mask")->bytes() - 1;
+ m_sprites_colour_mask = memregion("sprites_colour")->bytes() - 1;
+}
+