mirror of
https://github.com/holub/mame
synced 2025-07-04 09:28:51 +03:00
hyprduel : Cleanups, Add imagetek_i4220_device, Allocate sound output… (#3272)
* hyprduel : Cleanups, Add imagetek_i4220_device, Allocate sound output form real PCB(real PCB only has mono sound output) imagetek_i4100.cpp : Boost tilemap drawing routines when VIDEO_UPDATE_SCANLINE case of screen video attributes, Add notes * Minor cleanup, Add notes * imagetek_i4100 : Fix tilemap drawing at tilemap offset X/Y !=0 case * hyprduel : Fix mistake * magerror : Remove MACHINE_NOT_WORKING Flags
This commit is contained in:
parent
71d728f348
commit
5a8890c31c
@ -2557,8 +2557,6 @@ files {
|
||||
createMAMEProjects(_target, _subtarget, "metro")
|
||||
files {
|
||||
MAME_DIR .. "src/mame/drivers/hyprduel.cpp",
|
||||
MAME_DIR .. "src/mame/includes/hyprduel.h",
|
||||
MAME_DIR .. "src/mame/video/hyprduel.cpp",
|
||||
MAME_DIR .. "src/mame/drivers/metro.cpp",
|
||||
MAME_DIR .. "src/mame/includes/metro.h",
|
||||
MAME_DIR .. "src/mame/video/metro.cpp",
|
||||
|
@ -66,7 +66,7 @@
|
||||
#include "emu.h"
|
||||
#include "imagetek_i4100.h"
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
//**************************************************************************
|
||||
// GLOBAL VARIABLES
|
||||
@ -342,7 +342,7 @@ WRITE16_MEMBER(imagetek_i4100_device::vram_0_w){ COMBINE_DATA(&m_vram_0[offset])
|
||||
WRITE16_MEMBER(imagetek_i4100_device::vram_1_w){ COMBINE_DATA(&m_vram_1[offset]); }
|
||||
WRITE16_MEMBER(imagetek_i4100_device::vram_2_w){ COMBINE_DATA(&m_vram_2[offset]); }
|
||||
|
||||
/* This game uses almost only the blitter to write to the tilemaps.
|
||||
/* Some game uses almost only the blitter to write to the tilemaps.
|
||||
The CPU can only access a "window" of 512x256 pixels in the upper
|
||||
left corner of the big tilemap */
|
||||
// TODO: Puzzlet, Sankokushi & Lady Killer contradicts with aformentioned description (more like RMW?)
|
||||
@ -1053,10 +1053,37 @@ void imagetek_i4100_device::draw_tilemap( screen_device &screen, bitmap_ind16 &b
|
||||
int windowwidth = width >> 2;
|
||||
int windowheight = height >> 3;
|
||||
|
||||
sx += m_tilemap_scrolldx[layer] * (m_screen_flip ? 1 : -1);
|
||||
sy += m_tilemap_scrolldy[layer] * (m_screen_flip ? 1 : -1);
|
||||
int dx = m_tilemap_scrolldx[layer] * (m_screen_flip ? 1 : -1);
|
||||
int dy = m_tilemap_scrolldy[layer] * (m_screen_flip ? 1 : -1);
|
||||
|
||||
for (y = 0; y < scrheight; y++)
|
||||
sx += dx;
|
||||
sy += dy;
|
||||
|
||||
int min_x, max_x, min_y, max_y;
|
||||
|
||||
if (dx != 0)
|
||||
{
|
||||
min_x = 0;
|
||||
max_x = scrwidth-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
min_x = cliprect.min_x;
|
||||
max_x = cliprect.max_x;
|
||||
}
|
||||
|
||||
if (dy != 0)
|
||||
{
|
||||
min_y = 0;
|
||||
max_y = scrheight-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
min_y = cliprect.min_y;
|
||||
max_y = cliprect.max_y;
|
||||
}
|
||||
|
||||
for (y = min_y; y <= max_y; y++)
|
||||
{
|
||||
int scrolly = (sy+y-wy)&(windowheight-1);
|
||||
int x;
|
||||
@ -1070,7 +1097,7 @@ void imagetek_i4100_device::draw_tilemap( screen_device &screen, bitmap_ind16 &b
|
||||
dst = &bitmap.pix16(y);
|
||||
priority_baseaddr = &priority_bitmap.pix8(y);
|
||||
|
||||
for (x = 0; x < scrwidth; x++)
|
||||
for (x = min_x; x <= max_x; x++)
|
||||
{
|
||||
int scrollx = (sx+x-wx)&(windowwidth-1);
|
||||
int srccol = (wx+scrollx)&(width-1);
|
||||
@ -1094,7 +1121,7 @@ void imagetek_i4100_device::draw_tilemap( screen_device &screen, bitmap_ind16 &b
|
||||
dst = &bitmap.pix16(scrheight-y-1);
|
||||
priority_baseaddr = &priority_bitmap.pix8(scrheight-y-1);
|
||||
|
||||
for (x = 0; x < scrwidth; x++)
|
||||
for (x = min_x; x <= max_x; x++)
|
||||
{
|
||||
int scrollx = (sx+x-wx)&(windowwidth-1);
|
||||
int srccol = (wx+scrollx)&(width-1);
|
||||
|
@ -37,16 +37,81 @@ fix comms so it boots, it's a bit of a hack for hyperduel at the moment ;-)
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "includes/hyprduel.h"
|
||||
|
||||
#include "cpu/m68000/m68000.h"
|
||||
#include "machine/timer.h"
|
||||
#include "sound/okim6295.h"
|
||||
#include "sound/ym2151.h"
|
||||
#include "sound/ym2413.h"
|
||||
#include "video/imagetek_i4100.h"
|
||||
|
||||
#include "screen.h"
|
||||
#include "speaker.h"
|
||||
|
||||
|
||||
#define RASTER_LINES 262
|
||||
#define FIRST_VISIBLE_LINE 0
|
||||
#define LAST_VISIBLE_LINE 223
|
||||
|
||||
class hyprduel_state : public driver_device
|
||||
{
|
||||
public:
|
||||
hyprduel_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag)
|
||||
, m_irq_enable(*this, "irq_enable")
|
||||
, m_sharedram(*this, "sharedram%u", 1)
|
||||
, m_maincpu(*this, "maincpu")
|
||||
, m_subcpu(*this, "sub")
|
||||
, m_vdp(*this, "vdp")
|
||||
{ }
|
||||
|
||||
DECLARE_READ16_MEMBER(irq_cause_r);
|
||||
DECLARE_WRITE16_MEMBER(irq_cause_w);
|
||||
DECLARE_WRITE16_MEMBER(subcpu_control_w);
|
||||
DECLARE_READ16_MEMBER(hyprduel_cpusync_trigger1_r);
|
||||
DECLARE_WRITE16_MEMBER(hyprduel_cpusync_trigger1_w);
|
||||
DECLARE_READ16_MEMBER(hyprduel_cpusync_trigger2_r);
|
||||
DECLARE_WRITE16_MEMBER(hyprduel_cpusync_trigger2_w);
|
||||
DECLARE_DRIVER_INIT(magerror);
|
||||
DECLARE_DRIVER_INIT(hyprduel);
|
||||
DECLARE_MACHINE_START(hyprduel);
|
||||
DECLARE_MACHINE_START(magerror);
|
||||
TIMER_CALLBACK_MEMBER(vblank_end_callback);
|
||||
DECLARE_WRITE_LINE_MEMBER(vdp_blit_end_w);
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(interrupt);
|
||||
|
||||
void magerror(machine_config &config);
|
||||
void hyprduel(machine_config &config);
|
||||
void i4220_config(machine_config &config);
|
||||
void hyprduel_map(address_map &map);
|
||||
void hyprduel_map2(address_map &map);
|
||||
void magerror_map(address_map &map);
|
||||
void magerror_map2(address_map &map);
|
||||
protected:
|
||||
virtual void machine_reset() override;
|
||||
|
||||
private:
|
||||
/* memory pointers */
|
||||
required_shared_ptr<uint16_t> m_irq_enable;
|
||||
required_shared_ptr_array<uint16_t, 3> m_sharedram;
|
||||
|
||||
/* misc */
|
||||
emu_timer *m_vblank_end_timer;
|
||||
int m_blitter_bit;
|
||||
int m_requested_int;
|
||||
int m_subcpu_resetline;
|
||||
int m_cpu_trigger;
|
||||
int m_int_num;
|
||||
|
||||
/* devices */
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<cpu_device> m_subcpu;
|
||||
required_device<imagetek_i4220_device> m_vdp;
|
||||
|
||||
void update_irq_state( );
|
||||
};
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Interrupts
|
||||
***************************************************************************/
|
||||
@ -139,14 +204,14 @@ READ16_MEMBER(hyprduel_state::hyprduel_cpusync_trigger1_r)
|
||||
m_cpu_trigger = 0;
|
||||
}
|
||||
|
||||
return m_sharedram1[0x000408 / 2 + offset];
|
||||
return m_sharedram[0][0x000408 / 2 + offset];
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(hyprduel_state::hyprduel_cpusync_trigger1_w)
|
||||
{
|
||||
COMBINE_DATA(&m_sharedram1[0x00040e / 2 + offset]);
|
||||
COMBINE_DATA(&m_sharedram[0][0x00040e / 2 + offset]);
|
||||
|
||||
if (((m_sharedram1[0x00040e / 2] << 16) + m_sharedram1[0x000410 / 2]) != 0x00)
|
||||
if (((m_sharedram[0][0x00040e / 2] << 16) + m_sharedram[0][0x000410 / 2]) != 0x00)
|
||||
{
|
||||
if (!m_cpu_trigger && !m_subcpu_resetline)
|
||||
{
|
||||
@ -165,12 +230,12 @@ READ16_MEMBER(hyprduel_state::hyprduel_cpusync_trigger2_r)
|
||||
m_cpu_trigger = 0;
|
||||
}
|
||||
|
||||
return m_sharedram3[(0xfff34c - 0xfe4000) / 2 + offset];
|
||||
return m_sharedram[2][(0xfff34c - 0xfe4000) / 2 + offset];
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(hyprduel_state::hyprduel_cpusync_trigger2_w)
|
||||
{
|
||||
COMBINE_DATA(&m_sharedram1[0x000408 / 2 + offset]);
|
||||
COMBINE_DATA(&m_sharedram[0][0x000408 / 2 + offset]);
|
||||
|
||||
if (ACCESSING_BITS_8_15)
|
||||
{
|
||||
@ -182,260 +247,21 @@ WRITE16_MEMBER(hyprduel_state::hyprduel_cpusync_trigger2_w)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TIMER_CALLBACK_MEMBER(hyprduel_state::magerror_irq_callback)
|
||||
{
|
||||
m_subcpu->set_input_line(1, HOLD_LINE);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Banked ROM access
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
The main CPU has access to the ROMs that hold the graphics through
|
||||
a banked window of 64k. Those ROMs also usually store the tables for
|
||||
the virtual tiles set. The tile codes to be written to the tilemap
|
||||
memory to render the backgrounds are also stored here, in a format
|
||||
that the blitter can readily use (which is a form of compression)
|
||||
*/
|
||||
|
||||
READ16_MEMBER(hyprduel_state::bankedrom_r)
|
||||
{
|
||||
uint8_t *ROM = memregion("gfx1")->base();
|
||||
size_t len = memregion("gfx1")->bytes();
|
||||
|
||||
offset = offset * 2 + 0x10000 * (*m_rombank);
|
||||
|
||||
if (offset < len)
|
||||
return ((ROM[offset + 0] << 8) + ROM[offset + 1]);
|
||||
else
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Blitter
|
||||
|
||||
[ Registers ]
|
||||
|
||||
Offset: Value:
|
||||
|
||||
0.l Destination Tilemap (1,2,3)
|
||||
4.l Blitter Data Address (byte offset into the gfx ROMs)
|
||||
8.l Destination Address << 7 (byte offset into the tilemap)
|
||||
|
||||
The Blitter reads a byte and looks at the most significative
|
||||
bits for the opcode, while the remaining bits define a value
|
||||
(usually how many bytes to write). The opcode byte may be
|
||||
followed by a number of other bytes:
|
||||
|
||||
76------ Opcode
|
||||
--543210 N
|
||||
(at most N+1 bytes follow)
|
||||
|
||||
|
||||
The blitter is designed to write every other byte (e.g. it
|
||||
writes a byte and skips the next). Hence 2 blits are needed
|
||||
to fill a tilemap (first even, then odd addresses)
|
||||
|
||||
[ Opcodes ]
|
||||
|
||||
0 Copy the following N+1 bytes. If the whole byte
|
||||
is $00: stop and generate an IRQ
|
||||
|
||||
1 Fill N+1 bytes with a sequence, starting with
|
||||
the value in the following byte
|
||||
|
||||
2 Fill N+1 bytes with the value in the following
|
||||
byte
|
||||
|
||||
3 Skip N+1 bytes. If the whole byte is $C0:
|
||||
skip to the next row of the tilemap (+0x200 bytes)
|
||||
but preserve the column passed at the start of the
|
||||
blit (destination address % 0x200)
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
TIMER_CALLBACK_MEMBER(hyprduel_state::blit_done)
|
||||
WRITE_LINE_MEMBER(hyprduel_state::vdp_blit_end_w)
|
||||
{
|
||||
m_requested_int |= 1 << m_blitter_bit;
|
||||
update_irq_state();
|
||||
}
|
||||
|
||||
inline int hyprduel_state::blt_read( const uint8_t *ROM, const int offs )
|
||||
{
|
||||
return ROM[offs];
|
||||
}
|
||||
|
||||
void hyprduel_state::blt_write( address_space &space, const int tmap, const offs_t offs, const uint16_t data, const uint16_t mask )
|
||||
{
|
||||
switch( tmap )
|
||||
{
|
||||
case 1: vram_0_w(space, offs,data,mask); break;
|
||||
case 2: vram_1_w(space, offs, data, mask); break;
|
||||
case 3: vram_2_w(space, offs, data, mask); break;
|
||||
}
|
||||
// logerror("%s : Blitter %X] %04X <- %04X & %04X\n", machine().describe_context(), tmap, offs, data, mask);
|
||||
}
|
||||
|
||||
|
||||
WRITE16_MEMBER(hyprduel_state::blitter_w)
|
||||
{
|
||||
COMBINE_DATA(&m_blitter_regs[offset]);
|
||||
|
||||
if (offset == 0xc / 2)
|
||||
{
|
||||
uint8_t *src = memregion("gfx1")->base();
|
||||
size_t src_len = memregion("gfx1")->bytes();
|
||||
|
||||
uint32_t tmap = (m_blitter_regs[0x00 / 2] << 16) + m_blitter_regs[0x02 / 2];
|
||||
uint32_t src_offs = (m_blitter_regs[0x04 / 2] << 16) + m_blitter_regs[0x06 / 2];
|
||||
uint32_t dst_offs = (m_blitter_regs[0x08 / 2] << 16) + m_blitter_regs[0x0a / 2];
|
||||
|
||||
int shift = (dst_offs & 0x80) ? 0 : 8;
|
||||
uint16_t mask = (dst_offs & 0x80) ? 0x00ff : 0xff00;
|
||||
|
||||
// logerror("CPU #0 PC %06X : Blitter regs %08X, %08X, %08X\n", m_maincpu->pc(), tmap, src_offs, dst_offs);
|
||||
|
||||
dst_offs >>= 7 + 1;
|
||||
switch (tmap)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
break;
|
||||
default:
|
||||
logerror("CPU #0 PC %06X : Blitter unknown destination: %08X\n", m_maincpu->pc(), tmap);
|
||||
return;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
uint16_t b1, b2, count;
|
||||
|
||||
src_offs %= src_len;
|
||||
b1 = blt_read(src, src_offs);
|
||||
// logerror("CPU #0 PC %06X : Blitter opcode %02X at %06X\n", m_maincpu->pc(), b1, src_offs);
|
||||
src_offs++;
|
||||
|
||||
count = ((~b1) & 0x3f) + 1;
|
||||
|
||||
switch ((b1 & 0xc0) >> 6)
|
||||
{
|
||||
case 0:
|
||||
|
||||
/* Stop and Generate an IRQ. We can't generate it now
|
||||
both because it's unlikely that the blitter is so
|
||||
fast and because some games (e.g. lastfort) need to
|
||||
complete the blitter irq service routine before doing
|
||||
another blit. */
|
||||
if (b1 == 0)
|
||||
{
|
||||
m_blit_done_timer->adjust(attotime::from_usec(500));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Copy */
|
||||
while (count--)
|
||||
{
|
||||
src_offs %= src_len;
|
||||
b2 = blt_read(src, src_offs) << shift;
|
||||
src_offs++;
|
||||
|
||||
dst_offs &= 0xffff;
|
||||
blt_write(space, tmap, dst_offs, b2, mask);
|
||||
dst_offs = ((dst_offs + 1) & (0x100 - 1)) | (dst_offs & (~(0x100 - 1)));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 1:
|
||||
|
||||
/* Fill with an increasing value */
|
||||
src_offs %= src_len;
|
||||
b2 = blt_read(src, src_offs);
|
||||
src_offs++;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
dst_offs &= 0xffff;
|
||||
blt_write(space, tmap, dst_offs, b2 << shift, mask);
|
||||
dst_offs = ((dst_offs + 1) & (0x100 - 1)) | (dst_offs & (~(0x100 - 1)));
|
||||
b2++;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 2:
|
||||
|
||||
/* Fill with a fixed value */
|
||||
src_offs %= src_len;
|
||||
b2 = blt_read(src, src_offs) << shift;
|
||||
src_offs++;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
dst_offs &= 0xffff;
|
||||
blt_write(space, tmap, dst_offs, b2, mask);
|
||||
dst_offs = ((dst_offs + 1) & (0x100 - 1)) | (dst_offs & (~(0x100 - 1)));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 3:
|
||||
|
||||
/* Skip to the next line ?? */
|
||||
if (b1 == 0xC0)
|
||||
{
|
||||
dst_offs += 0x100;
|
||||
dst_offs &= ~(0x100 - 1);
|
||||
dst_offs |= (0x100 - 1) & (m_blitter_regs[0x0a / 2] >> (7 + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
dst_offs += count;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
logerror("CPU #0 PC %06X : Blitter unknown opcode %02X at %06X\n", m_maincpu->pc(), b1, src_offs - 1);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Memory Maps
|
||||
***************************************************************************/
|
||||
|
||||
ADDRESS_MAP_START(hyprduel_state::hyprduel_map)
|
||||
AM_RANGE(0x000000, 0x07ffff) AM_ROM
|
||||
AM_RANGE(0x400000, 0x41ffff) AM_RAM_WRITE(vram_0_w) AM_SHARE("vram_0") /* Layer 0 */
|
||||
AM_RANGE(0x420000, 0x43ffff) AM_RAM_WRITE(vram_1_w) AM_SHARE("vram_1") /* Layer 1 */
|
||||
AM_RANGE(0x440000, 0x45ffff) AM_RAM_WRITE(vram_2_w) AM_SHARE("vram_2") /* Layer 2 */
|
||||
AM_RANGE(0x460000, 0x46ffff) AM_READ(bankedrom_r) /* Banked ROM */
|
||||
AM_RANGE(0x470000, 0x473fff) AM_RAM_WRITE(paletteram_w) AM_SHARE("paletteram") /* Palette */
|
||||
AM_RANGE(0x474000, 0x474fff) AM_RAM AM_SHARE("spriteram") /* Sprites */
|
||||
AM_RANGE(0x475000, 0x477fff) AM_RAM /* only used memory test */
|
||||
AM_RANGE(0x478000, 0x4787ff) AM_RAM AM_SHARE("tiletable") /* Tiles Set */
|
||||
AM_RANGE(0x478840, 0x47884d) AM_WRITE(blitter_w) AM_SHARE("blitter_regs") /* Tiles Blitter */
|
||||
AM_RANGE(0x478850, 0x478853) AM_RAM AM_SHARE("spriteregs")
|
||||
AM_RANGE(0x478860, 0x47886b) AM_WRITE(window_w) AM_SHARE("window") /* Tilemap Window */
|
||||
AM_RANGE(0x478870, 0x47887b) AM_RAM_WRITE(scrollreg_w) AM_SHARE("scroll") /* Scroll Regs */
|
||||
AM_RANGE(0x47887c, 0x47887d) AM_WRITE(scrollreg_init_w)
|
||||
AM_RANGE(0x478880, 0x478881) AM_WRITENOP
|
||||
AM_RANGE(0x478890, 0x478891) AM_WRITENOP
|
||||
AM_RANGE(0x4788a0, 0x4788a1) AM_WRITENOP
|
||||
AM_RANGE(0x400000, 0x47ffff) AM_DEVICE("vdp", imagetek_i4220_device, v2_map)
|
||||
AM_RANGE(0x4788a2, 0x4788a3) AM_READWRITE(irq_cause_r, irq_cause_w) /* IRQ Cause,Acknowledge */
|
||||
AM_RANGE(0x4788a4, 0x4788a5) AM_RAM AM_SHARE("irq_enable") /* IRQ Enable */
|
||||
AM_RANGE(0x4788aa, 0x4788ab) AM_RAM AM_SHARE("rombank") /* Rom Bank */
|
||||
AM_RANGE(0x4788ac, 0x4788ad) AM_RAM AM_SHARE("screenctrl") /* Screen Control */
|
||||
AM_RANGE(0x479700, 0x479713) AM_RAM AM_SHARE("videoregs") /* Video Registers */
|
||||
AM_RANGE(0x800000, 0x800001) AM_WRITE(subcpu_control_w)
|
||||
AM_RANGE(0xc00000, 0xc07fff) AM_RAM AM_SHARE("sharedram1")
|
||||
AM_RANGE(0xe00000, 0xe00001) AM_READ_PORT("SERVICE") AM_WRITENOP
|
||||
@ -449,7 +275,7 @@ ADDRESS_MAP_END
|
||||
ADDRESS_MAP_START(hyprduel_state::hyprduel_map2)
|
||||
AM_RANGE(0x000000, 0x003fff) AM_RAM AM_SHARE("sharedram1") /* shadow ($c00000 - $c03fff : vector) */
|
||||
AM_RANGE(0x004000, 0x007fff) AM_READONLY AM_WRITENOP AM_SHARE("sharedram3") /* shadow ($fe4000 - $fe7fff : read only) */
|
||||
AM_RANGE(0x400000, 0x400003) AM_DEVREADWRITE8("ymsnd", ym2151_device, read, write, 0x00ff )
|
||||
AM_RANGE(0x400000, 0x400003) AM_DEVREADWRITE8("ymsnd", ym2151_device, read, write, 0x00ff)
|
||||
AM_RANGE(0x400004, 0x400005) AM_DEVREADWRITE8("oki", okim6295_device, read, write, 0x00ff)
|
||||
AM_RANGE(0x800000, 0x800001) AM_NOP
|
||||
AM_RANGE(0xc00000, 0xc07fff) AM_RAM AM_SHARE("sharedram1")
|
||||
@ -463,27 +289,9 @@ ADDRESS_MAP_END
|
||||
ADDRESS_MAP_START(hyprduel_state::magerror_map)
|
||||
AM_RANGE(0x000000, 0x07ffff) AM_ROM
|
||||
AM_RANGE(0x400000, 0x400001) AM_WRITE(subcpu_control_w)
|
||||
AM_RANGE(0x800000, 0x81ffff) AM_RAM_WRITE(vram_0_w) AM_SHARE("vram_0") /* Layer 0 */
|
||||
AM_RANGE(0x820000, 0x83ffff) AM_RAM_WRITE(vram_1_w) AM_SHARE("vram_1") /* Layer 1 */
|
||||
AM_RANGE(0x840000, 0x85ffff) AM_RAM_WRITE(vram_2_w) AM_SHARE("vram_2") /* Layer 2 */
|
||||
AM_RANGE(0x860000, 0x86ffff) AM_READ(bankedrom_r) /* Banked ROM */
|
||||
AM_RANGE(0x870000, 0x873fff) AM_RAM_WRITE(paletteram_w) AM_SHARE("paletteram") /* Palette */
|
||||
AM_RANGE(0x874000, 0x874fff) AM_RAM AM_SHARE("spriteram") /* Sprites */
|
||||
AM_RANGE(0x875000, 0x877fff) AM_RAM /* only used memory test */
|
||||
AM_RANGE(0x878000, 0x8787ff) AM_RAM AM_SHARE("tiletable") /* Tiles Set */
|
||||
AM_RANGE(0x878840, 0x87884d) AM_WRITE(blitter_w) AM_SHARE("blitter_regs") /* Tiles Blitter */
|
||||
AM_RANGE(0x878850, 0x878853) AM_RAM AM_SHARE("spriteregs")
|
||||
AM_RANGE(0x878860, 0x87886b) AM_WRITE(window_w) AM_SHARE("window") /* Tilemap Window */
|
||||
AM_RANGE(0x878870, 0x87887b) AM_RAM_WRITE(scrollreg_w) AM_SHARE("scroll") /* Scroll Regs */
|
||||
AM_RANGE(0x87887c, 0x87887d) AM_WRITE(scrollreg_init_w)
|
||||
AM_RANGE(0x878880, 0x878881) AM_WRITENOP
|
||||
AM_RANGE(0x878890, 0x878891) AM_WRITENOP
|
||||
AM_RANGE(0x8788a0, 0x8788a1) AM_WRITENOP
|
||||
AM_RANGE(0x800000, 0x87ffff) AM_DEVICE("vdp", imagetek_i4220_device, v2_map)
|
||||
AM_RANGE(0x8788a2, 0x8788a3) AM_READWRITE(irq_cause_r, irq_cause_w) /* IRQ Cause, Acknowledge */
|
||||
AM_RANGE(0x8788a4, 0x8788a5) AM_RAM AM_SHARE("irq_enable") /* IRQ Enable */
|
||||
AM_RANGE(0x8788aa, 0x8788ab) AM_RAM AM_SHARE("rombank") /* Rom Bank */
|
||||
AM_RANGE(0x8788ac, 0x8788ad) AM_RAM AM_SHARE("screenctrl") /* Screen Control */
|
||||
AM_RANGE(0x879700, 0x879713) AM_RAM AM_SHARE("videoregs") /* Video Registers */
|
||||
AM_RANGE(0xc00000, 0xc1ffff) AM_RAM AM_SHARE("sharedram1")
|
||||
AM_RANGE(0xe00000, 0xe00001) AM_READ_PORT("SERVICE") AM_WRITENOP
|
||||
AM_RANGE(0xe00002, 0xe00003) AM_READ_PORT("DSW")
|
||||
@ -611,11 +419,28 @@ static const gfx_layout layout_8x8x4 =
|
||||
};
|
||||
|
||||
/* 8x8x8 tiles for later games */
|
||||
static GFXLAYOUT_RAW( layout_8x8x8h, 8, 8, 8*8, 32*8 )
|
||||
static GFXLAYOUT_RAW( layout_8x8x8, 8, 8, 8*8, 32*8 )
|
||||
|
||||
static GFXDECODE_START( 14220 )
|
||||
GFXDECODE_ENTRY( "gfx1", 0, layout_8x8x4, 0x0, 0x200 ) // [0] 4 Bit Tiles
|
||||
GFXDECODE_ENTRY( "gfx1", 0, layout_8x8x8h, 0x0, 0x20 ) // [1] 8 Bit Tiles
|
||||
/* 16x16x4 tiles for later games */
|
||||
static const gfx_layout layout_16x16x4 =
|
||||
{
|
||||
16,16,
|
||||
RGN_FRAC(1,1),
|
||||
4,
|
||||
{ STEP4(0,1) },
|
||||
{ 4*1,4*0, 4*3,4*2, 4*5,4*4, 4*7,4*6, 4*9,4*8, 4*11,4*10, 4*13,4*12, 4*15,4*14 },
|
||||
{ STEP16(0,4*16) },
|
||||
4*8*8
|
||||
};
|
||||
|
||||
/* 16x16x8 tiles for later games */
|
||||
static GFXLAYOUT_RAW( layout_16x16x8, 16, 16, 16*8, 32*8 )
|
||||
|
||||
static GFXDECODE_START( i4220 )
|
||||
GFXDECODE_ENTRY( "gfx1", 0, layout_8x8x4, 0x0, 0x100 ) // [0] 4 Bit Tiles
|
||||
GFXDECODE_ENTRY( "gfx1", 0, layout_8x8x8, 0x0, 0x10 ) // [1] 8 Bit Tiles
|
||||
GFXDECODE_ENTRY( "gfx1", 0, layout_16x16x4, 0x0, 0x100 ) // [2] 4 Bit Tiles 16x16
|
||||
GFXDECODE_ENTRY( "gfx1", 0, layout_16x16x8, 0x0, 0x10 ) // [3] 8 Bit Tiles 16x16
|
||||
GFXDECODE_END
|
||||
|
||||
/***************************************************************************
|
||||
@ -641,15 +466,25 @@ MACHINE_START_MEMBER(hyprduel_state,hyprduel)
|
||||
save_item(NAME(m_subcpu_resetline));
|
||||
save_item(NAME(m_cpu_trigger));
|
||||
|
||||
m_blit_done_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(hyprduel_state::blit_done), this));
|
||||
m_vblank_end_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(hyprduel_state::vblank_end_callback), this));
|
||||
}
|
||||
|
||||
MACHINE_START_MEMBER(hyprduel_state,magerror)
|
||||
{
|
||||
MACHINE_START_CALL_MEMBER(hyprduel);
|
||||
m_magerror_irq_timer->adjust(attotime::zero, 0, attotime::from_hz(968)); /* tempo? */
|
||||
}
|
||||
MACHINE_CONFIG_START(hyprduel_state::i4220_config)
|
||||
MCFG_DEVICE_ADD("vdp", I4220, XTAL(26'666'000))
|
||||
MCFG_I4100_GFXDECODE("gfxdecode")
|
||||
MCFG_I4100_BLITTER_END_CALLBACK(WRITELINE(hyprduel_state,vdp_blit_end_w))
|
||||
|
||||
MCFG_SCREEN_ADD("screen", RASTER)
|
||||
MCFG_SCREEN_VIDEO_ATTRIBUTES(VIDEO_UPDATE_SCANLINE)
|
||||
MCFG_SCREEN_REFRESH_RATE(60) // Unknown/Unverified
|
||||
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
|
||||
MCFG_SCREEN_SIZE(320, 224)
|
||||
MCFG_SCREEN_VISIBLE_AREA(0, 320-1, FIRST_VISIBLE_LINE, LAST_VISIBLE_LINE)
|
||||
MCFG_SCREEN_UPDATE_DEVICE("vdp", imagetek_i4100_device, screen_update)
|
||||
MCFG_SCREEN_PALETTE(":vdp:palette")
|
||||
|
||||
MCFG_GFXDECODE_ADD("gfxdecode", ":vdp:palette", i4220)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
MACHINE_CONFIG_START(hyprduel_state::hyprduel)
|
||||
|
||||
@ -664,31 +499,17 @@ MACHINE_CONFIG_START(hyprduel_state::hyprduel)
|
||||
MCFG_MACHINE_START_OVERRIDE(hyprduel_state,hyprduel)
|
||||
|
||||
/* video hardware */
|
||||
MCFG_SCREEN_ADD("screen", RASTER)
|
||||
MCFG_SCREEN_VIDEO_ATTRIBUTES(VIDEO_UPDATE_SCANLINE)
|
||||
MCFG_SCREEN_REFRESH_RATE(60)
|
||||
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
|
||||
MCFG_SCREEN_SIZE(320, 224)
|
||||
MCFG_SCREEN_VISIBLE_AREA(0, 320-1, FIRST_VISIBLE_LINE, LAST_VISIBLE_LINE)
|
||||
MCFG_SCREEN_UPDATE_DRIVER(hyprduel_state, screen_update)
|
||||
MCFG_SCREEN_PALETTE("palette")
|
||||
|
||||
MCFG_GFXDECODE_ADD("gfxdecode", "palette", 14220)
|
||||
MCFG_PALETTE_ADD("palette", 8192)
|
||||
|
||||
MCFG_VIDEO_START_OVERRIDE(hyprduel_state,hyprduel_14220)
|
||||
i4220_config(config);
|
||||
|
||||
/* sound hardware */
|
||||
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
|
||||
MCFG_SPEAKER_STANDARD_MONO("mono")
|
||||
|
||||
MCFG_YM2151_ADD("ymsnd", 4000000)
|
||||
MCFG_YM2151_IRQ_HANDLER(INPUTLINE("sub", 1))
|
||||
MCFG_SOUND_ROUTE(0, "lspeaker", 0.80)
|
||||
MCFG_SOUND_ROUTE(1, "rspeaker", 0.80)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.80)
|
||||
|
||||
MCFG_OKIM6295_ADD("oki", 4000000/16/16*132, PIN7_HIGH) // clock frequency & pin 7 not verified
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.57)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.57)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.57)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
@ -701,34 +522,21 @@ MACHINE_CONFIG_START(hyprduel_state::magerror)
|
||||
|
||||
MCFG_CPU_ADD("sub", M68000,20000000/2) /* 10MHz */
|
||||
MCFG_CPU_PROGRAM_MAP(magerror_map2)
|
||||
MCFG_CPU_PERIODIC_INT_DRIVER(hyprduel_state, irq1_line_hold, 968) /* tempo? */
|
||||
|
||||
MCFG_MACHINE_START_OVERRIDE(hyprduel_state,magerror)
|
||||
MCFG_MACHINE_START_OVERRIDE(hyprduel_state,hyprduel)
|
||||
|
||||
/* video hardware */
|
||||
MCFG_SCREEN_ADD("screen", RASTER)
|
||||
MCFG_SCREEN_VIDEO_ATTRIBUTES(VIDEO_UPDATE_SCANLINE)
|
||||
MCFG_SCREEN_REFRESH_RATE(60)
|
||||
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
|
||||
MCFG_SCREEN_SIZE(320, 224)
|
||||
MCFG_SCREEN_VISIBLE_AREA(0, 320-1, FIRST_VISIBLE_LINE, LAST_VISIBLE_LINE)
|
||||
MCFG_SCREEN_UPDATE_DRIVER(hyprduel_state, screen_update)
|
||||
MCFG_SCREEN_PALETTE("palette")
|
||||
|
||||
MCFG_GFXDECODE_ADD("gfxdecode", "palette", 14220)
|
||||
MCFG_PALETTE_ADD("palette", 8192)
|
||||
|
||||
MCFG_VIDEO_START_OVERRIDE(hyprduel_state,magerror_14220)
|
||||
i4220_config(config);
|
||||
|
||||
/* sound hardware */
|
||||
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
|
||||
MCFG_SPEAKER_STANDARD_MONO("mono")
|
||||
|
||||
MCFG_SOUND_ADD("ymsnd", YM2413, 3579545)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.00)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.00)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
|
||||
|
||||
MCFG_OKIM6295_ADD("oki", 4000000/16/16*132, PIN7_HIGH) // clock frequency & pin 7 not verified
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 0.57)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 0.57)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.57)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
/***************************************************************************
|
||||
@ -795,7 +603,6 @@ DRIVER_INIT_MEMBER(hyprduel_state,hyprduel)
|
||||
DRIVER_INIT_MEMBER(hyprduel_state,magerror)
|
||||
{
|
||||
m_int_num = 0x01;
|
||||
m_magerror_irq_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(hyprduel_state::magerror_irq_callback),this));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,137 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Luca Elia, Hau
|
||||
|
||||
#include "machine/timer.h"
|
||||
#include "screen.h"
|
||||
|
||||
#define RASTER_LINES 262
|
||||
#define FIRST_VISIBLE_LINE 0
|
||||
#define LAST_VISIBLE_LINE 223
|
||||
|
||||
class hyprduel_state : public driver_device
|
||||
{
|
||||
public:
|
||||
hyprduel_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag),
|
||||
m_vram_0(*this, "vram_0"),
|
||||
m_vram_1(*this, "vram_1"),
|
||||
m_vram_2(*this, "vram_2"),
|
||||
m_paletteram(*this, "paletteram"),
|
||||
m_spriteram(*this, "spriteram"),
|
||||
m_spriteregs(*this, "spriteregs"),
|
||||
m_tiletable(*this, "tiletable"),
|
||||
m_blitter_regs(*this, "blitter_regs"),
|
||||
m_window(*this, "window"),
|
||||
m_scroll(*this, "scroll"),
|
||||
m_irq_enable(*this, "irq_enable"),
|
||||
m_rombank(*this, "rombank"),
|
||||
m_screenctrl(*this, "screenctrl"),
|
||||
m_videoregs(*this, "videoregs"),
|
||||
m_sharedram1(*this, "sharedram1"),
|
||||
m_sharedram3(*this, "sharedram3"),
|
||||
m_maincpu(*this, "maincpu"),
|
||||
m_subcpu(*this, "sub"),
|
||||
m_gfxdecode(*this, "gfxdecode"),
|
||||
m_screen(*this, "screen"),
|
||||
m_palette(*this, "palette") { }
|
||||
|
||||
DECLARE_READ16_MEMBER(irq_cause_r);
|
||||
DECLARE_WRITE16_MEMBER(irq_cause_w);
|
||||
DECLARE_WRITE16_MEMBER(subcpu_control_w);
|
||||
DECLARE_READ16_MEMBER(hyprduel_cpusync_trigger1_r);
|
||||
DECLARE_WRITE16_MEMBER(hyprduel_cpusync_trigger1_w);
|
||||
DECLARE_READ16_MEMBER(hyprduel_cpusync_trigger2_r);
|
||||
DECLARE_WRITE16_MEMBER(hyprduel_cpusync_trigger2_w);
|
||||
DECLARE_READ16_MEMBER(bankedrom_r);
|
||||
DECLARE_WRITE16_MEMBER(blitter_w);
|
||||
DECLARE_WRITE16_MEMBER(paletteram_w);
|
||||
DECLARE_WRITE16_MEMBER(vram_0_w);
|
||||
DECLARE_WRITE16_MEMBER(vram_1_w);
|
||||
DECLARE_WRITE16_MEMBER(vram_2_w);
|
||||
DECLARE_WRITE16_MEMBER(window_w);
|
||||
DECLARE_WRITE16_MEMBER(scrollreg_w);
|
||||
DECLARE_WRITE16_MEMBER(scrollreg_init_w);
|
||||
DECLARE_DRIVER_INIT(magerror);
|
||||
DECLARE_DRIVER_INIT(hyprduel);
|
||||
TILE_GET_INFO_MEMBER(get_tile_info_0_8bit);
|
||||
TILE_GET_INFO_MEMBER(get_tile_info_1_8bit);
|
||||
TILE_GET_INFO_MEMBER(get_tile_info_2_8bit);
|
||||
DECLARE_MACHINE_START(hyprduel);
|
||||
DECLARE_VIDEO_START(hyprduel_14220);
|
||||
DECLARE_MACHINE_START(magerror);
|
||||
DECLARE_VIDEO_START(magerror_14220);
|
||||
DECLARE_VIDEO_START(common_14220);
|
||||
uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
||||
TIMER_CALLBACK_MEMBER(vblank_end_callback);
|
||||
TIMER_CALLBACK_MEMBER(magerror_irq_callback);
|
||||
TIMER_CALLBACK_MEMBER(blit_done);
|
||||
TIMER_DEVICE_CALLBACK_MEMBER(interrupt);
|
||||
|
||||
void magerror(machine_config &config);
|
||||
void hyprduel(machine_config &config);
|
||||
void hyprduel_map(address_map &map);
|
||||
void hyprduel_map2(address_map &map);
|
||||
void magerror_map(address_map &map);
|
||||
void magerror_map2(address_map &map);
|
||||
protected:
|
||||
virtual void machine_reset() override;
|
||||
|
||||
private:
|
||||
/* memory pointers */
|
||||
required_shared_ptr<uint16_t> m_vram_0;
|
||||
required_shared_ptr<uint16_t> m_vram_1;
|
||||
required_shared_ptr<uint16_t> m_vram_2;
|
||||
required_shared_ptr<uint16_t> m_paletteram;
|
||||
required_shared_ptr<uint16_t> m_spriteram;
|
||||
required_shared_ptr<uint16_t> m_spriteregs;
|
||||
required_shared_ptr<uint16_t> m_tiletable;
|
||||
required_shared_ptr<uint16_t> m_blitter_regs;
|
||||
required_shared_ptr<uint16_t> m_window;
|
||||
required_shared_ptr<uint16_t> m_scroll;
|
||||
required_shared_ptr<uint16_t> m_irq_enable;
|
||||
required_shared_ptr<uint16_t> m_rombank;
|
||||
required_shared_ptr<uint16_t> m_screenctrl;
|
||||
required_shared_ptr<uint16_t> m_videoregs;
|
||||
required_shared_ptr<uint16_t> m_sharedram1;
|
||||
required_shared_ptr<uint16_t> m_sharedram3;
|
||||
std::unique_ptr<uint16_t[]> m_tiletable_old;
|
||||
|
||||
/* video-related */
|
||||
tilemap_t *m_bg_tilemap[3];
|
||||
std::unique_ptr<uint8_t[]> m_empty_tiles;
|
||||
std::unique_ptr<uint8_t[]> m_dirtyindex;
|
||||
int m_sprite_xoffs;
|
||||
int m_sprite_yoffs;
|
||||
std::unique_ptr<uint8_t[]> m_expanded_gfx1;
|
||||
|
||||
/* misc */
|
||||
emu_timer *m_magerror_irq_timer;
|
||||
emu_timer *m_vblank_end_timer;
|
||||
emu_timer *m_blit_done_timer;
|
||||
int m_blitter_bit;
|
||||
int m_requested_int;
|
||||
int m_subcpu_resetline;
|
||||
int m_cpu_trigger;
|
||||
int m_int_num;
|
||||
|
||||
/* devices */
|
||||
required_device<cpu_device> m_maincpu;
|
||||
required_device<cpu_device> m_subcpu;
|
||||
required_device<gfxdecode_device> m_gfxdecode;
|
||||
required_device<screen_device> m_screen;
|
||||
required_device<palette_device> m_palette;
|
||||
|
||||
void postload();
|
||||
inline void get_tile_info( tile_data &tileinfo, int tile_index, int layer, uint16_t *vram);
|
||||
inline void get_tile_info_8bit( tile_data &tileinfo, int tile_index, int layer, uint16_t *vram );
|
||||
inline void get_tile_info_16x16_8bit( tile_data &tileinfo, int tile_index, int layer, uint16_t *vram );
|
||||
inline void vram_w( offs_t offset, uint16_t data, uint16_t mem_mask, int layer, uint16_t *vram );
|
||||
void alloc_empty_tiles( );
|
||||
void expand_gfx1( );
|
||||
void draw_sprites( screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect );
|
||||
void draw_layers( screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int pri, int layers_ctrl );
|
||||
void dirty_tiles( int layer, uint16_t *vram );
|
||||
void update_irq_state( );
|
||||
inline int blt_read( const uint8_t *ROM, const int offs );
|
||||
void blt_write( address_space &space, const int tmap, const offs_t offs, const uint16_t data, const uint16_t mask );
|
||||
};
|
@ -1,730 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Luca Elia, Hau
|
||||
|
||||
/* based on driver from video/metro.c by Luca Elia */
|
||||
/* modified by Hau */
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
-= Metro Games =-
|
||||
|
||||
driver by Luca Elia (l.elia@tin.it)
|
||||
|
||||
|
||||
Note: if MAME_DEBUG is defined, pressing Z with:
|
||||
|
||||
Q Shows Layer 0
|
||||
W Shows Layer 1
|
||||
E Shows Layer 2
|
||||
A Shows Sprites
|
||||
|
||||
Keys can be used together!
|
||||
|
||||
|
||||
[ 3 Scrolling Layers ]
|
||||
|
||||
There is memory for a huge layer, but the actual tilemap
|
||||
is a smaller window (of fixed size) carved from anywhere
|
||||
inside that layer.
|
||||
|
||||
Tile Size: 8 x 8 x 4
|
||||
(later games can switch to 8 x 8 x 8, 16 x 16 x 4/8 at run time)
|
||||
|
||||
Big Layer Size: 2048 x 2048 (8x8 tiles) or 4096 x 4096 (16x16 tiles)
|
||||
|
||||
Tilemap Window Size: 512 x 256 (8x8 tiles) or 1024 x 512 (16x16 tiles)
|
||||
|
||||
The tile codes in memory do not map directly to tiles. They
|
||||
are indexes into a table (with 0x200 entries) that defines
|
||||
a virtual set of tiles for the 3 layers. Each entry in that
|
||||
table adds 16 tiles to the set of available tiles, and decides
|
||||
their color code.
|
||||
|
||||
Tile code with their msbit set are different as they mean:
|
||||
draw a tile filled with a single color (0-1ff)
|
||||
|
||||
|
||||
[ 512 Zooming Sprites ]
|
||||
|
||||
The sprites are NOT tile based: the "tile" size can vary from
|
||||
8 to 64 (independently for width and height) with an 8 pixel
|
||||
granularity. The "tile" address is a multiple of 8x8 pixels.
|
||||
|
||||
Each sprite can be shrinked to ~1/4 or enlarged to ~32x following
|
||||
an exponential curve of sizes (with one zoom value for both width
|
||||
and height)
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "includes/hyprduel.h"
|
||||
|
||||
/***************************************************************************
|
||||
Palette GGGGGRRRRRBBBBBx
|
||||
***************************************************************************/
|
||||
|
||||
WRITE16_MEMBER(hyprduel_state::paletteram_w)
|
||||
{
|
||||
data = COMBINE_DATA(&m_paletteram[offset]);
|
||||
m_palette->set_pen_color(offset, pal5bit(data >> 6), pal5bit(data >> 11), pal5bit(data >> 1));
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Tilemaps: Tiles Set & Window
|
||||
|
||||
Each entry in the Tiles Set RAM uses 2 words to specify a starting
|
||||
tile code and a color code. This adds 16 consecutive tiles with
|
||||
that color code to the set of available tiles.
|
||||
|
||||
Offset: Bits: Value:
|
||||
|
||||
0.w fedc ---- ---- ----
|
||||
---- ba98 7654 ---- Color Code
|
||||
---- ---- ---- 3210 Code High Bits
|
||||
|
||||
2.w Code Low Bits
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Tilemaps: Rendering
|
||||
***************************************************************************/
|
||||
|
||||
/* A 2048 x 2048 virtual tilemap */
|
||||
|
||||
#define BIG_NX (0x100)
|
||||
#define BIG_NY (0x100)
|
||||
|
||||
/* A smaller 512 x 256 window defines the actual tilemap */
|
||||
|
||||
#define WIN_NX (0x40)
|
||||
#define WIN_NY (0x20)
|
||||
//#define WIN_NX (0x40+1)
|
||||
//#define WIN_NY (0x20+1)
|
||||
|
||||
|
||||
/* 8x8x4 tiles only */
|
||||
inline void hyprduel_state::get_tile_info( tile_data &tileinfo, int tile_index, int layer, uint16_t *vram)
|
||||
{
|
||||
uint16_t code;
|
||||
int table_index;
|
||||
uint32_t tile;
|
||||
|
||||
/* The actual tile index depends on the window */
|
||||
tile_index = ((tile_index / WIN_NX + m_window[layer * 2 + 0] / 8) % BIG_NY) * BIG_NX +
|
||||
((tile_index % WIN_NX + m_window[layer * 2 + 1] / 8) % BIG_NX);
|
||||
|
||||
/* Fetch the code */
|
||||
code = vram[tile_index];
|
||||
|
||||
/* Use it as an index into the tiles set table */
|
||||
table_index = ((code & 0x1ff0) >> 4 ) * 2;
|
||||
tile = (m_tiletable[table_index + 0] << 16) + m_tiletable[table_index + 1];
|
||||
|
||||
if (code & 0x8000) /* Special: draw a tile of a single color (i.e. not from the gfx ROMs) */
|
||||
{
|
||||
int _code = code & 0x000f;
|
||||
tileinfo.pen_data = m_empty_tiles.get() + _code * 16 * 16;
|
||||
tileinfo.palette_base = ((code & 0x0ff0)) + 0x1000;
|
||||
tileinfo.flags = 0;
|
||||
tileinfo.group = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
tileinfo.group = 0;
|
||||
SET_TILE_INFO_MEMBER(0,
|
||||
(tile & 0xfffff) + (code & 0xf),
|
||||
(((tile & 0x0ff00000) >> 20)) + 0x100,
|
||||
TILE_FLIPXY((code & 0x6000) >> 13));
|
||||
}
|
||||
}
|
||||
|
||||
/* 8x8x4 or 8x8x8 tiles. It's the tile's color that decides: if its low 4
|
||||
bits are high ($f,$1f,$2f etc) the tile is 8bpp, otherwise it's 4bpp */
|
||||
inline void hyprduel_state::get_tile_info_8bit( tile_data &tileinfo, int tile_index, int layer, uint16_t *vram )
|
||||
{
|
||||
uint16_t code;
|
||||
int table_index;
|
||||
uint32_t tile;
|
||||
|
||||
/* The actual tile index depends on the window */
|
||||
tile_index = ((tile_index / WIN_NX + m_window[layer * 2 + 0] / 8) % BIG_NY) * BIG_NX +
|
||||
((tile_index % WIN_NX + m_window[layer * 2 + 1] / 8) % BIG_NX);
|
||||
|
||||
/* Fetch the code */
|
||||
code = vram[tile_index];
|
||||
|
||||
/* Use it as an index into the tiles set table */
|
||||
table_index = ((code & 0x1ff0) >> 4) * 2;
|
||||
tile = (m_tiletable[table_index + 0] << 16) + m_tiletable[table_index + 1];
|
||||
|
||||
if (code & 0x8000) /* Special: draw a tile of a single color (i.e. not from the gfx ROMs) */
|
||||
{
|
||||
int _code = code & 0x000f;
|
||||
tileinfo.pen_data = m_empty_tiles.get() + _code * 16 * 16;
|
||||
tileinfo.palette_base = ((code & 0x0ff0)) + 0x1000;
|
||||
tileinfo.flags = 0;
|
||||
tileinfo.group = 0;
|
||||
}
|
||||
else if ((tile & 0x00f00000) == 0x00f00000) /* draw tile as 8bpp */
|
||||
{
|
||||
tileinfo.group = 1;
|
||||
SET_TILE_INFO_MEMBER(1,
|
||||
(tile & 0xfffff) + 2*(code & 0xf),
|
||||
((tile & 0x0f000000) >> 24) + 0x10,
|
||||
TILE_FLIPXY((code & 0x6000) >> 13));
|
||||
}
|
||||
else
|
||||
{
|
||||
tileinfo.group = 0;
|
||||
SET_TILE_INFO_MEMBER(0,
|
||||
(tile & 0xfffff) + (code & 0xf),
|
||||
(((tile & 0x0ff00000) >> 20)) + 0x100,
|
||||
TILE_FLIPXY((code & 0x6000) >> 13));
|
||||
}
|
||||
}
|
||||
|
||||
/* 16x16x4 or 16x16x8 tiles. It's the tile's color that decides: if its low 4
|
||||
bits are high ($f,$1f,$2f etc) the tile is 8bpp, otherwise it's 4bpp */
|
||||
inline void hyprduel_state::get_tile_info_16x16_8bit( tile_data &tileinfo, int tile_index, int layer, uint16_t *vram )
|
||||
{
|
||||
uint16_t code;
|
||||
int table_index;
|
||||
uint32_t tile;
|
||||
|
||||
/* The actual tile index depends on the window */
|
||||
tile_index = ((tile_index / WIN_NX + m_window[layer * 2 + 0] / 8) % BIG_NY) * BIG_NX +
|
||||
((tile_index % WIN_NX + m_window[layer * 2 + 1] / 8) % BIG_NX);
|
||||
|
||||
/* Fetch the code */
|
||||
code = vram[tile_index];
|
||||
|
||||
/* Use it as an index into the tiles set table */
|
||||
table_index = ((code & 0x1ff0) >> 4) * 2;
|
||||
tile = (m_tiletable[table_index + 0] << 16) + m_tiletable[table_index + 1];
|
||||
|
||||
if (code & 0x8000) /* Special: draw a tile of a single color (i.e. not from the gfx ROMs) */
|
||||
{
|
||||
int _code = code & 0x000f;
|
||||
tileinfo.pen_data = m_empty_tiles.get() + _code * 16 * 16;
|
||||
tileinfo.palette_base = ((code & 0x0ff0)) + 0x1000;
|
||||
tileinfo.flags = 0;
|
||||
tileinfo.group = 0;
|
||||
}
|
||||
else if ((tile & 0x00f00000) == 0x00f00000) /* draw tile as 8bpp */
|
||||
{
|
||||
tileinfo.group = 1;
|
||||
SET_TILE_INFO_MEMBER(3,
|
||||
(tile & 0xfffff) + 8*(code & 0xf),
|
||||
((tile & 0x0f000000) >> 24) + 0x10,
|
||||
TILE_FLIPXY((code & 0x6000) >> 13));
|
||||
}
|
||||
else
|
||||
{
|
||||
tileinfo.group = 0;
|
||||
SET_TILE_INFO_MEMBER(2,
|
||||
(tile & 0xfffff) + 4*(code & 0xf),
|
||||
(((tile & 0x0ff00000) >> 20)) + 0x100,
|
||||
TILE_FLIPXY((code & 0x6000) >> 13));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
inline void hyprduel_state::vram_w( offs_t offset, uint16_t data, uint16_t mem_mask, int layer, uint16_t *vram )
|
||||
{
|
||||
COMBINE_DATA(&vram[offset]);
|
||||
{
|
||||
/* Account for the window */
|
||||
int col = (offset % BIG_NX) - ((m_window[layer * 2 + 1] / 8) % BIG_NX);
|
||||
int row = (offset / BIG_NX) - ((m_window[layer * 2 + 0] / 8) % BIG_NY);
|
||||
if (col < -(BIG_NX-WIN_NX))
|
||||
col += (BIG_NX-WIN_NX) + WIN_NX;
|
||||
if (row < -(BIG_NY-WIN_NY))
|
||||
row += (BIG_NY-WIN_NY) + WIN_NY;
|
||||
if ((col >= 0) && (col < WIN_NX) && (row >= 0) && (row < WIN_NY))
|
||||
m_bg_tilemap[layer]->mark_tile_dirty(row * WIN_NX + col);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
TILE_GET_INFO_MEMBER(hyprduel_state::get_tile_info_0_8bit)
|
||||
{
|
||||
get_tile_info_8bit(tileinfo, tile_index, 0, m_vram_0);
|
||||
}
|
||||
|
||||
TILE_GET_INFO_MEMBER(hyprduel_state::get_tile_info_1_8bit)
|
||||
{
|
||||
get_tile_info_8bit(tileinfo, tile_index, 1, m_vram_1);
|
||||
}
|
||||
|
||||
TILE_GET_INFO_MEMBER(hyprduel_state::get_tile_info_2_8bit)
|
||||
{
|
||||
get_tile_info_8bit(tileinfo, tile_index, 2, m_vram_2);
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(hyprduel_state::vram_0_w)
|
||||
{
|
||||
vram_w(offset, data, mem_mask, 0, m_vram_0);
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(hyprduel_state::vram_1_w)
|
||||
{
|
||||
vram_w(offset, data, mem_mask, 1, m_vram_1);
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(hyprduel_state::vram_2_w)
|
||||
{
|
||||
vram_w(offset, data, mem_mask, 2, m_vram_2);
|
||||
}
|
||||
|
||||
|
||||
/* Dirty the relevant tilemap when its window changes */
|
||||
WRITE16_MEMBER(hyprduel_state::window_w)
|
||||
{
|
||||
uint16_t olddata = m_window[offset];
|
||||
uint16_t newdata = COMBINE_DATA(&m_window[offset]);
|
||||
if (newdata != olddata)
|
||||
{
|
||||
offset /= 2;
|
||||
m_bg_tilemap[offset]->mark_all_dirty();
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Video Init Routines
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
Sprites are not tile based, so we decode their graphics at runtime.
|
||||
*/
|
||||
|
||||
void hyprduel_state::alloc_empty_tiles( )
|
||||
{
|
||||
int code,i;
|
||||
|
||||
m_empty_tiles = std::make_unique<uint8_t[]>(16*16*16);
|
||||
save_pointer(NAME(m_empty_tiles.get()), 16*16*16);
|
||||
|
||||
for (code = 0; code < 0x10; code++)
|
||||
for (i = 0; i < 16 * 16; i++)
|
||||
m_empty_tiles[16 * 16 * code + i] = code;
|
||||
}
|
||||
|
||||
|
||||
void hyprduel_state::postload()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
uint16_t wx = m_window[i * 2 + 1];
|
||||
uint16_t wy = m_window[i * 2 + 0];
|
||||
|
||||
m_bg_tilemap[i]->set_scrollx(0, m_scroll[i * 2 + 1] - wx - (wx & 7));
|
||||
m_bg_tilemap[i]->set_scrolly(0, m_scroll[i * 2 + 0] - wy - (wy & 7));
|
||||
|
||||
m_bg_tilemap[i]->mark_all_dirty();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void hyprduel_state::expand_gfx1()
|
||||
{
|
||||
uint8_t *base_gfx = memregion("gfx1")->base();
|
||||
uint32_t length = 2 * memregion("gfx1")->bytes();
|
||||
m_expanded_gfx1 = std::make_unique<uint8_t[]>(length);
|
||||
for (int i = 0; i < length; i += 2)
|
||||
{
|
||||
uint8_t src = base_gfx[i / 2];
|
||||
m_expanded_gfx1[i+0] = src & 15;
|
||||
m_expanded_gfx1[i+1] = src >> 4;
|
||||
}
|
||||
}
|
||||
|
||||
VIDEO_START_MEMBER(hyprduel_state,common_14220)
|
||||
{
|
||||
expand_gfx1();
|
||||
alloc_empty_tiles();
|
||||
m_tiletable_old = std::make_unique<uint16_t[]>(m_tiletable.bytes() / 2);
|
||||
m_dirtyindex = std::make_unique<uint8_t[]>(m_tiletable.bytes() / 4);
|
||||
|
||||
save_pointer(NAME(m_tiletable_old.get()), m_tiletable.bytes() / 2);
|
||||
save_pointer(NAME(m_dirtyindex.get()), m_tiletable.bytes() / 4);
|
||||
|
||||
m_bg_tilemap[0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(hyprduel_state::get_tile_info_0_8bit),this), TILEMAP_SCAN_ROWS, 8, 8, WIN_NX, WIN_NY);
|
||||
m_bg_tilemap[1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(hyprduel_state::get_tile_info_1_8bit),this), TILEMAP_SCAN_ROWS, 8, 8, WIN_NX, WIN_NY);
|
||||
m_bg_tilemap[2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(FUNC(hyprduel_state::get_tile_info_2_8bit),this), TILEMAP_SCAN_ROWS, 8, 8, WIN_NX, WIN_NY);
|
||||
|
||||
m_bg_tilemap[0]->map_pen_to_layer(0, 15, TILEMAP_PIXEL_TRANSPARENT);
|
||||
m_bg_tilemap[0]->map_pen_to_layer(1, 255, TILEMAP_PIXEL_TRANSPARENT);
|
||||
|
||||
m_bg_tilemap[1]->map_pen_to_layer(0, 15, TILEMAP_PIXEL_TRANSPARENT);
|
||||
m_bg_tilemap[1]->map_pen_to_layer(1, 255, TILEMAP_PIXEL_TRANSPARENT);
|
||||
|
||||
m_bg_tilemap[2]->map_pen_to_layer(0, 15, TILEMAP_PIXEL_TRANSPARENT);
|
||||
m_bg_tilemap[2]->map_pen_to_layer(1, 255, TILEMAP_PIXEL_TRANSPARENT);
|
||||
|
||||
m_bg_tilemap[0]->set_scrolldx(0, 0);
|
||||
m_bg_tilemap[1]->set_scrolldx(0, 0);
|
||||
m_bg_tilemap[2]->set_scrolldx(0, 0);
|
||||
|
||||
/* Set up save state */
|
||||
save_item(NAME(m_sprite_xoffs));
|
||||
save_item(NAME(m_sprite_yoffs));
|
||||
machine().save().register_postload(save_prepost_delegate(FUNC(hyprduel_state::postload), this));
|
||||
}
|
||||
|
||||
VIDEO_START_MEMBER(hyprduel_state,hyprduel_14220)
|
||||
{
|
||||
VIDEO_START_CALL_MEMBER(common_14220);
|
||||
}
|
||||
|
||||
VIDEO_START_MEMBER(hyprduel_state,magerror_14220)
|
||||
{
|
||||
VIDEO_START_CALL_MEMBER(common_14220);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Video Registers
|
||||
|
||||
|
||||
Offset: Bits: Value:
|
||||
|
||||
0.w Number Of Sprites To Draw
|
||||
2.w f--- ---- ---- ---- Disabled Sprites Layer Priority
|
||||
-edc ---- ---- ----
|
||||
---- ba-- ---- ---- Sprites Masked Layer
|
||||
---- --98 ---- ---- Sprites Priority
|
||||
---- ---- 765- ----
|
||||
---- ---- ---4 3210 Sprites Masked Number
|
||||
4.w Sprites Y Offset
|
||||
6.w Sprites X Offset
|
||||
8.w Sprites Color Codes Start
|
||||
|
||||
-
|
||||
|
||||
10.w fedc ba98 76-- ----
|
||||
---- ---- --54 ---- Layer 2 Priority (3 backmost, 0 frontmost)
|
||||
---- ---- ---- 32-- Layer 1 Priority
|
||||
---- ---- ---- --10 Layer 0 Priority
|
||||
|
||||
12.w Backround Color
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Sprites Drawing
|
||||
|
||||
|
||||
Offset: Bits: Value:
|
||||
|
||||
0.w fedc b--- ---- ---- Priority (0 = Max)
|
||||
---- -a98 7654 3210 X
|
||||
|
||||
2.w fedc ba-- ---- ---- Zoom (Both X & Y)
|
||||
---- --98 7654 3210 Y
|
||||
|
||||
4.w f--- ---- ---- ---- Flip X
|
||||
-e-- ---- ---- ---- Flip Y
|
||||
--dc b--- ---- ---- Size X *
|
||||
---- -a98 ---- ---- Size Y *
|
||||
---- ---- 7654 ---- Color
|
||||
---- ---- ---- 3210 Code High Bits **
|
||||
|
||||
6.w Code Low Bits **
|
||||
|
||||
* 8 pixel increments
|
||||
** 8x8 pixel increments
|
||||
***************************************************************************/
|
||||
|
||||
/* Draw sprites */
|
||||
|
||||
void hyprduel_state::draw_sprites( screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect )
|
||||
{
|
||||
uint8_t *base_gfx4 = m_expanded_gfx1.get();
|
||||
uint8_t *base_gfx8 = memregion("gfx1")->base();
|
||||
uint32_t gfx_size = memregion("gfx1")->bytes();
|
||||
|
||||
int max_x = (m_spriteregs[1]+1) * 2;
|
||||
int max_y = (m_spriteregs[0]+1) * 2;
|
||||
|
||||
int max_sprites = m_spriteram.bytes() / 8;
|
||||
int sprites = m_videoregs[0x00 / 2] % max_sprites;
|
||||
|
||||
int color_start = ((m_videoregs[0x08 / 2] & 0xf) << 4) + 0x100;
|
||||
|
||||
int i, j, pri;
|
||||
static const int primask[4] = { 0x0000, 0xff00, 0xff00|0xf0f0, 0xff00|0xf0f0|0xcccc };
|
||||
|
||||
uint16_t *src;
|
||||
int inc;
|
||||
|
||||
if (sprites == 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < 0x20; i++)
|
||||
{
|
||||
if (!(m_videoregs[0x02 / 2] & 0x8000))
|
||||
{
|
||||
src = m_spriteram + (sprites - 1) * (8 / 2);
|
||||
inc = -(8 / 2);
|
||||
} else {
|
||||
src = m_spriteram;
|
||||
inc = (8 / 2);
|
||||
}
|
||||
|
||||
for (j = 0; j < sprites; j++)
|
||||
{
|
||||
int x, y, attr, code, color, flipx, flipy, zoom, curr_pri, width, height;
|
||||
|
||||
/* Exponential zoom table extracted from daitoride */
|
||||
static const int zoomtable[0x40] =
|
||||
{
|
||||
0xAAC,0x800,0x668,0x554,0x494,0x400,0x390,0x334,
|
||||
0x2E8,0x2AC,0x278,0x248,0x224,0x200,0x1E0,0x1C8,
|
||||
0x1B0,0x198,0x188,0x174,0x164,0x154,0x148,0x13C,
|
||||
0x130,0x124,0x11C,0x110,0x108,0x100,0x0F8,0x0F0,
|
||||
0x0EC,0x0E4,0x0DC,0x0D8,0x0D4,0x0CC,0x0C8,0x0C4,
|
||||
0x0C0,0x0BC,0x0B8,0x0B4,0x0B0,0x0AC,0x0A8,0x0A4,
|
||||
0x0A0,0x09C,0x098,0x094,0x090,0x08C,0x088,0x080,
|
||||
0x078,0x070,0x068,0x060,0x058,0x050,0x048,0x040
|
||||
};
|
||||
|
||||
x = src[0];
|
||||
curr_pri = (x & 0xf800) >> 11;
|
||||
|
||||
if ((curr_pri == 0x1f) || (curr_pri != i))
|
||||
{
|
||||
src += inc;
|
||||
continue;
|
||||
}
|
||||
|
||||
pri = (m_videoregs[0x02 / 2] & 0x0300) >> 8;
|
||||
|
||||
if (!(m_videoregs[0x02 / 2] & 0x8000))
|
||||
{
|
||||
if (curr_pri > (m_videoregs[0x02 / 2] & 0x1f))
|
||||
pri = (m_videoregs[0x02 / 2] & 0x0c00) >> 10;
|
||||
}
|
||||
|
||||
y = src[1];
|
||||
attr = src[2];
|
||||
code = src[3];
|
||||
|
||||
flipx = attr & 0x8000;
|
||||
flipy = attr & 0x4000;
|
||||
color = (attr & 0xf0) >> 4;
|
||||
|
||||
zoom = zoomtable[(y & 0xfc00) >> 10] << (16 - 8);
|
||||
|
||||
x = (x & 0x07ff) - m_sprite_xoffs;
|
||||
y = (y & 0x03ff) - m_sprite_yoffs;
|
||||
|
||||
width = (((attr >> 11) & 0x7) + 1) * 8;
|
||||
height = (((attr >> 8) & 0x7) + 1) * 8;
|
||||
|
||||
uint32_t gfxstart = (8 * 8 * 4 / 8) * (((attr & 0x000f) << 16) + code);
|
||||
|
||||
if (flip_screen())
|
||||
{
|
||||
flipx = !flipx; x = max_x - x - width;
|
||||
flipy = !flipy; y = max_y - y - height;
|
||||
}
|
||||
|
||||
if (color == 0xf) /* 8bpp */
|
||||
{
|
||||
/* Bounds checking */
|
||||
if ((gfxstart + width * height - 1) >= gfx_size)
|
||||
continue;
|
||||
|
||||
gfx_element gfx(m_palette, base_gfx8 + gfxstart, width, height, width, m_palette->entries(), 0, 256);
|
||||
|
||||
gfx.prio_zoom_transpen(bitmap,cliprect,
|
||||
0,
|
||||
color_start >> 4,
|
||||
flipx, flipy,
|
||||
x, y,
|
||||
zoom, zoom,
|
||||
screen.priority(),primask[pri], 255);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Bounds checking */
|
||||
if ((gfxstart + width / 2 * height - 1) >= gfx_size)
|
||||
continue;
|
||||
|
||||
gfx_element gfx(m_palette, base_gfx4 + 2 * gfxstart, width, height, width, m_palette->entries(), 0, 16);
|
||||
|
||||
gfx.prio_zoom_transpen(bitmap,cliprect,
|
||||
0,
|
||||
color + color_start,
|
||||
flipx, flipy,
|
||||
x, y,
|
||||
zoom, zoom,
|
||||
screen.priority(),primask[pri], 15);
|
||||
}
|
||||
#if 0
|
||||
{ /* Display priority + zoom on each sprite */
|
||||
char buf[80];
|
||||
sprintf(buf, "%02X %02X",((src[ 0 ] & 0xf800) >> 11)^0x1f,((src[ 1 ] & 0xfc00) >> 10) );
|
||||
ui_draw_text(buf, x, y);
|
||||
}
|
||||
#endif
|
||||
src += inc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Screen Drawing
|
||||
***************************************************************************/
|
||||
|
||||
WRITE16_MEMBER(hyprduel_state::scrollreg_w)
|
||||
{
|
||||
uint16_t window = m_window[offset];
|
||||
|
||||
COMBINE_DATA(&m_scroll[offset]);
|
||||
|
||||
if (offset & 0x01)
|
||||
m_bg_tilemap[offset / 2]->set_scrollx(0, m_scroll[offset] - window - (window & 7));
|
||||
else
|
||||
m_bg_tilemap[offset / 2]->set_scrolly(0, m_scroll[offset] - window - (window & 7));
|
||||
}
|
||||
|
||||
WRITE16_MEMBER(hyprduel_state::scrollreg_init_w)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
uint16_t wx = m_window[i * 2 + 1];
|
||||
uint16_t wy = m_window[i * 2 + 0];
|
||||
|
||||
m_scroll[i * 2 + 1] = data;
|
||||
m_scroll[i * 2 + 0] = data;
|
||||
|
||||
m_bg_tilemap[i]->set_scrollx(0, data - wx - (wx & 7));
|
||||
m_bg_tilemap[i]->set_scrolly(0, data - wy - (wy & 7));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void hyprduel_state::draw_layers( screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect, int pri, int layers_ctrl )
|
||||
{
|
||||
uint16_t layers_pri = m_videoregs[0x10/2];
|
||||
int layer;
|
||||
|
||||
/* Draw all the layers with priority == pri */
|
||||
for (layer = 2; layer >= 0; layer--) // tilemap[2] below?
|
||||
{
|
||||
if ( pri == ((layers_pri >> (layer*2)) & 3) )
|
||||
{
|
||||
if (layers_ctrl & (1 << layer)) // for debug
|
||||
m_bg_tilemap[layer]->draw(screen, bitmap, cliprect, 0, 1 << (3 - pri));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Dirty tilemaps when the tiles set changes */
|
||||
void hyprduel_state::dirty_tiles( int layer, uint16_t *vram )
|
||||
{
|
||||
int col, row;
|
||||
|
||||
for (row = 0; row < WIN_NY; row++)
|
||||
{
|
||||
for (col = 0; col < WIN_NX; col++)
|
||||
{
|
||||
int offset = (col + m_window[layer * 2 + 1] / 8) % BIG_NX + ((row + m_window[layer * 2 + 0] / 8) % BIG_NY) * BIG_NX;
|
||||
uint16_t code = vram[offset];
|
||||
|
||||
if (!(code & 0x8000) && m_dirtyindex[(code & 0x1ff0) >> 4])
|
||||
m_bg_tilemap[layer]->mark_tile_dirty(row * WIN_NX + col);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t hyprduel_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
||||
{
|
||||
int i, pri, layers_ctrl = -1;
|
||||
uint16_t screenctrl = *m_screenctrl;
|
||||
|
||||
{
|
||||
int dirty = 0;
|
||||
|
||||
memset(m_dirtyindex.get(), 0, m_tiletable.bytes() / 4);
|
||||
for (i = 0; i < m_tiletable.bytes() / 4; i++)
|
||||
{
|
||||
uint32_t tile_new = (m_tiletable[2 * i + 0] << 16 ) + m_tiletable[2 * i + 1];
|
||||
uint32_t tile_old = (m_tiletable_old[2 * i + 0] << 16 ) + m_tiletable_old[2 * i + 1];
|
||||
|
||||
if ((tile_new ^ tile_old) & 0x0fffffff)
|
||||
{
|
||||
m_dirtyindex[i] = 1;
|
||||
dirty = 1;
|
||||
}
|
||||
}
|
||||
memcpy(m_tiletable_old.get(), m_tiletable, m_tiletable.bytes());
|
||||
|
||||
if (dirty)
|
||||
{
|
||||
dirty_tiles(0, m_vram_0);
|
||||
dirty_tiles(1, m_vram_1);
|
||||
dirty_tiles(2, m_vram_2);
|
||||
}
|
||||
}
|
||||
|
||||
m_sprite_xoffs = m_videoregs[0x06 / 2] - (m_spriteregs[1]+1);
|
||||
m_sprite_yoffs = m_videoregs[0x04 / 2] - (m_spriteregs[0]+1);
|
||||
|
||||
/* The background color is selected by a register */
|
||||
screen.priority().fill(0, cliprect);
|
||||
bitmap.fill((m_videoregs[0x12 / 2] & 0x0fff) + 0x1000, cliprect);
|
||||
|
||||
/* Screen Control Register:
|
||||
|
||||
f--- ---- ---- ---- ?
|
||||
-edc b--- ---- ----
|
||||
---- -a98 ---- ---- ? Leds
|
||||
---- ---- 7--- ---- 16x16 Tiles (Layer 2)
|
||||
---- ---- -6-- ---- 16x16 Tiles (Layer 1)
|
||||
---- ---- --5- ---- 16x16 Tiles (Layer 0)
|
||||
---- ---- ---4 32--
|
||||
---- ---- ---- --1- ? Blank Screen
|
||||
---- ---- ---- ---0 Flip Screen */
|
||||
if (screenctrl & 2)
|
||||
return 0;
|
||||
flip_screen_set(screenctrl & 1);
|
||||
|
||||
#if 0
|
||||
if (machine().input().code_pressed(KEYCODE_Z))
|
||||
{ int msk = 0;
|
||||
if (machine().input().code_pressed(KEYCODE_Q)) msk |= 0x01;
|
||||
if (machine().input().code_pressed(KEYCODE_W)) msk |= 0x02;
|
||||
if (machine().input().code_pressed(KEYCODE_E)) msk |= 0x04;
|
||||
if (machine().input().code_pressed(KEYCODE_A)) msk |= 0x08;
|
||||
if (msk != 0)
|
||||
{
|
||||
bitmap.fill(0, cliprect);
|
||||
layers_ctrl &= msk;
|
||||
}
|
||||
|
||||
popmessage("%x-%x-%x:%04x %04x %04x",
|
||||
m_videoregs[0x10/2]&3,(m_videoregs[0x10/2] & 0xc) >> 2, (m_videoregs[0x10/2] & 0x30) >> 4,
|
||||
m_videoregs[0x02/2], m_videoregs[0x08/2],
|
||||
*m_screenctrl);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (pri = 3; pri >= 0; pri--)
|
||||
draw_layers(screen, bitmap, cliprect, pri, layers_ctrl);
|
||||
|
||||
if (layers_ctrl & 0x08)
|
||||
draw_sprites(screen, bitmap, cliprect);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user