Moved Kaneko Super Nova sprite chip emulation inside its own file [David Haywood]

This commit is contained in:
Angelo Salese 2011-03-22 20:57:27 +00:00
parent 4a8673b639
commit 235b0d2e01
9 changed files with 685 additions and 586 deletions

2
.gitattributes vendored
View File

@ -4215,6 +4215,8 @@ src/mame/video/sidepckt.c svneol=native#text/plain
src/mame/video/silkroad.c svneol=native#text/plain
src/mame/video/simpl156.c svneol=native#text/plain
src/mame/video/simpsons.c svneol=native#text/plain
src/mame/video/sknsspr.c svneol=native#text/plain
src/mame/video/sknsspr.h svneol=native#text/plain
src/mame/video/skullxbo.c svneol=native#text/plain
src/mame/video/skydiver.c svneol=native#text/plain
src/mame/video/skyfox.c svneol=native#text/plain

View File

@ -65,9 +65,8 @@ Dumped by Uki
#include "cpu/m68000/m68000.h"
#include "deprecat.h"
#include "sound/ymz280b.h"
#include "includes/suprnova.h"
#include "includes/kaneko16.h"
#include "video/sknsspr.h"
class galpani3_state : public driver_device
{
@ -115,6 +114,8 @@ public:
UINT16 regs1_address_regs[0x20];
UINT16 regs2_address_regs[0x20];
UINT16 regs3_address_regs[0x20];
sknsspr_device* spritegen;
};
@ -146,11 +147,11 @@ static VIDEO_START(galpani3)
state->spriteram32 = auto_alloc_array(machine, UINT32, 0x4000/4);
machine->generic.spriteram_size = 0x4000;
state->spc_regs = auto_alloc_array(machine, UINT32, 0x40/4);
suprnova_alt_enable_sprites = 1;
state->sprite_bitmap_1 = auto_bitmap_alloc(machine,1024,1024,BITMAP_FORMAT_INDEXED16);
state->spritegen = machine->device<sknsspr_device>("spritegen");
state->spritegen->skns_sprite_kludge(0,0);
}
@ -346,7 +347,7 @@ static SCREEN_UPDATE(galpani3)
bitmap_fill(state->sprite_bitmap_1, cliprect, 0x0000);
skns_draw_sprites(screen->machine, state->sprite_bitmap_1, cliprect, state->spriteram32, screen->machine->generic.spriteram_size, screen->machine->region("gfx1")->base(), screen->machine->region ("gfx1")->bytes(), state->spc_regs );
state->spritegen->skns_draw_sprites(screen->machine, state->sprite_bitmap_1, cliprect, state->spriteram32, screen->machine->generic.spriteram_size, screen->machine->region("gfx1")->base(), screen->machine->region ("gfx1")->bytes(), state->spc_regs );
// ignoring priority bits for now..
for (y=0;y<240;y++)
@ -963,6 +964,8 @@ static MACHINE_CONFIG_START( galpani3, galpani3_state )
MCFG_VIDEO_START(galpani3)
MCFG_DEVICE_ADD("spritegen", sknsspr_, 0)
/* sound hardware */
MCFG_SPEAKER_STANDARD_MONO("mono")

View File

@ -172,9 +172,8 @@ there are 9 PALS on the pcb (not dumped)
#include "deprecat.h"
#include "machine/nvram.h"
#include "sound/ymz280b.h"
#include "includes/suprnova.h"
#include "includes/kaneko16.h"
#include "video/sknsspr.h"
class jchan_state : public driver_device
{
@ -198,20 +197,15 @@ public:
UINT16 *mcu_ram;
UINT16 mcu_com[4];
UINT16 *ctrl;
sknsspr_device* spritegen1;
sknsspr_device* spritegen2;
};
/***************************************************************************
MCU Code Simulation
(follows the implementation of kaneko16.c)
Provided we find a working PCB, trojan code will help:
- to get this game working (but there are many #4 sub-commands!)
- to have more patterns and eventualy defeat the MCU 'encryption'
- decapping and manually recovering the interal ROM is being persued
This will benefit galpani3 and other kaneko16 games with TOYBOX MCU.
***************************************************************************/
@ -359,7 +353,12 @@ static VIDEO_START(jchan)
state->sprite_bitmap_1 = auto_bitmap_alloc(machine,1024,1024,BITMAP_FORMAT_INDEXED16);
state->sprite_bitmap_2 = auto_bitmap_alloc(machine,1024,1024,BITMAP_FORMAT_INDEXED16);
suprnova_alt_enable_sprites = 1;
state->spritegen1 = machine->device<sknsspr_device>("spritegen1");
state->spritegen2 = machine->device<sknsspr_device>("spritegen2");
state->spritegen1->skns_sprite_kludge(0,0);
state->spritegen2->skns_sprite_kludge(0,0);
VIDEO_START_CALL( kaneko16_1xVIEW2_tilemaps );
}
@ -387,8 +386,8 @@ static SCREEN_UPDATE(jchan)
bitmap_fill(state->sprite_bitmap_1, cliprect, 0x0000);
bitmap_fill(state->sprite_bitmap_2, cliprect, 0x0000);
skns_draw_sprites(screen->machine, state->sprite_bitmap_1, cliprect, state->sprite_ram32_1, 0x4000, screen->machine->region("gfx1")->base(), screen->machine->region ("gfx1")->bytes(), state->sprite_regs32_1 );
skns_draw_sprites(screen->machine, state->sprite_bitmap_2, cliprect, state->sprite_ram32_2, 0x4000, screen->machine->region("gfx2")->base(), screen->machine->region ("gfx2")->bytes(), state->sprite_regs32_2 );
state->spritegen1->skns_draw_sprites(screen->machine, state->sprite_bitmap_1, cliprect, state->sprite_ram32_1, 0x4000, screen->machine->region("gfx1")->base(), screen->machine->region ("gfx1")->bytes(), state->sprite_regs32_1 );
state->spritegen2->skns_draw_sprites(screen->machine, state->sprite_bitmap_2, cliprect, state->sprite_ram32_2, 0x4000, screen->machine->region("gfx2")->base(), screen->machine->region ("gfx2")->bytes(), state->sprite_regs32_2 );
// ignoring priority bits for now - might use alpha too, check 0x8000 of palette writes
for (y=0;y<240;y++)
@ -690,6 +689,9 @@ static MACHINE_CONFIG_START( jchan, jchan_state )
MCFG_VIDEO_START(jchan)
MCFG_DEVICE_ADD("spritegen1", sknsspr_, 0)
MCFG_DEVICE_ADD("spritegen2", sknsspr_, 0)
MCFG_NVRAM_ADD_0FILL("nvram")
/* sound hardware */

View File

@ -150,8 +150,10 @@ NEP-16
#include "deprecat.h"
#include "sound/ymz280b.h"
#include "cpu/sh2/sh2.h"
#include "includes/suprnova.h"
#include "machine/nvram.h"
#include "video/sknsspr.h"
#include "includes/suprnova.h"
#define BIOS_SKIP 1 // Skip Bios as it takes too long and doesn't complete atm.
@ -791,7 +793,10 @@ static const ymz280b_interface ymz280b_intf =
0 // irq ?
};
static MACHINE_CONFIG_START( skns, driver_device )
static MACHINE_CONFIG_START( skns, skns_state )
MCFG_CPU_ADD("maincpu", SH2,28638000)
MCFG_CPU_PROGRAM_MAP(skns_map)
MCFG_CPU_VBLANK_INT_HACK(skns_interrupt,2)
@ -820,6 +825,8 @@ static MACHINE_CONFIG_START( skns, driver_device )
MCFG_PALETTE_LENGTH(32768)
MCFG_GFXDECODE(skns_bg)
MCFG_DEVICE_ADD("spritegen", sknsspr_, 0)
MCFG_VIDEO_START(skns)
MCFG_VIDEO_RESET(skns)
@ -967,25 +974,25 @@ static void set_drc_pcflush(running_machine *machine, UINT32 addr)
sh2drc_add_pcflush(machine->device("maincpu"), addr);
}
static DRIVER_INIT( galpani4 ) { skns_sprite_kludge(-5,-1); init_skns(machine); }
static DRIVER_INIT( galpanis ) { skns_sprite_kludge(-5,-1); init_skns(machine); }
static DRIVER_INIT( cyvern ) { skns_sprite_kludge(+0,+2); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x604d3c8, 0x604d3cb, 0, 0, cyvern_speedup_r ); set_drc_pcflush(machine, 0x402ebd2); }
static DRIVER_INIT( galpans2 ) { skns_sprite_kludge(-1,-1); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x60fb6bc, 0x60fb6bf, 0, 0, galpans2_speedup_r ); set_drc_pcflush(machine, 0x4049ae2); }
static DRIVER_INIT( gutsn ) { skns_sprite_kludge(+0,+0); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x600c780, 0x600c783, 0, 0, gutsn_speedup_r ); set_drc_pcflush(machine, 0x402206e); }
static DRIVER_INIT( panicstr ) { skns_sprite_kludge(-1,-1); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x60f19e4, 0x60f19e7, 0, 0, panicstr_speedup_r ); set_drc_pcflush(machine, 0x404e68a); }
static DRIVER_INIT( senknow ) { skns_sprite_kludge(+1,+1); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x60000dc, 0x60000df, 0, 0, senknow_speedup_r ); set_drc_pcflush(machine, 0x4017dce); }
static DRIVER_INIT( puzzloop ) { skns_sprite_kludge(-9,-1); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x6081d38, 0x6081d3b, 0, 0, puzzloop_speedup_r ); set_drc_pcflush(machine, 0x401da14); }
static DRIVER_INIT( puzzloopj ) { skns_sprite_kludge(-9,-1); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x6086714, 0x6086717, 0, 0, puzzloopj_speedup_r ); set_drc_pcflush(machine, 0x401dca0); }
static DRIVER_INIT( puzzloopa ) { skns_sprite_kludge(-9,-1); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x6085bcc, 0x6085bcf, 0, 0, puzzloopa_speedup_r ); set_drc_pcflush(machine, 0x401d9d4); }
static DRIVER_INIT( puzzloopu ) { skns_sprite_kludge(-9,-1); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x6085cec, 0x6085cef, 0, 0, puzzloopu_speedup_r ); set_drc_pcflush(machine, 0x401dab0); }
static DRIVER_INIT( jjparads ) { skns_sprite_kludge(+5,+1); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x6000994, 0x6000997, 0, 0, jjparads_speedup_r ); set_drc_pcflush(machine, 0x4015e84); }
static DRIVER_INIT( jjparad2 ) { skns_sprite_kludge(+5,+1); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x6000984, 0x6000987, 0, 0, jjparad2_speedup_r ); set_drc_pcflush(machine, 0x401620a); }
static DRIVER_INIT( ryouran ) { skns_sprite_kludge(+5,+1); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x6000a14, 0x6000a17, 0, 0, ryouran_speedup_r ); set_drc_pcflush(machine, 0x40182ce); }
static DRIVER_INIT( teljan ) { skns_sprite_kludge(+5,+1); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x6002fb4, 0x6002fb7, 0, 0, teljan_speedup_r ); set_drc_pcflush(machine, 0x401ba32); }
static DRIVER_INIT( sengekis ) { skns_sprite_kludge(-192,-272); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x60b74bc, 0x60b74bf, 0, 0, sengekis_speedup_r ); set_drc_pcflush(machine, 0x60006ec); }
static DRIVER_INIT( sengekij ) { skns_sprite_kludge(-192,-272); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x60b7380, 0x60b7383, 0, 0, sengekij_speedup_r ); set_drc_pcflush(machine, 0x60006ec); }
static DRIVER_INIT( sarukani ) { skns_sprite_kludge(-1,-1); init_skns(machine); set_drc_pcflush(machine, 0x4013b42); } // Speedup is in skns_io_w()
static DRIVER_INIT( galpans3 ) { skns_sprite_kludge(-1,-1); init_skns(machine); }
static DRIVER_INIT( galpani4 ) { machine->device<sknsspr_device>("spritegen")->skns_sprite_kludge(-5,-1); init_skns(machine); }
static DRIVER_INIT( galpanis ) { machine->device<sknsspr_device>("spritegen")->skns_sprite_kludge(-5,-1); init_skns(machine); }
static DRIVER_INIT( cyvern ) { machine->device<sknsspr_device>("spritegen")->skns_sprite_kludge(+0,+2); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x604d3c8, 0x604d3cb, 0, 0, cyvern_speedup_r ); set_drc_pcflush(machine, 0x402ebd2); }
static DRIVER_INIT( galpans2 ) { machine->device<sknsspr_device>("spritegen")->skns_sprite_kludge(-1,-1); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x60fb6bc, 0x60fb6bf, 0, 0, galpans2_speedup_r ); set_drc_pcflush(machine, 0x4049ae2); }
static DRIVER_INIT( gutsn ) { machine->device<sknsspr_device>("spritegen")->skns_sprite_kludge(+0,+0); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x600c780, 0x600c783, 0, 0, gutsn_speedup_r ); set_drc_pcflush(machine, 0x402206e); }
static DRIVER_INIT( panicstr ) { machine->device<sknsspr_device>("spritegen")->skns_sprite_kludge(-1,-1); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x60f19e4, 0x60f19e7, 0, 0, panicstr_speedup_r ); set_drc_pcflush(machine, 0x404e68a); }
static DRIVER_INIT( senknow ) { machine->device<sknsspr_device>("spritegen")->skns_sprite_kludge(+1,+1); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x60000dc, 0x60000df, 0, 0, senknow_speedup_r ); set_drc_pcflush(machine, 0x4017dce); }
static DRIVER_INIT( puzzloop ) { machine->device<sknsspr_device>("spritegen")->skns_sprite_kludge(-9,-1); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x6081d38, 0x6081d3b, 0, 0, puzzloop_speedup_r ); set_drc_pcflush(machine, 0x401da14); }
static DRIVER_INIT( puzzloopj ) { machine->device<sknsspr_device>("spritegen")->skns_sprite_kludge(-9,-1); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x6086714, 0x6086717, 0, 0, puzzloopj_speedup_r ); set_drc_pcflush(machine, 0x401dca0); }
static DRIVER_INIT( puzzloopa ) { machine->device<sknsspr_device>("spritegen")->skns_sprite_kludge(-9,-1); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x6085bcc, 0x6085bcf, 0, 0, puzzloopa_speedup_r ); set_drc_pcflush(machine, 0x401d9d4); }
static DRIVER_INIT( puzzloopu ) { machine->device<sknsspr_device>("spritegen")->skns_sprite_kludge(-9,-1); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x6085cec, 0x6085cef, 0, 0, puzzloopu_speedup_r ); set_drc_pcflush(machine, 0x401dab0); }
static DRIVER_INIT( jjparads ) { machine->device<sknsspr_device>("spritegen")->skns_sprite_kludge(+5,+1); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x6000994, 0x6000997, 0, 0, jjparads_speedup_r ); set_drc_pcflush(machine, 0x4015e84); }
static DRIVER_INIT( jjparad2 ) { machine->device<sknsspr_device>("spritegen")->skns_sprite_kludge(+5,+1); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x6000984, 0x6000987, 0, 0, jjparad2_speedup_r ); set_drc_pcflush(machine, 0x401620a); }
static DRIVER_INIT( ryouran ) { machine->device<sknsspr_device>("spritegen")->skns_sprite_kludge(+5,+1); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x6000a14, 0x6000a17, 0, 0, ryouran_speedup_r ); set_drc_pcflush(machine, 0x40182ce); }
static DRIVER_INIT( teljan ) { machine->device<sknsspr_device>("spritegen")->skns_sprite_kludge(+5,+1); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x6002fb4, 0x6002fb7, 0, 0, teljan_speedup_r ); set_drc_pcflush(machine, 0x401ba32); }
static DRIVER_INIT( sengekis ) { machine->device<sknsspr_device>("spritegen")->skns_sprite_kludge(-192,-272); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x60b74bc, 0x60b74bf, 0, 0, sengekis_speedup_r ); set_drc_pcflush(machine, 0x60006ec); }
static DRIVER_INIT( sengekij ) { machine->device<sknsspr_device>("spritegen")->skns_sprite_kludge(-192,-272); init_skns(machine); memory_install_read32_handler(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0x60b7380, 0x60b7383, 0, 0, sengekij_speedup_r ); set_drc_pcflush(machine, 0x60006ec); }
static DRIVER_INIT( sarukani ) { machine->device<sknsspr_device>("spritegen")->skns_sprite_kludge(-1,-1); init_skns(machine); set_drc_pcflush(machine, 0x4013b42); } // Speedup is in skns_io_w()
static DRIVER_INIT( galpans3 ) { machine->device<sknsspr_device>("spritegen")->skns_sprite_kludge(-1,-1); init_skns(machine); }

View File

@ -1,13 +1,20 @@
/*----------- defined in drivers/suprnova.c -----------*/
class skns_state : public driver_device
{
public:
skns_state(running_machine &machine, const driver_device_config_base &config)
: driver_device(machine, config) { }
sknsspr_device* spritegen;
};
extern UINT32 *skns_tilemapA_ram, *skns_tilemapB_ram, *skns_v3slc_ram;
extern UINT32 *skns_palette_ram;
extern UINT32 *skns_pal_regs, *skns_v3_regs, *skns_spc_regs;
/*----------- defined in video/suprnova.c -----------*/
extern int suprnova_alt_enable_sprites;
void skns_sprite_kludge(int x, int y);
void skns_draw_sprites(
running_machine *machine, bitmap_t *bitmap, const rectangle *cliprect,

View File

@ -776,6 +776,7 @@ $(MAMEOBJ)/kaneko.a: \
$(DRIVERS)/kaneko16.o $(MACHINE)/kaneko16.o $(VIDEO)/kaneko16.o \
$(DRIVERS)/sandscrp.o \
$(DRIVERS)/suprnova.o $(VIDEO)/suprnova.o \
$(VIDEO)/sknsspr.o \
$(MAMEOBJ)/konami.a: \
$(DRIVERS)/88games.o $(VIDEO)/88games.o \

575
src/mame/video/sknsspr.c Normal file
View File

@ -0,0 +1,575 @@
/* Super Kaneko Nova System Sprites
"CG24173 6186" & "CG24143 4181" (always used as a pair?)
- used by suprnova.c
galpani3.c
jchan.c
- ToDo:
Get rid of sprite position kludges
Fix zooming precision/rounding (most noticable on jchan backgrounds)
*/
#include "emu.h"
#include "sknsspr.h"
sknsspr_device_config::sknsspr_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock)
: device_config(mconfig, static_alloc_device_config, "sknsspr_device", tag, owner, clock)
{
}
device_config *sknsspr_device_config::static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock)
{
return global_alloc(sknsspr_device_config(mconfig, tag, owner, clock));
}
device_t *sknsspr_device_config::alloc_device(running_machine &machine) const
{
return auto_alloc(&machine, sknsspr_device(machine, *this));
}
sknsspr_device::sknsspr_device(running_machine &_machine, const sknsspr_device_config &config)
: device_t(_machine, config),
m_config(config)
{
}
void sknsspr_device::device_start()
{
//printf("sknsspr_device::device_start()\n");
}
void sknsspr_device::device_reset()
{
//printf("sknsspr_device::device_reset()\n");
}
int sknsspr_device::skns_rle_decode ( running_machine *machine, int romoffset, int size, UINT8*gfx_source, size_t gfx_length )
{
UINT8 *src = gfx_source;
size_t srcsize = gfx_length;
UINT8 *dst = decodebuffer;
int decodeoffset = 0;
while(size>0) {
UINT8 code = src[(romoffset++)%srcsize];
size -= (code & 0x7f) + 1;
if(code & 0x80) { /* (code & 0x7f) normal values will follow */
code &= 0x7f;
do {
dst[(decodeoffset++)%SUPRNOVA_DECODE_BUFFER_SIZE] = src[(romoffset++)%srcsize];
code--;
} while(code != 0xff);
} else { /* repeat next value (code & 0x7f) times */
UINT8 val = src[(romoffset++)%srcsize];
do {
dst[(decodeoffset++)%SUPRNOVA_DECODE_BUFFER_SIZE] = val;
code--;
} while(code != 0xff);
}
}
return &src[romoffset%srcsize]-gfx_source;
}
void sknsspr_device::skns_sprite_kludge(int x, int y)
{
sprite_kludge_x = x;
sprite_kludge_y = y;
}
/* Zooming blitter, zoom is by way of both source and destination offsets */
/* We are working in .6 fixed point if you hadn't guessed */
#define z_decls(step) \
UINT16 zxs = 0x40-(zx_m>>2); \
UINT16 zxd = 0x40-(zx_s>>2); \
UINT16 zys = 0x40-(zy_m>>2); \
UINT16 zyd = 0x40-(zy_s>>2); \
int xs, ys, xd, yd, old, old2; \
int step_spr = step; \
int bxs = 0, bys = 0; \
rectangle clip; \
clip.min_x = cliprect->min_x<<6; \
clip.max_x = (cliprect->max_x+1)<<6; \
clip.min_y = cliprect->min_y<<6; \
clip.max_y = (cliprect->max_y+1)<<6; \
sx <<= 6; \
sy <<= 6; \
x <<= 6; \
y <<= 6;
#define z_clamp_x_min() \
if(x < clip.min_x) { \
do { \
bxs += zxs; \
x += zxd; \
} while(x < clip.min_x); \
}
#define z_clamp_x_max() \
if(x > clip.max_x) { \
do { \
bxs += zxs; \
x -= zxd; \
} while(x > clip.max_x); \
}
#define z_clamp_y_min() \
if(y < clip.min_y) { \
do { \
bys += zys; \
y += zyd; \
} while(y < clip.min_y); \
src += (bys>>6)*step_spr; \
}
#define z_clamp_y_max() \
if(y > clip.max_y) { \
do { \
bys += zys; \
y -= zyd; \
} while(y > clip.max_y); \
src += (bys>>6)*step_spr; \
}
#define z_loop_x() \
xs = bxs; \
xd = x; \
while(xs < sx && xd <= clip.max_x)
#define z_loop_x_flip() \
xs = bxs; \
xd = x; \
while(xs < sx && xd >= clip.min_x)
#define z_loop_y() \
ys = bys; \
yd = y; \
while(ys < sy && yd <= clip.max_y)
#define z_loop_y_flip() \
ys = bys; \
yd = y; \
while(ys < sy && yd >= clip.min_y)
#define z_draw_pixel() \
UINT8 val = src[xs >> 6]; \
if(val) \
*BITMAP_ADDR16(bitmap, yd>>6, xd>>6) = val + colour;
#define z_x_dst(op) \
old = xd; \
do { \
xs += zxs; \
xd op zxd; \
} while(!((xd^old) & ~0x3f));
#define z_y_dst(op) \
old = yd; \
old2 = ys; \
do { \
ys += zys; \
yd op zyd; \
} while(!((yd^old) & ~0x3f)); \
while((ys^old2) & ~0x3f) { \
src += step_spr; \
old2 += 0x40; \
}
static void blit_nf_z(bitmap_t *bitmap, const rectangle *cliprect, const UINT8 *src, int x, int y, int sx, int sy, UINT16 zx_m, UINT16 zx_s, UINT16 zy_m, UINT16 zy_s, int colour)
{
z_decls(sx);
z_clamp_x_min();
z_clamp_y_min();
z_loop_y() {
z_loop_x() {
z_draw_pixel();
z_x_dst(+=);
}
z_y_dst(+=);
}
}
static void blit_fy_z(bitmap_t *bitmap, const rectangle *cliprect, const UINT8 *src, int x, int y, int sx, int sy, UINT16 zx_m, UINT16 zx_s, UINT16 zy_m, UINT16 zy_s, int colour)
{
z_decls(sx);
z_clamp_x_min();
z_clamp_y_max();
z_loop_y_flip() {
z_loop_x() {
z_draw_pixel();
z_x_dst(+=);
}
z_y_dst(-=);
}
}
static void blit_fx_z(bitmap_t *bitmap, const rectangle *cliprect, const UINT8 *src, int x, int y, int sx, int sy, UINT16 zx_m, UINT16 zx_s, UINT16 zy_m, UINT16 zy_s, int colour)
{
z_decls(sx);
z_clamp_x_max();
z_clamp_y_min();
z_loop_y() {
z_loop_x_flip() {
z_draw_pixel();
z_x_dst(-=);
}
z_y_dst(+=);
}
}
static void blit_fxy_z(bitmap_t *bitmap, const rectangle *cliprect, const UINT8 *src, int x, int y, int sx, int sy, UINT16 zx_m, UINT16 zx_s, UINT16 zy_m, UINT16 zy_s, int colour)
{
z_decls(sx);
z_clamp_x_max();
z_clamp_y_max();
z_loop_y_flip() {
z_loop_x_flip() {
z_draw_pixel();
z_x_dst(-=);
}
z_y_dst(-=);
}
}
static void (*const blit_z[4])(bitmap_t *bitmap, const rectangle *cliprect, const UINT8 *src, int x, int y, int sx, int sy, UINT16 zx_m, UINT16 zx_s, UINT16 zy_m, UINT16 zy_s, int colour) = {
blit_nf_z,
blit_fy_z,
blit_fx_z,
blit_fxy_z,
};
void sknsspr_device::skns_draw_sprites(running_machine *machine, bitmap_t *bitmap, const rectangle *cliprect, UINT32* spriteram_source, size_t spriteram_size, UINT8* gfx_source, size_t gfx_length, UINT32* sprite_regs)
{
/*- SPR RAM Format -**
16 bytes per sprite
0x00 --ss --SS z--- ---- jjjg g-ff ppcc cccc
s = y size
S = x size
j = joint
g = group sprite is part of (if groups are enabled)
f = flip
p = priority
c = palette
0x04 ---- -aaa aaaa aaaa aaaa aaaa aaaa aaaa
a = ROM address of sprite data
0x08 ZZZZ ZZ-- zzzz zz-- xxxx xxxx xx-- ----
Z = horizontal zoom table
z = horizontal zoom subtable
x = x position
0x0C ZZZZ ZZ-- zzzz zz-- yyyy yyyy yy-- ----
Z = vertical zoom table
z = vertical zoom subtable
x = y position
**- End of Comments -*/
/* sprite ram start / end is not really fixed registers change it */
//printf ("addr %08x\n", (sprite_regs[0x14/4]));
UINT32 *source = spriteram_source;
UINT32 *finish = source + spriteram_size/4;
int group_x_offset[4];
int group_y_offset[4];
int group_enable;
int group_number;
int sprite_flip;
int sprite_x_scroll;
int sprite_y_scroll;
int disabled = sprite_regs[0x04/4] & 0x08; // RWR1
int xsize,ysize, size, xpos=0,ypos=0, pri=0, romoffset, colour=0, xflip,yflip, joint;
int sx,sy;
int endromoffs=0, gfxlen;
int grow;
UINT16 zoomx_m, zoomx_s, zoomy_m, zoomy_s;
if ((!disabled)){
group_enable = (sprite_regs[0x00/4] & 0x0040) >> 6; // RWR0
/* Sengekis uses global flip */
sprite_flip = (sprite_regs[0x04/4] & 0x03); // RWR1
sprite_y_scroll = ((sprite_regs[0x08/4] & 0x7fc0) >> 6); // RWR2
sprite_x_scroll = ((sprite_regs[0x10/4] & 0x7fc0) >> 6); // RWR4
if (sprite_y_scroll&0x100) sprite_y_scroll -= 0x200; // Signed
if (sprite_x_scroll&0x100) sprite_x_scroll -= 0x200; // Signed
group_x_offset[0] = (sprite_regs[0x18/4] & 0xffc0) >> 6; // RWR6
group_y_offset[0] = (sprite_regs[0x1c/4] & 0xffc0) >> 6; // RWR7
if (group_x_offset[0]&0x200) group_x_offset[0] -= 0x400; // Signed
if (group_y_offset[0]&0x200) group_y_offset[0] -= 0x400; // Signed
group_x_offset[1] = (sprite_regs[0x20/4] & 0xffc0) >> 6; // RWR8
group_y_offset[1] = (sprite_regs[0x24/4] & 0xffc0) >> 6; // RWR9
if (group_x_offset[1]&0x200) group_x_offset[1] -= 0x400; // Signed
if (group_y_offset[1]&0x200) group_y_offset[1] -= 0x400; // Signed
group_x_offset[2] = (sprite_regs[0x28/4] & 0xffc0) >> 6; // RWR10
group_y_offset[2] = (sprite_regs[0x2c/4] & 0xffc0) >> 6; // RWR11
if (group_x_offset[2]&0x200) group_x_offset[2] -= 0x400; // Signed
if (group_y_offset[2]&0x200) group_y_offset[2] -= 0x400; // Signed
group_x_offset[3] = (sprite_regs[0x30/4] & 0xffc0) >> 6; // RWR12
group_y_offset[3] = (sprite_regs[0x34/4] & 0xffc0) >> 6; // RWR13
if (group_x_offset[3]&0x200) group_x_offset[3] -= 0x400; // Signed
if (group_y_offset[3]&0x200) group_y_offset[3] -= 0x400; // Signed
// popmessage ("x %08x y %08x x2 %08x y2 %08x",sprite_x_scroll, sprite_y_scroll,group_x_offset[1], group_y_offset[1]);
// popmessage("%d %d %d %d A:%d B:%d", sprite_kludge_x, sprite_kludge_y, sprite_x_scroll, sprite_y_scroll, (skns_pal_regs[0x00/4] & 0x7000) >> 12, (skns_pal_regs[0x10/4] & 0x7000) >> 12);
// if (keyboard_pressed(KEYCODE_Q)) sprite_kludge_x++;
// if (keyboard_pressed(KEYCODE_W)) sprite_kludge_x--;
// if (keyboard_pressed(KEYCODE_E)) sprite_kludge_y++;
// if (keyboard_pressed(KEYCODE_D)) sprite_kludge_y--;
// Tilemap Pri/enables
// popmessage("A: %x %x B: %x %x", skns_v3_regs[0x10/4]>>3, skns_v3_regs[0x10/4]&7, skns_v3_regs[0x34/4]>>3, skns_v3_regs[0x34/4]&7);
/* Seems that sprites are consistently off by a fixed no. of pixels in different games
(Patterns emerge through Manufacturer/Date/Orientation) */
sprite_x_scroll += sprite_kludge_x;
sprite_y_scroll += sprite_kludge_y;
gfxlen = gfx_length;
while( source<finish )
{
xflip = (source[0] & 0x00000200) >> 9;
yflip = (source[0] & 0x00000100) >> 8;
ysize = (source[0] & 0x30000000) >> 28;
xsize = (source[0] & 0x03000000) >> 24;
xsize ++;
ysize ++;
xsize *= 16;
ysize *= 16;
size = xsize * ysize;
joint = (source[0] & 0x0000e000) >> 13;
if (!(joint & 1))
{
xpos = (source[2] & 0x0000ffc0) >> 6;
ypos = (source[3] & 0x0000ffc0) >> 6;
xpos += sprite_x_scroll; // Global offset
ypos += sprite_y_scroll;
if (group_enable)
{
group_number = (source[0] & 0x00001800) >> 11;
/* the group positioning doesn't seem to be working as i'd expect,
if I apply the x position the cursor on galpani4 ends up moving
from the correct position to too far right, also the y offset
seems to cause the position to be off by one in galpans2 even if
it fixes the position in galpani4?
even if I take into account the global sprite scroll registers
it isn't right
global offset kludged using game specific offset -pjp */
xpos += group_x_offset[group_number];
ypos += group_y_offset[group_number];
}
}
else
{
xpos += (source[2] & 0x0000ffc0) >> 6;
ypos += (source[3] & 0x0000ffc0) >> 6;
}
if (xpos > 0x1ff) xpos -= 0x400;
if (ypos > 0x1ff) ypos -= 0x400;
/* Local sprite offset (for taking flip into account and drawing offset) */
sx = xpos;
sy = ypos;
/* Global Sprite Flip (sengekis) */
if (sprite_flip&2)
{
xflip ^= 1;
sx = machine->primary_screen->visible_area().max_x+1 - sx;
}
if (sprite_flip&1)
{
yflip ^= 1;
sy = machine->primary_screen->visible_area().max_y+1 - sy;
}
/* Palette linking */
if (!(joint & 2))
{
colour = (source[0] & 0x0000003f) >> 0;
}
/* Priority and Tile linking */
if (!(joint & 4))
{
romoffset = (source[1] & 0x07ffffff) >> 0;
pri = (source[0] & 0x000000c0) >> 6;
} else {
romoffset = endromoffs;
}
grow = (source[0]>>23) & 1;
if (!grow)
{
zoomx_m = (source[2] >> 24)&0x00fc;
zoomx_s = (source[2] >> 16)&0x00fc;
zoomy_m = (source[3] >> 24)&0x00fc;
zoomy_s = (source[3] >> 16)&0x00fc;
}
else
{
// sengekis uses this on sprites which are shrinking as they head towards the ground
// it's also used on the input test of Gals Panic S2
//
// it appears to offer a higher precision 'shrink' mode (although I'm not entirely
// convinced this implementation is correct because we simply end up ignoring
// part of the data)
zoomx_m = 0;
zoomx_s = (source[2] >> 24)&0x00fc;
zoomy_m = 0;
zoomy_s = (source[3] >> 24)&0x00fc;
}
romoffset &= gfxlen-1;
endromoffs = skns_rle_decode ( machine, romoffset, size, gfx_source, gfx_length );
// in Cyvern
// train in tunnel pri = 0x00
// nothing? = 0x01
// players etc. pri = 0x02
// pickups etc. pri = 0x03
// PriTest
// if(!( (keyboard_pressed(KEYCODE_Q)&&(pri==0)) || (keyboard_pressed(KEYCODE_W)&&(pri==1)) || (keyboard_pressed(KEYCODE_E)&&(pri==2)) || (keyboard_pressed(KEYCODE_D)&&(pri==3)) ))
// if( !(keyboard_pressed(KEYCODE_Q) && ((source[0] & 0x00800000)>>24)) )
{
int NewColour = (colour<<8) | (pri << 14);
if(zoomx_m || zoomx_s || zoomy_m || zoomy_s)
{
blit_z[ (xflip<<1) | yflip ](bitmap, cliprect, decodebuffer, sx, sy, xsize, ysize, zoomx_m, zoomx_s, zoomy_m, zoomy_s, NewColour);
}
else
{
if (!xflip && !yflip) {
int xx,yy;
for (xx = 0; xx<xsize; xx++)
{
if ((sx+xx < (cliprect->max_x+1)) && (sx+xx >= cliprect->min_x))
{
for (yy = 0; yy<ysize; yy++)
{
if ((sy+yy < (cliprect->max_y+1)) && (sy+yy >= cliprect->min_y))
{
int pix;
pix = decodebuffer[xsize*yy+xx];
if (pix)
*BITMAP_ADDR16(bitmap, sy+yy, sx+xx) = pix+ NewColour; // change later
}
}
}
}
} else if (!xflip && yflip) {
int xx,yy;
sy -= ysize;
for (xx = 0; xx<xsize; xx++)
{
if ((sx+xx < (cliprect->max_x+1)) && (sx+xx >= cliprect->min_x))
{
for (yy = 0; yy<ysize; yy++)
{
if ((sy+(ysize-1-yy) < (cliprect->max_y+1)) && (sy+(ysize-1-yy) >= cliprect->min_y))
{
int pix;
pix = decodebuffer[xsize*yy+xx];
if (pix)
*BITMAP_ADDR16(bitmap, sy+(ysize-1-yy), sx+xx) = pix+ NewColour; // change later
}
}
}
}
} else if (xflip && !yflip) {
int xx,yy;
sx -= xsize;
for (xx = 0; xx<xsize; xx++)
{
if ( (sx+(xsize-1-xx) < (cliprect->max_x+1)) && (sx+(xsize-1-xx) >= cliprect->min_x))
{
for (yy = 0; yy<ysize; yy++)
{
if ((sy+yy < (cliprect->max_y+1)) && (sy+yy >= cliprect->min_y))
{
int pix;
pix = decodebuffer[xsize*yy+xx];
if (pix)
*BITMAP_ADDR16(bitmap, sy+yy, sx+(xsize-1-xx)) = pix+ NewColour; // change later
}
}
}
}
} else if (xflip && yflip) {
int xx,yy;
sx -= xsize;
sy -= ysize;
for (xx = 0; xx<xsize; xx++)
{
if ((sx+(xsize-1-xx) < (cliprect->max_x+1)) && (sx+(xsize-1-xx) >= cliprect->min_x))
{
for (yy = 0; yy<ysize; yy++)
{
if ((sy+(ysize-1-yy) < (cliprect->max_y+1)) && (sy+(ysize-1-yy) >= cliprect->min_y))
{
int pix;
pix = decodebuffer[xsize*yy+xx];
if (pix)
*BITMAP_ADDR16(bitmap, sy+(ysize-1-yy), sx+(xsize-1-xx)) = pix+ NewColour; // change later
}
}
}
}
}
}
}//End PriTest
source+=4;
}
}
}

36
src/mame/video/sknsspr.h Normal file
View File

@ -0,0 +1,36 @@
class sknsspr_device_config : public device_config
{
friend class sknsspr_device;
sknsspr_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
public:
static device_config *static_alloc_device_config(const machine_config &mconfig, const char *tag, const device_config *owner, UINT32 clock);
virtual device_t *alloc_device(running_machine &machine) const;
protected:
};
class sknsspr_device : public device_t
{
friend class sknsspr_device_config;
sknsspr_device(running_machine &_machine, const sknsspr_device_config &config);
public:
void skns_draw_sprites(running_machine *machine, bitmap_t *bitmap, const rectangle *cliprect, UINT32* spriteram_source, size_t spriteram_size, UINT8* gfx_source, size_t gfx_length, UINT32* sprite_regs);
void skns_sprite_kludge(int x, int y);
protected:
virtual void device_start();
virtual void device_reset();
const sknsspr_device_config &m_config;
private:
int sprite_kludge_x, sprite_kludge_y;
#define SUPRNOVA_DECODE_BUFFER_SIZE 0x2000
UINT8 decodebuffer[SUPRNOVA_DECODE_BUFFER_SIZE];
int skns_rle_decode ( running_machine *machine, int romoffset, int size, UINT8*gfx_source, size_t gfx_length );
};
const device_type sknsspr_ = sknsspr_device_config::static_alloc_device_config;

View File

@ -1,20 +1,7 @@
/* Super Kaneko Nova System video */
/*
TODO:
Implement double buffering for sprites?
We have to tell games which buffer to draw to? irrelevant to emulation
Remove all debug keys
*/
/*
Done:
Add global sprite flip
Tilemap flip flags were reversed
*/
#include "emu.h"
#include "video/sknsspr.h"
#include "includes/suprnova.h"
static bitmap_t *sprite_bitmap;
@ -109,13 +96,10 @@ static void suprnova_draw_roz(bitmap_t* bitmap, bitmap_t* bitmapflags, const rec
}
#define SUPRNOVA_DECODE_BUFFER_SIZE 0x2000
static UINT8 decodebuffer[SUPRNOVA_DECODE_BUFFER_SIZE];
static int depthA=0;
static int depthB=0;
static int sprite_kludge_x=0, sprite_kludge_y=0;
static int use_spc_bright, use_v3_bright; // makes sarukani rather dark, but should be default..
static UINT8 bright_spc_b=0x00, bright_spc_g=0x00, bright_spc_r=0x00;
@ -311,532 +295,6 @@ static void palette_update(running_machine *machine)
}
static int skns_rle_decode ( running_machine *machine, int romoffset, int size, UINT8*gfx_source, size_t gfx_length )
{
UINT8 *src = gfx_source;
size_t srcsize = gfx_length;
UINT8 *dst = decodebuffer;
int decodeoffset = 0;
while(size>0) {
UINT8 code = src[(romoffset++)%srcsize];
size -= (code & 0x7f) + 1;
if(code & 0x80) { /* (code & 0x7f) normal values will follow */
code &= 0x7f;
do {
dst[(decodeoffset++)%SUPRNOVA_DECODE_BUFFER_SIZE] = src[(romoffset++)%srcsize];
code--;
} while(code != 0xff);
} else { /* repeat next value (code & 0x7f) times */
UINT8 val = src[(romoffset++)%srcsize];
do {
dst[(decodeoffset++)%SUPRNOVA_DECODE_BUFFER_SIZE] = val;
code--;
} while(code != 0xff);
}
}
return &src[romoffset%srcsize]-gfx_source;
}
void skns_sprite_kludge(int x, int y)
{
sprite_kludge_x = x;
sprite_kludge_y = y;
}
/* Zooming blitter, zoom is by way of both source and destination offsets */
/* We are working in .6 fixed point if you hadn't guessed */
#define z_decls(step) \
UINT16 zxs = 0x40-(zx_m>>2); \
UINT16 zxd = 0x40-(zx_s>>2); \
UINT16 zys = 0x40-(zy_m>>2); \
UINT16 zyd = 0x40-(zy_s>>2); \
int xs, ys, xd, yd, old, old2; \
int step_spr = step; \
int bxs = 0, bys = 0; \
rectangle clip; \
clip.min_x = cliprect->min_x<<6; \
clip.max_x = (cliprect->max_x+1)<<6; \
clip.min_y = cliprect->min_y<<6; \
clip.max_y = (cliprect->max_y+1)<<6; \
sx <<= 6; \
sy <<= 6; \
x <<= 6; \
y <<= 6;
#define z_clamp_x_min() \
if(x < clip.min_x) { \
do { \
bxs += zxs; \
x += zxd; \
} while(x < clip.min_x); \
}
#define z_clamp_x_max() \
if(x > clip.max_x) { \
do { \
bxs += zxs; \
x -= zxd; \
} while(x > clip.max_x); \
}
#define z_clamp_y_min() \
if(y < clip.min_y) { \
do { \
bys += zys; \
y += zyd; \
} while(y < clip.min_y); \
src += (bys>>6)*step_spr; \
}
#define z_clamp_y_max() \
if(y > clip.max_y) { \
do { \
bys += zys; \
y -= zyd; \
} while(y > clip.max_y); \
src += (bys>>6)*step_spr; \
}
#define z_loop_x() \
xs = bxs; \
xd = x; \
while(xs < sx && xd <= clip.max_x)
#define z_loop_x_flip() \
xs = bxs; \
xd = x; \
while(xs < sx && xd >= clip.min_x)
#define z_loop_y() \
ys = bys; \
yd = y; \
while(ys < sy && yd <= clip.max_y)
#define z_loop_y_flip() \
ys = bys; \
yd = y; \
while(ys < sy && yd >= clip.min_y)
#define z_draw_pixel() \
UINT8 val = src[xs >> 6]; \
if(val) \
*BITMAP_ADDR16(bitmap, yd>>6, xd>>6) = val + colour;
#define z_x_dst(op) \
old = xd; \
do { \
xs += zxs; \
xd op zxd; \
} while(!((xd^old) & ~0x3f));
#define z_y_dst(op) \
old = yd; \
old2 = ys; \
do { \
ys += zys; \
yd op zyd; \
} while(!((yd^old) & ~0x3f)); \
while((ys^old2) & ~0x3f) { \
src += step_spr; \
old2 += 0x40; \
}
static void blit_nf_z(bitmap_t *bitmap, const rectangle *cliprect, const UINT8 *src, int x, int y, int sx, int sy, UINT16 zx_m, UINT16 zx_s, UINT16 zy_m, UINT16 zy_s, int colour)
{
z_decls(sx);
z_clamp_x_min();
z_clamp_y_min();
z_loop_y() {
z_loop_x() {
z_draw_pixel();
z_x_dst(+=);
}
z_y_dst(+=);
}
}
static void blit_fy_z(bitmap_t *bitmap, const rectangle *cliprect, const UINT8 *src, int x, int y, int sx, int sy, UINT16 zx_m, UINT16 zx_s, UINT16 zy_m, UINT16 zy_s, int colour)
{
z_decls(sx);
z_clamp_x_min();
z_clamp_y_max();
z_loop_y_flip() {
z_loop_x() {
z_draw_pixel();
z_x_dst(+=);
}
z_y_dst(-=);
}
}
static void blit_fx_z(bitmap_t *bitmap, const rectangle *cliprect, const UINT8 *src, int x, int y, int sx, int sy, UINT16 zx_m, UINT16 zx_s, UINT16 zy_m, UINT16 zy_s, int colour)
{
z_decls(sx);
z_clamp_x_max();
z_clamp_y_min();
z_loop_y() {
z_loop_x_flip() {
z_draw_pixel();
z_x_dst(-=);
}
z_y_dst(+=);
}
}
static void blit_fxy_z(bitmap_t *bitmap, const rectangle *cliprect, const UINT8 *src, int x, int y, int sx, int sy, UINT16 zx_m, UINT16 zx_s, UINT16 zy_m, UINT16 zy_s, int colour)
{
z_decls(sx);
z_clamp_x_max();
z_clamp_y_max();
z_loop_y_flip() {
z_loop_x_flip() {
z_draw_pixel();
z_x_dst(-=);
}
z_y_dst(-=);
}
}
static void (*const blit_z[4])(bitmap_t *bitmap, const rectangle *cliprect, const UINT8 *src, int x, int y, int sx, int sy, UINT16 zx_m, UINT16 zx_s, UINT16 zy_m, UINT16 zy_s, int colour) = {
blit_nf_z,
blit_fy_z,
blit_fx_z,
blit_fxy_z,
};
void skns_draw_sprites(running_machine *machine, bitmap_t *bitmap, const rectangle *cliprect, UINT32* spriteram_source, size_t spriteram_size, UINT8* gfx_source, size_t gfx_length, UINT32* sprite_regs)
{
/*- SPR RAM Format -**
16 bytes per sprite
0x00 --ss --SS z--- ---- jjjg g-ff ppcc cccc
s = y size
S = x size
j = joint
g = group sprite is part of (if groups are enabled)
f = flip
p = priority
c = palette
0x04 ---- -aaa aaaa aaaa aaaa aaaa aaaa aaaa
a = ROM address of sprite data
0x08 ZZZZ ZZ-- zzzz zz-- xxxx xxxx xx-- ----
Z = horizontal zoom table
z = horizontal zoom subtable
x = x position
0x0C ZZZZ ZZ-- zzzz zz-- yyyy yyyy yy-- ----
Z = vertical zoom table
z = vertical zoom subtable
x = y position
**- End of Comments -*/
/* sprite ram start / end is not really fixed registers change it */
//printf ("addr %08x\n", (sprite_regs[0x14/4]));
UINT32 *source = spriteram_source;
UINT32 *finish = source + spriteram_size/4;
int group_x_offset[4];
int group_y_offset[4];
int group_enable;
int group_number;
int sprite_flip;
int sprite_x_scroll;
int sprite_y_scroll;
int disabled = sprite_regs[0x04/4] & 0x08; // RWR1
int xsize,ysize, size, xpos=0,ypos=0, pri=0, romoffset, colour=0, xflip,yflip, joint;
int sx,sy;
int endromoffs=0, gfxlen;
int grow;
UINT16 zoomx_m, zoomx_s, zoomy_m, zoomy_s;
if ((!disabled) && suprnova_alt_enable_sprites){
group_enable = (sprite_regs[0x00/4] & 0x0040) >> 6; // RWR0
/* Sengekis uses global flip */
sprite_flip = (sprite_regs[0x04/4] & 0x03); // RWR1
sprite_y_scroll = ((sprite_regs[0x08/4] & 0x7fc0) >> 6); // RWR2
sprite_x_scroll = ((sprite_regs[0x10/4] & 0x7fc0) >> 6); // RWR4
if (sprite_y_scroll&0x100) sprite_y_scroll -= 0x200; // Signed
if (sprite_x_scroll&0x100) sprite_x_scroll -= 0x200; // Signed
group_x_offset[0] = (sprite_regs[0x18/4] & 0xffc0) >> 6; // RWR6
group_y_offset[0] = (sprite_regs[0x1c/4] & 0xffc0) >> 6; // RWR7
if (group_x_offset[0]&0x200) group_x_offset[0] -= 0x400; // Signed
if (group_y_offset[0]&0x200) group_y_offset[0] -= 0x400; // Signed
group_x_offset[1] = (sprite_regs[0x20/4] & 0xffc0) >> 6; // RWR8
group_y_offset[1] = (sprite_regs[0x24/4] & 0xffc0) >> 6; // RWR9
if (group_x_offset[1]&0x200) group_x_offset[1] -= 0x400; // Signed
if (group_y_offset[1]&0x200) group_y_offset[1] -= 0x400; // Signed
group_x_offset[2] = (sprite_regs[0x28/4] & 0xffc0) >> 6; // RWR10
group_y_offset[2] = (sprite_regs[0x2c/4] & 0xffc0) >> 6; // RWR11
if (group_x_offset[2]&0x200) group_x_offset[2] -= 0x400; // Signed
if (group_y_offset[2]&0x200) group_y_offset[2] -= 0x400; // Signed
group_x_offset[3] = (sprite_regs[0x30/4] & 0xffc0) >> 6; // RWR12
group_y_offset[3] = (sprite_regs[0x34/4] & 0xffc0) >> 6; // RWR13
if (group_x_offset[3]&0x200) group_x_offset[3] -= 0x400; // Signed
if (group_y_offset[3]&0x200) group_y_offset[3] -= 0x400; // Signed
// popmessage ("x %08x y %08x x2 %08x y2 %08x",sprite_x_scroll, sprite_y_scroll,group_x_offset[1], group_y_offset[1]);
// popmessage("%d %d %d %d A:%d B:%d", sprite_kludge_x, sprite_kludge_y, sprite_x_scroll, sprite_y_scroll, (skns_pal_regs[0x00/4] & 0x7000) >> 12, (skns_pal_regs[0x10/4] & 0x7000) >> 12);
// if (keyboard_pressed(KEYCODE_Q)) sprite_kludge_x++;
// if (keyboard_pressed(KEYCODE_W)) sprite_kludge_x--;
// if (keyboard_pressed(KEYCODE_E)) sprite_kludge_y++;
// if (keyboard_pressed(KEYCODE_D)) sprite_kludge_y--;
// Tilemap Pri/enables
// popmessage("A: %x %x B: %x %x", skns_v3_regs[0x10/4]>>3, skns_v3_regs[0x10/4]&7, skns_v3_regs[0x34/4]>>3, skns_v3_regs[0x34/4]&7);
/* Seems that sprites are consistently off by a fixed no. of pixels in different games
(Patterns emerge through Manufacturer/Date/Orientation) */
sprite_x_scroll += sprite_kludge_x;
sprite_y_scroll += sprite_kludge_y;
gfxlen = gfx_length;
while( source<finish )
{
xflip = (source[0] & 0x00000200) >> 9;
yflip = (source[0] & 0x00000100) >> 8;
ysize = (source[0] & 0x30000000) >> 28;
xsize = (source[0] & 0x03000000) >> 24;
xsize ++;
ysize ++;
xsize *= 16;
ysize *= 16;
size = xsize * ysize;
joint = (source[0] & 0x0000e000) >> 13;
if (!(joint & 1))
{
xpos = (source[2] & 0x0000ffc0) >> 6;
ypos = (source[3] & 0x0000ffc0) >> 6;
xpos += sprite_x_scroll; // Global offset
ypos += sprite_y_scroll;
if (group_enable)
{
group_number = (source[0] & 0x00001800) >> 11;
/* the group positioning doesn't seem to be working as i'd expect,
if I apply the x position the cursor on galpani4 ends up moving
from the correct position to too far right, also the y offset
seems to cause the position to be off by one in galpans2 even if
it fixes the position in galpani4?
even if I take into account the global sprite scroll registers
it isn't right
global offset kludged using game specific offset -pjp */
xpos += group_x_offset[group_number];
ypos += group_y_offset[group_number];
}
}
else
{
xpos += (source[2] & 0x0000ffc0) >> 6;
ypos += (source[3] & 0x0000ffc0) >> 6;
}
if (xpos > 0x1ff) xpos -= 0x400;
if (ypos > 0x1ff) ypos -= 0x400;
/* Local sprite offset (for taking flip into account and drawing offset) */
sx = xpos;
sy = ypos;
/* Global Sprite Flip (sengekis) */
if (sprite_flip&2)
{
xflip ^= 1;
sx = machine->primary_screen->visible_area().max_x+1 - sx;
}
if (sprite_flip&1)
{
yflip ^= 1;
sy = machine->primary_screen->visible_area().max_y+1 - sy;
}
/* Palette linking */
if (!(joint & 2))
{
colour = (source[0] & 0x0000003f) >> 0;
}
/* Priority and Tile linking */
if (!(joint & 4))
{
romoffset = (source[1] & 0x07ffffff) >> 0;
pri = (source[0] & 0x000000c0) >> 6;
} else {
romoffset = endromoffs;
}
grow = (source[0]>>23) & 1;
if (!grow)
{
zoomx_m = (source[2] >> 24)&0x00fc;
zoomx_s = (source[2] >> 16)&0x00fc;
zoomy_m = (source[3] >> 24)&0x00fc;
zoomy_s = (source[3] >> 16)&0x00fc;
}
else
{
// sengekis uses this on sprites which are shrinking as they head towards the ground
// it's also used on the input test of Gals Panic S2
//
// it appears to offer a higher precision 'shrink' mode (although I'm not entirely
// convinced this implementation is correct because we simply end up ignoring
// part of the data)
zoomx_m = 0;
zoomx_s = (source[2] >> 24)&0x00fc;
zoomy_m = 0;
zoomy_s = (source[3] >> 24)&0x00fc;
}
romoffset &= gfxlen-1;
endromoffs = skns_rle_decode ( machine, romoffset, size, gfx_source, gfx_length );
// in Cyvern
// train in tunnel pri = 0x00
// nothing? = 0x01
// players etc. pri = 0x02
// pickups etc. pri = 0x03
// PriTest
// if(!( (keyboard_pressed(KEYCODE_Q)&&(pri==0)) || (keyboard_pressed(KEYCODE_W)&&(pri==1)) || (keyboard_pressed(KEYCODE_E)&&(pri==2)) || (keyboard_pressed(KEYCODE_D)&&(pri==3)) ))
// if( !(keyboard_pressed(KEYCODE_Q) && ((source[0] & 0x00800000)>>24)) )
{
int NewColour = (colour<<8) | (pri << 14);
if(zoomx_m || zoomx_s || zoomy_m || zoomy_s)
{
blit_z[ (xflip<<1) | yflip ](bitmap, cliprect, decodebuffer, sx, sy, xsize, ysize, zoomx_m, zoomx_s, zoomy_m, zoomy_s, NewColour);
}
else
{
if (!xflip && !yflip) {
int xx,yy;
for (xx = 0; xx<xsize; xx++)
{
if ((sx+xx < (cliprect->max_x+1)) && (sx+xx >= cliprect->min_x))
{
for (yy = 0; yy<ysize; yy++)
{
if ((sy+yy < (cliprect->max_y+1)) && (sy+yy >= cliprect->min_y))
{
int pix;
pix = decodebuffer[xsize*yy+xx];
if (pix)
*BITMAP_ADDR16(bitmap, sy+yy, sx+xx) = pix+ NewColour; // change later
}
}
}
}
} else if (!xflip && yflip) {
int xx,yy;
sy -= ysize;
for (xx = 0; xx<xsize; xx++)
{
if ((sx+xx < (cliprect->max_x+1)) && (sx+xx >= cliprect->min_x))
{
for (yy = 0; yy<ysize; yy++)
{
if ((sy+(ysize-1-yy) < (cliprect->max_y+1)) && (sy+(ysize-1-yy) >= cliprect->min_y))
{
int pix;
pix = decodebuffer[xsize*yy+xx];
if (pix)
*BITMAP_ADDR16(bitmap, sy+(ysize-1-yy), sx+xx) = pix+ NewColour; // change later
}
}
}
}
} else if (xflip && !yflip) {
int xx,yy;
sx -= xsize;
for (xx = 0; xx<xsize; xx++)
{
if ( (sx+(xsize-1-xx) < (cliprect->max_x+1)) && (sx+(xsize-1-xx) >= cliprect->min_x))
{
for (yy = 0; yy<ysize; yy++)
{
if ((sy+yy < (cliprect->max_y+1)) && (sy+yy >= cliprect->min_y))
{
int pix;
pix = decodebuffer[xsize*yy+xx];
if (pix)
*BITMAP_ADDR16(bitmap, sy+yy, sx+(xsize-1-xx)) = pix+ NewColour; // change later
}
}
}
}
} else if (xflip && yflip) {
int xx,yy;
sx -= xsize;
sy -= ysize;
for (xx = 0; xx<xsize; xx++)
{
if ((sx+(xsize-1-xx) < (cliprect->max_x+1)) && (sx+(xsize-1-xx) >= cliprect->min_x))
{
for (yy = 0; yy<ysize; yy++)
{
if ((sy+(ysize-1-yy) < (cliprect->max_y+1)) && (sy+(ysize-1-yy) >= cliprect->min_y))
{
int pix;
pix = decodebuffer[xsize*yy+xx];
if (pix)
*BITMAP_ADDR16(bitmap, sy+(ysize-1-yy), sx+(xsize-1-xx)) = pix+ NewColour; // change later
}
}
}
}
}
}
}//End PriTest
source+=4;
}
}
}
static tilemap_t *skns_tilemap_A;
static tilemap_t *skns_tilemap_B;
@ -916,6 +374,10 @@ WRITE32_HANDLER ( skns_v3_regs_w )
VIDEO_START(skns)
{
skns_state *state = machine->driver_data<skns_state>();
state->spritegen = machine->device<sknsspr_device>("spritegen");
skns_tilemap_A = tilemap_create(machine, get_tilemap_A_tile_info,tilemap_scan_rows,16,16,64, 64);
tilemap_set_transparent_pen(skns_tilemap_A,0);
@ -1009,6 +471,8 @@ static void supernova_draw_b( bitmap_t *bitmap, bitmap_t* bitmap_flags, const re
SCREEN_UPDATE(skns)
{
skns_state *state = screen->machine->driver_data<skns_state>();
palette_update(screen->machine);
bitmap_fill(bitmap, cliprect, get_black_pen(screen->machine));
@ -1181,7 +645,9 @@ SCREEN_UPDATE(skns)
}
bitmap_fill(sprite_bitmap, cliprect, 0x0000);
skns_draw_sprites(screen->machine, sprite_bitmap, cliprect, screen->machine->generic.spriteram.u32, screen->machine->generic.spriteram_size, screen->machine->region("gfx1")->base(), screen->machine->region ("gfx1")->bytes(), skns_spc_regs );
if (suprnova_alt_enable_sprites)
state->spritegen->skns_draw_sprites(screen->machine, sprite_bitmap, cliprect, screen->machine->generic.spriteram.u32, screen->machine->generic.spriteram_size, screen->machine->region("gfx1")->base(), screen->machine->region ("gfx1")->bytes(), skns_spc_regs );
return 0;