mirror of
https://github.com/holub/mame
synced 2025-06-28 07:04:35 +03:00
1942 lines
63 KiB
C
1942 lines
63 KiB
C
/***************************************************************************
|
|
|
|
|
|
Funtech Super A'Can
|
|
-------------------
|
|
|
|
Preliminary driver by Angelo Salese
|
|
Improvements by Harmony
|
|
|
|
|
|
*******************************************************************************
|
|
|
|
INFO:
|
|
|
|
The system unit contains a reset button.
|
|
|
|
Controllers:
|
|
- 4 directional buttons
|
|
- A, B, X, Y, buttons
|
|
- Start, select buttons
|
|
- L, R shoulder buttons
|
|
|
|
STATUS:
|
|
|
|
The driver is begging for a re-write or at least a split into video/supracan.c. It will happen eventually.
|
|
|
|
Sound CPU comms and sound chip are completely unknown.
|
|
|
|
There are 6 interrupt sources on the 6502 side, all of which use the IRQ line.
|
|
The register at 0x411 is bitmapped to indicate what source(s) are active.
|
|
In priority order from most to least important, they are:
|
|
|
|
411 value How acked Notes
|
|
0x40 read reg 0x16 of sound chip likely timer. snd regs 0x16/0x17 are time constant, write 0 to reg 0x9f to start
|
|
0x04 read at 0x405 latch 1? 0xcd is magic value
|
|
0x08 read at 0x404 latch 2? 0xcd is magic value
|
|
0x10 read at 0x409 unknown, dispatched but not used in startup 6502 code
|
|
0x20 read at 0x40a possible periodic like vblank?
|
|
0x80 read reg 0x14 of sound chip depends on reg 0x14 of sound chip & 0x40: if not set writes 0x8f to reg 0x14,
|
|
otherwise writes 0x4f to reg 0x14 and performs additional processing
|
|
|
|
Known unemulated graphical effects and issues:
|
|
- All: Sprite sizing is still imperfect.
|
|
- All: Sprites need to be converted to use scanline rendering for proper clipping.
|
|
- All: Improperly-emulated 1bpp ROZ mode, used by the Super A'Can BIOS logo.
|
|
- All: Unimplemented ROZ scaling tables, used by the Super A'Can BIOS logo and Speedy Dragon intro, among others.
|
|
- All: Priorities are largely unknown.
|
|
- C.U.G.: Gameplay backgrounds are broken.
|
|
- Sango Fighter: Possible missing masking on the upper edges of the screen during gameplay.
|
|
- Sango Fighter: Raster effects off by 1 line
|
|
- Sango Fighter: Specifies tiles out of range of video ram??
|
|
- Speedy Dragon: Backgrounds are broken (wrong tile bank/region).
|
|
- Super Taiwanese Baseball League: Does not boot, uses an unemulated DMA type
|
|
- Super Taiwanese Baseball League: Missing window effect applied on tilemaps?
|
|
- The Son of Evil: Many graphical issues.
|
|
- Visible area, looks like it should be 224 pixels high at most, most games need 8 off the top and 8 off the bottom (or a global scroll)
|
|
Sango looks like it needs 16 off the bottom instead
|
|
Visible area is almost certainly 224 as Son of Evil has an explicit check in the vblank handler
|
|
|
|
- All: are ALL the layers ROZ capable??
|
|
|
|
DEBUG TRICKS:
|
|
|
|
baseball game debug trick:
|
|
wpset e90020,1f,w
|
|
do pc=5ac40
|
|
...
|
|
do pc=5acd4
|
|
wpclear
|
|
bp 0269E4
|
|
[ff7be4] <- 0x269ec
|
|
bpclear
|
|
|
|
***************************************************************************/
|
|
|
|
#include "emu.h"
|
|
#include "cpu/m68000/m68000.h"
|
|
#include "cpu/m6502/m6502.h"
|
|
#include "imagedev/cartslot.h"
|
|
//#include "debugger.h"
|
|
|
|
#define SOUNDCPU_BOOT_HACK (1)
|
|
|
|
#define DRAW_DEBUG_ROZ (0)
|
|
|
|
#define DRAW_DEBUG_UNK_SPRITE (0)
|
|
|
|
#define DEBUG_PRIORITY (0)
|
|
#define DEBUG_PRIORITY_INDEX (0) // 0-3
|
|
|
|
#define VERBOSE_LEVEL (3)
|
|
|
|
#define ENABLE_VERBOSE_LOG (1)
|
|
|
|
struct acan_dma_regs_t
|
|
{
|
|
UINT32 source[2];
|
|
UINT32 dest[2];
|
|
UINT16 count[2];
|
|
UINT16 control[2];
|
|
};
|
|
|
|
struct acan_sprdma_regs_t
|
|
{
|
|
UINT32 src;
|
|
UINT16 src_inc;
|
|
UINT32 dst;
|
|
UINT16 dst_inc;
|
|
UINT16 count;
|
|
UINT16 control;
|
|
};
|
|
|
|
class supracan_state : public driver_device
|
|
{
|
|
public:
|
|
supracan_state(const machine_config &mconfig, device_type type, const char *tag)
|
|
: driver_device(mconfig, type, tag),
|
|
m_maincpu(*this, "maincpu"),
|
|
m_soundram(*this, "soundram")
|
|
{
|
|
m_m6502_reset = 0;
|
|
}
|
|
|
|
required_device<cpu_device> m_maincpu;
|
|
DECLARE_READ16_MEMBER(supracan_68k_soundram_r);
|
|
DECLARE_WRITE16_MEMBER(supracan_68k_soundram_w);
|
|
DECLARE_READ8_MEMBER(supracan_6502_soundmem_r);
|
|
DECLARE_WRITE8_MEMBER(supracan_6502_soundmem_w);
|
|
DECLARE_WRITE16_MEMBER(supracan_dma_w);
|
|
DECLARE_READ16_MEMBER(supracan_sound_r);
|
|
DECLARE_WRITE16_MEMBER(supracan_sound_w);
|
|
DECLARE_READ16_MEMBER(supracan_video_r);
|
|
DECLARE_WRITE16_MEMBER(supracan_video_w);
|
|
DECLARE_READ16_MEMBER(supracan_vram_r);
|
|
DECLARE_WRITE16_MEMBER(supracan_vram_w);
|
|
DECLARE_WRITE16_MEMBER(paletteram_w);
|
|
acan_dma_regs_t m_acan_dma_regs;
|
|
acan_sprdma_regs_t m_acan_sprdma_regs;
|
|
|
|
UINT16 m_m6502_reset;
|
|
required_shared_ptr<UINT8> m_soundram;
|
|
UINT8 m_soundlatch;
|
|
UINT8 m_soundcpu_irq_src;
|
|
UINT8 m_sound_irq_enable_reg;
|
|
UINT8 m_sound_irq_source_reg;
|
|
UINT8 m_sound_cpu_68k_irq_reg;
|
|
|
|
emu_timer *m_video_timer;
|
|
emu_timer *m_hbl_timer;
|
|
emu_timer *m_line_on_timer;
|
|
emu_timer *m_line_off_timer;
|
|
UINT16 *m_vram;
|
|
UINT16 *m_vram_swapped;
|
|
UINT8 *m_vram_addr_swapped;
|
|
|
|
UINT16 *m_pram;
|
|
|
|
UINT16 m_sprite_count;
|
|
UINT32 m_sprite_base_addr;
|
|
UINT8 m_sprite_flags;
|
|
|
|
UINT32 m_tilemap_base_addr[3];
|
|
int m_tilemap_scrollx[3];
|
|
int m_tilemap_scrolly[3];
|
|
UINT16 m_video_flags;
|
|
UINT16 m_tilemap_flags[3];
|
|
UINT16 m_tilemap_mode[3];
|
|
UINT16 m_irq_mask;
|
|
UINT16 m_hbl_mask;
|
|
|
|
UINT32 m_roz_base_addr;
|
|
UINT16 m_roz_mode;
|
|
UINT32 m_roz_scrollx;
|
|
UINT32 m_roz_scrolly;
|
|
UINT16 m_roz_tile_bank;
|
|
UINT32 m_roz_unk_base0;
|
|
UINT32 m_roz_unk_base1;
|
|
UINT32 m_roz_unk_base2;
|
|
UINT16 m_roz_coeffa;
|
|
UINT16 m_roz_coeffb;
|
|
UINT16 m_roz_coeffc;
|
|
UINT16 m_roz_coeffd;
|
|
INT32 m_roz_changed;
|
|
INT32 m_roz_cx;
|
|
INT32 m_roz_cy;
|
|
UINT16 m_unk_1d0;
|
|
|
|
UINT16 m_video_regs[256];
|
|
|
|
bool m_hack_68k_to_6502_access;
|
|
|
|
tilemap_t *m_tilemap_sizes[4][4];
|
|
bitmap_ind16 m_sprite_final_bitmap;
|
|
void write_swapped_byte(int offset, UINT8 byte);
|
|
TILE_GET_INFO_MEMBER(get_supracan_tilemap0_tile_info);
|
|
TILE_GET_INFO_MEMBER(get_supracan_tilemap1_tile_info);
|
|
TILE_GET_INFO_MEMBER(get_supracan_tilemap2_tile_info);
|
|
TILE_GET_INFO_MEMBER(get_supracan_roz_tile_info);
|
|
virtual void machine_start();
|
|
virtual void machine_reset();
|
|
virtual void video_start();
|
|
virtual void palette_init();
|
|
UINT32 screen_update_supracan(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
|
|
INTERRUPT_GEN_MEMBER(supracan_irq);
|
|
INTERRUPT_GEN_MEMBER(supracan_sound_irq);
|
|
};
|
|
|
|
|
|
|
|
#if ENABLE_VERBOSE_LOG
|
|
INLINE void verboselog(const char *tag, running_machine &machine, int n_level, const char *s_fmt, ...)
|
|
{
|
|
if( VERBOSE_LEVEL >= n_level )
|
|
{
|
|
va_list v;
|
|
char buf[ 32768 ];
|
|
va_start( v, s_fmt );
|
|
vsprintf( buf, s_fmt, v );
|
|
va_end( v );
|
|
logerror( "%06x: %s: %s", machine.device(tag)->safe_pc(), tag, buf );
|
|
}
|
|
}
|
|
|
|
#else
|
|
#define verboselog(w,x,y,z,...)
|
|
#endif
|
|
|
|
static int supracan_tilemap_get_region(running_machine &machine, int layer)
|
|
{
|
|
supracan_state *state = machine.driver_data<supracan_state>();
|
|
|
|
// HACK!!!
|
|
if (layer==2)
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
|
|
if (layer==3)
|
|
{
|
|
// roz layer
|
|
|
|
int gfx_mode = (state->m_roz_mode & 3);
|
|
|
|
switch(gfx_mode)
|
|
{
|
|
case 0: return 4;
|
|
case 1: return 2;
|
|
case 2: return 1;
|
|
case 3: return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
// normal layers
|
|
int gfx_mode = (state->m_tilemap_mode[layer] & 0x7000) >> 12;
|
|
|
|
switch(gfx_mode)
|
|
{
|
|
case 7: return 2;
|
|
case 4: return 1;
|
|
case 2: return 1;
|
|
case 0: return 1;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
}
|
|
|
|
static void supracan_tilemap_get_info_common(running_machine &machine, int layer, tile_data &tileinfo, int count)
|
|
{
|
|
supracan_state *state = machine.driver_data<supracan_state>();
|
|
|
|
UINT16* supracan_vram = state->m_vram;
|
|
|
|
UINT32 base = (state->m_tilemap_base_addr[layer]);
|
|
int gfx_mode = (state->m_tilemap_mode[layer] & 0x7000) >> 12;
|
|
int region = supracan_tilemap_get_region(machine, layer);
|
|
|
|
count += base;
|
|
|
|
UINT16 tile_bank = 0;
|
|
UINT16 palette_bank = 0;
|
|
switch(gfx_mode)
|
|
{
|
|
case 7:
|
|
tile_bank = 0x1c00;
|
|
palette_bank = 0x00;
|
|
break;
|
|
|
|
case 4:
|
|
tile_bank = 0x800;
|
|
palette_bank = 0x00;
|
|
break;
|
|
|
|
case 2:
|
|
tile_bank = 0x400;
|
|
palette_bank = 0x00;
|
|
break;
|
|
|
|
case 0:
|
|
tile_bank = 0;
|
|
palette_bank = 0x00;
|
|
break;
|
|
|
|
default:
|
|
verboselog("maincpu", machine, 0, "Unsupported tilemap mode: %d\n", (state->m_tilemap_mode[layer] & 0x7000) >> 12);
|
|
break;
|
|
}
|
|
|
|
|
|
if(layer == 2)
|
|
{
|
|
tile_bank = 0x1000;
|
|
}
|
|
|
|
int tile = (supracan_vram[count] & 0x03ff) + tile_bank;
|
|
int flipxy = (supracan_vram[count] & 0x0c00)>>10;
|
|
int palette = ((supracan_vram[count] & 0xf000) >> 12) + palette_bank;
|
|
|
|
SET_TILE_INFO(region, tile, palette, TILE_FLIPXY(flipxy));
|
|
}
|
|
|
|
// I wonder how different this really is.. my guess, not at all.
|
|
static void supracan_tilemap_get_info_roz(running_machine &machine, int layer, tile_data &tileinfo, int count)
|
|
{
|
|
supracan_state *state = machine.driver_data<supracan_state>();
|
|
|
|
UINT16* supracan_vram = state->m_vram;
|
|
|
|
UINT32 base = state->m_roz_base_addr;
|
|
|
|
|
|
int region = 1;
|
|
UINT16 tile_bank = 0;
|
|
UINT16 palette_bank = 0;
|
|
|
|
region = supracan_tilemap_get_region(machine, layer);
|
|
|
|
switch(state->m_roz_mode & 3) //FIXME: fix gfx bpp order
|
|
{
|
|
case 0:
|
|
// hack: case for startup logo
|
|
// this isn't understood properly, it's rendering a single 64x64 tile, which for convenience we've rearranged and decoded as 8x8 for the tilemaps
|
|
{
|
|
int tile = 0x880 + ((count & 7)*2);
|
|
// tile += (count & 0x070) >> 2;
|
|
|
|
if (count & 0x20) tile ^= 1;
|
|
tile |= (count & 0xc0)>>2;
|
|
|
|
SET_TILE_INFO(region, tile, 0, 0);
|
|
return;
|
|
}
|
|
|
|
|
|
case 1:
|
|
tile_bank = (state->m_roz_tile_bank & 0xf000) >> 3;
|
|
break;
|
|
|
|
case 2:
|
|
tile_bank = (state->m_roz_tile_bank & 0xf000) >> 3;
|
|
break;
|
|
|
|
case 3:
|
|
tile_bank = (state->m_roz_tile_bank & 0xf000) >> 3;
|
|
break;
|
|
}
|
|
|
|
count += base;
|
|
|
|
int tile = (supracan_vram[count] & 0x03ff) + tile_bank;
|
|
int flipxy = (supracan_vram[count] & 0x0c00)>>10;
|
|
int palette = ((supracan_vram[count] & 0xf000) >> 12) + palette_bank;
|
|
|
|
SET_TILE_INFO(region, tile, palette, TILE_FLIPXY(flipxy));
|
|
}
|
|
|
|
|
|
|
|
TILE_GET_INFO_MEMBER(supracan_state::get_supracan_tilemap0_tile_info)
|
|
{
|
|
|
|
supracan_tilemap_get_info_common(machine(), 0, tileinfo, tile_index);
|
|
}
|
|
|
|
TILE_GET_INFO_MEMBER(supracan_state::get_supracan_tilemap1_tile_info)
|
|
{
|
|
supracan_tilemap_get_info_common(machine(), 1, tileinfo, tile_index);
|
|
}
|
|
|
|
TILE_GET_INFO_MEMBER(supracan_state::get_supracan_tilemap2_tile_info)
|
|
{
|
|
|
|
supracan_tilemap_get_info_common(machine(), 2, tileinfo, tile_index);
|
|
}
|
|
|
|
TILE_GET_INFO_MEMBER(supracan_state::get_supracan_roz_tile_info)
|
|
{
|
|
|
|
supracan_tilemap_get_info_roz(machine(), 3, tileinfo, tile_index);
|
|
}
|
|
|
|
|
|
void supracan_state::video_start()
|
|
{
|
|
m_sprite_final_bitmap.allocate(1024, 1024, BITMAP_FORMAT_IND16);
|
|
|
|
m_vram = (UINT16*)(*machine().root_device().memregion("ram_gfx"));
|
|
m_vram_swapped = (UINT16*)(*machine().root_device().memregion("ram_gfx2"));
|
|
m_vram_addr_swapped = (UINT8*)(*memregion("ram_gfx3")); // hack for 1bpp layer at startup
|
|
|
|
m_tilemap_sizes[0][0] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(supracan_state::get_supracan_tilemap0_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
|
|
m_tilemap_sizes[0][1] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(supracan_state::get_supracan_tilemap0_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
|
|
m_tilemap_sizes[0][2] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(supracan_state::get_supracan_tilemap0_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 128, 32);
|
|
m_tilemap_sizes[0][3] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(supracan_state::get_supracan_tilemap0_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 64, 64);
|
|
|
|
m_tilemap_sizes[1][0] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(supracan_state::get_supracan_tilemap1_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
|
|
m_tilemap_sizes[1][1] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(supracan_state::get_supracan_tilemap1_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
|
|
m_tilemap_sizes[1][2] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(supracan_state::get_supracan_tilemap1_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 128, 32);
|
|
m_tilemap_sizes[1][3] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(supracan_state::get_supracan_tilemap1_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 64, 64);
|
|
|
|
m_tilemap_sizes[2][0] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(supracan_state::get_supracan_tilemap2_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
|
|
m_tilemap_sizes[2][1] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(supracan_state::get_supracan_tilemap2_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
|
|
m_tilemap_sizes[2][2] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(supracan_state::get_supracan_tilemap2_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 128, 32);
|
|
m_tilemap_sizes[2][3] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(supracan_state::get_supracan_tilemap2_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 64, 64);
|
|
|
|
m_tilemap_sizes[3][0] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(supracan_state::get_supracan_roz_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
|
|
m_tilemap_sizes[3][1] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(supracan_state::get_supracan_roz_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
|
|
m_tilemap_sizes[3][2] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(supracan_state::get_supracan_roz_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 128, 32);
|
|
m_tilemap_sizes[3][3] = &machine().tilemap().create(tilemap_get_info_delegate(FUNC(supracan_state::get_supracan_roz_tile_info),this), TILEMAP_SCAN_ROWS, 8, 8, 64, 64);
|
|
}
|
|
|
|
static int get_tilemap_dimensions(running_machine &machine, int &xsize, int &ysize, int layer)
|
|
{
|
|
supracan_state *state = (supracan_state *)machine.driver_data<supracan_state>();
|
|
int select;
|
|
|
|
xsize = 32;
|
|
ysize = 32;
|
|
|
|
if (layer==3) select = (state->m_roz_mode & 0x0f00);
|
|
else select = state->m_tilemap_flags[layer] & 0x0f00;
|
|
|
|
switch(select)
|
|
{
|
|
case 0x600:
|
|
xsize = 64;
|
|
ysize = 32;
|
|
return 1;
|
|
|
|
case 0xa00:
|
|
xsize = 128;
|
|
ysize = 32;
|
|
return 2;
|
|
|
|
case 0xc00:
|
|
xsize = 64;
|
|
ysize = 64;
|
|
return 3;
|
|
|
|
default:
|
|
verboselog("maincpu", machine, 0, "Unsupported tilemap size for layer %d: %04x\n", layer, select);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
static void draw_sprites(running_machine &machine, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
|
{
|
|
supracan_state *state = machine.driver_data<supracan_state>();
|
|
UINT16 *supracan_vram = state->m_vram;
|
|
|
|
// [0]
|
|
// -e-- ---- ---- ---- sprite enable?
|
|
// ---h hhh- ---- ---- Y size (not always right)
|
|
// ---- ---y yyyy yyyy Y position
|
|
// [1]
|
|
// bbbb ---- ---- ---- Tile bank
|
|
// ---- h--- ---- ---- Horizontal flip
|
|
// ---- -v-- ---- ---- Vertical flip
|
|
// ---- --mm ---- ---- Masking mode
|
|
// ---- ---- ---- -www X size
|
|
// [2]
|
|
// zzzz ---- ---- ---- X scale
|
|
// ---- ---x xxxx xxxx X position
|
|
// [3]
|
|
// d--- ---- ---- ---- Direct Sprite (use details from here, not looked up in vram)
|
|
// -ooo oooo oooo oooo Sprite address
|
|
|
|
UINT32 skip_count = 0;
|
|
UINT32 start_word = (state->m_sprite_base_addr >> 1) + skip_count * 4;
|
|
UINT32 end_word = start_word + (state->m_sprite_count - skip_count) * 4;
|
|
int region = (state->m_sprite_flags & 1) ? 0 : 1; //8bpp : 4bpp
|
|
|
|
// printf("frame\n");
|
|
#define VRAM_MASK (0xffff)
|
|
|
|
for(int i = start_word; i < end_word; i += 4)
|
|
{
|
|
int x = supracan_vram[i+2] & 0x01ff;
|
|
int y = supracan_vram[i+0] & 0x01ff;
|
|
|
|
int sprite_offset = (supracan_vram[i+3])<< 1;
|
|
|
|
int bank = (supracan_vram[i+1] & 0xf000) >> 12;
|
|
//int mask = (supracan_vram[i+1] & 0x0300) >> 8;
|
|
int sprite_xflip = (supracan_vram[i+1] & 0x0800) >> 11;
|
|
int sprite_yflip = (supracan_vram[i+1] & 0x0400) >> 10;
|
|
//int xscale = (supracan_vram[i+2] & 0xf000) >> 12;
|
|
gfx_element *gfx = machine.gfx[region];
|
|
|
|
|
|
|
|
|
|
// wraparound
|
|
if (y>=0x180) y-=0x200;
|
|
if (x>=0x180) x-=0x200;
|
|
|
|
if((supracan_vram[i+0] & 0x4000))
|
|
{
|
|
|
|
#if 0
|
|
printf("%d (unk %02x) (enable %02x) (unk Y2 %02x, %02x) (y pos %02x) (bank %01x) (flip %01x) (unknown %02x) (x size %02x) (xscale %01x) (unk %01x) (xpos %02x) (code %04x)\n", i,
|
|
(supracan_vram[i+0] & 0x8000) >> 15,
|
|
(supracan_vram[i+0] & 0x4000) >> 14,
|
|
(supracan_vram[i+0] & 0x2000) >> 13,
|
|
(supracan_vram[i+0] & 0x1e00) >> 8,
|
|
(supracan_vram[i+0] & 0x01ff),
|
|
(supracan_vram[i+1] & 0xf000) >> 12,
|
|
(supracan_vram[i+1] & 0x0c00) >> 10,
|
|
(supracan_vram[i+1] & 0x03f0) >> 4,
|
|
(supracan_vram[i+1] & 0x000f),
|
|
(supracan_vram[i+2] & 0xf000) >> 12,
|
|
(supracan_vram[i+2] & 0x0e00) >> 8,
|
|
(supracan_vram[i+2] & 0x01ff) >> 0,
|
|
(supracan_vram[i+3] & 0xffff));
|
|
#endif
|
|
|
|
|
|
if (supracan_vram[i+3] &0x8000)
|
|
{
|
|
UINT16 data = supracan_vram[i+3];
|
|
int tile = (bank * 0x200) + (data & 0x03ff);
|
|
|
|
int palette = (data & 0xf000) >> 12; // this might not be correct, due to the &0x8000 condition above this would force all single tile sprites to be using palette >=0x8 only
|
|
|
|
//printf("sprite data %04x %04x %04x %04x\n", supracan_vram[i+0] , supracan_vram[i+1] , supracan_vram[i+2] ,supracan_vram[i+3] );
|
|
|
|
drawgfx_transpen(bitmap,cliprect,gfx,tile,palette,sprite_xflip,sprite_yflip,
|
|
x,
|
|
y,
|
|
0);
|
|
|
|
}
|
|
else
|
|
{
|
|
int xsize = 1 << (supracan_vram[i+1] & 7);
|
|
int ysize = ((supracan_vram[i+0] & 0x1e00) >> 9) + 1;
|
|
|
|
// I think the xsize must influence the ysize somehow, there are too many conflicting cases otherwise
|
|
// there don't appear to be any special markers in the actual looked up tile data to indicate skip / end of list
|
|
|
|
for(int ytile = 0; ytile < ysize; ytile++)
|
|
{
|
|
for(int xtile = 0; xtile< xsize; xtile++)
|
|
{
|
|
UINT16 data = supracan_vram[(sprite_offset+ytile*xsize+xtile)&VRAM_MASK];
|
|
int tile = (bank * 0x200) + (data & 0x03ff);
|
|
int palette = (data & 0xf000) >> 12;
|
|
|
|
int xpos, ypos;
|
|
|
|
if (!sprite_yflip)
|
|
{
|
|
ypos = y + ytile*8;
|
|
}
|
|
else
|
|
{
|
|
ypos = y - (ytile+1)*8;
|
|
ypos += ysize*8;
|
|
}
|
|
|
|
if (!sprite_xflip)
|
|
{
|
|
xpos = x + xtile*8;
|
|
}
|
|
else
|
|
{
|
|
xpos = x - (xtile+1)*8;
|
|
xpos += xsize*8;
|
|
}
|
|
|
|
int tile_xflip = sprite_xflip ^ ((data & 0x0800)>>11);
|
|
int tile_yflip = sprite_yflip ^ ((data & 0x0400)>>10);
|
|
|
|
drawgfx_transpen(bitmap,cliprect,gfx,tile,palette,tile_xflip,tile_yflip,xpos,ypos,0);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
if(xscale == 0) continue;
|
|
UINT32 delta = (1 << 17) / xscale;
|
|
for(int sy = 0; sy < ysize*8; sy++)
|
|
{
|
|
UINT16 *src = &sprite_bitmap->pix16(sy);
|
|
UINT16 *dst = &bitmap.pix16(y + sy);
|
|
UINT32 dx = x << 16;
|
|
for(int sx = 0; sx < xsize*8; sx++)
|
|
{
|
|
dst[dx >> 16] = src[sx];
|
|
dx += delta;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void mark_active_tilemap_all_dirty(running_machine &machine, int layer)
|
|
{
|
|
supracan_state *state = (supracan_state *)machine.driver_data<supracan_state>();
|
|
int xsize = 0;
|
|
int ysize = 0;
|
|
|
|
int which_tilemap_size;
|
|
|
|
which_tilemap_size = get_tilemap_dimensions(machine, xsize, ysize, layer);
|
|
// for (int i=0;i<4;i++)
|
|
// tilemap_mark_all_tiles_dirty(state->m_tilemap_sizes[layer][i]);
|
|
state->m_tilemap_sizes[layer][which_tilemap_size]->mark_all_dirty();
|
|
}
|
|
|
|
|
|
|
|
/* draws ROZ with linescroll OR columnscroll to 16-bit indexed bitmap */
|
|
static void supracan_suprnova_draw_roz(running_machine &machine, bitmap_ind16 &bitmap, const rectangle &cliprect, tilemap_t *tmap, UINT32 startx, UINT32 starty, int incxx, int incxy, int incyx, int incyy, int wraparound/*, int columnscroll, UINT32* scrollram*/, int transmask)
|
|
{
|
|
//bitmap_ind16 *destbitmap = bitmap;
|
|
bitmap_ind16 &srcbitmap = tmap->pixmap();
|
|
//bitmap_ind16 &srcbitmapflags = tmap->flagsmap();
|
|
const int xmask = srcbitmap.width()-1;
|
|
const int ymask = srcbitmap.height()-1;
|
|
const int widthshifted = srcbitmap.width() << 16;
|
|
const int heightshifted = srcbitmap.height() << 16;
|
|
UINT32 cx;
|
|
UINT32 cy;
|
|
int x;
|
|
int sx;
|
|
int sy;
|
|
int ex;
|
|
int ey;
|
|
UINT16 *dest;
|
|
// UINT8* destflags;
|
|
// UINT8 *pri;
|
|
//const UINT16 *src;
|
|
//const UINT8 *maskptr;
|
|
//int destadvance = destbitmap->bpp / 8;
|
|
|
|
/* pre-advance based on the cliprect */
|
|
startx += cliprect.min_x * incxx + cliprect.min_y * incyx;
|
|
starty += cliprect.min_x * incxy + cliprect.min_y * incyy;
|
|
|
|
/* extract start/end points */
|
|
sx = cliprect.min_x;
|
|
sy = cliprect.min_y;
|
|
ex = cliprect.max_x;
|
|
ey = cliprect.max_y;
|
|
|
|
{
|
|
/* loop over rows */
|
|
while (sy <= ey)
|
|
{
|
|
|
|
/* initialize X counters */
|
|
x = sx;
|
|
cx = startx;
|
|
cy = starty;
|
|
|
|
/* get dest and priority pointers */
|
|
dest = &bitmap.pix16(sy, sx);
|
|
//destflags = &bitmapflags->pix8(sy, sx);
|
|
|
|
/* loop over columns */
|
|
while (x <= ex)
|
|
{
|
|
if ((wraparound) || (cx < widthshifted && cy < heightshifted)) // not sure how this will cope with no wraparound, but row/col scroll..
|
|
{
|
|
#if 0
|
|
if (columnscroll)
|
|
{
|
|
int scroll = 0;//scrollram[(cx>>16)&0x3ff]);
|
|
|
|
|
|
UINT16 data = &srcbitmap.pix16(
|
|
((cy >> 16) - scroll) & ymask,
|
|
(cx >> 16) & xmask)[0];
|
|
|
|
if ((data & transmask)!=0)
|
|
dest[0] = data;
|
|
|
|
//destflags[0] = &srcbitmapflags.pix8(((cy >> 16) - scrollram[(cx>>16)&0x3ff]) & ymask, (cx >> 16) & xmask)[0];
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
int scroll = 0;//scrollram[(cy>>16)&0x3ff]);
|
|
UINT16 data = srcbitmap.pix16(
|
|
(cy >> 16) & ymask,
|
|
((cx >> 16) - scroll) & xmask);
|
|
|
|
|
|
if ((data & transmask)!=0)
|
|
dest[0] = data;
|
|
|
|
//destflags[0] = &srcbitmapflags.pix8((cy >> 16) & ymask, ((cx >> 16) - scrollram[(cy>>16)&0x3ff]) & xmask)[0];
|
|
}
|
|
}
|
|
|
|
/* advance in X */
|
|
cx += incxx;
|
|
cy += incxy;
|
|
x++;
|
|
dest++;
|
|
// destflags++;
|
|
// pri++;
|
|
}
|
|
|
|
/* advance in Y */
|
|
startx += incyx;
|
|
starty += incyy;
|
|
sy++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// VIDEO FLAGS ROZ MODE TILEMAP FLAGS
|
|
//
|
|
// Bit Bit Bit
|
|
// 15-9: Unknown 15-13: Priority? 15-13: Priority?
|
|
// 8: X ht. (256/320) 12: Unknown 12: Unknown
|
|
// 7: Tilemap 0 enable 11-8: Dims 11-8: Dims
|
|
// 6: Tilemap 1 enable 7-6: Unknown 7-6: Unknown
|
|
// 5: Tilemap 2 enable? 5: Wrap 5: Wrap
|
|
// 3: Sprite enable 4-2: Unknown 4-2: Mosaic
|
|
// 2: ROZ enable 1-0: Bit Depth 1-0: Bit Depth
|
|
// 1-0: Unknown
|
|
|
|
// Video Flags ROZ Mode Tilemap 0 Tilemap 1 Tilemap 2 VF Unk0
|
|
// A'Can logo: 120e: 0001 0010 0000 1110 4020: 0100 0000 0010 0000 4620 ---- ---- 0x09
|
|
// Boomzoo Intro: 9a82: 1001 1010 1000 0010 0402: 0000 0100 0000 0010 6400 6400 4400 0x4d
|
|
// Boomzoo Title: 9acc: 1001 1010 1100 1100 0402: 0000 0100 0000 0010 6400 6400 4400 0x4d
|
|
// C.U.G. Intro: 11c8: 0001 0001 1100 1000 0402: 0000 0100 0000 0010 2400 4400 6400 0x08
|
|
// C.U.G. Title: 11cc: 0001 0001 1100 1100 0602: 0000 0110 0000 0010 2600 4600 ---- 0x08
|
|
// Speedy Dragon Logo: 0388: 0000 0011 1000 1000 4020: 0100 0000 0010 0000 6c20 6c20 2600 0x01
|
|
// Speedy Dragon Title: 038c: 0000 0011 1000 1100 2603: 0010 0110 0000 0011 6c20 2c20 2600 0x01
|
|
// Sango Fighter Intro: 03c8: 0000 0011 1100 1000 ----: ---- ---- ---- ---- 6c20 4620 ---- 0x01
|
|
// Sango Fighter Game: 03ce: 0000 0011 1100 1110 0622: 0000 0110 0010 0010 2620 4620 ---- 0x01
|
|
|
|
UINT32 supracan_state::screen_update_supracan(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
|
|
{
|
|
|
|
|
|
|
|
// treat the sprites as frame-buffered and only update the buffer when drawing scanline 0 - this might not be true!
|
|
|
|
if (0)
|
|
{
|
|
if (cliprect.min_y == 0x00)
|
|
{
|
|
const rectangle &visarea = screen.visible_area();
|
|
|
|
m_sprite_final_bitmap.fill(0x00, visarea);
|
|
bitmap.fill(0x80, visarea);
|
|
|
|
draw_sprites(machine(), m_sprite_final_bitmap, visarea);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
m_sprite_final_bitmap.fill(0x00, cliprect);
|
|
bitmap.fill(0x80, cliprect);
|
|
|
|
draw_sprites(machine(), m_sprite_final_bitmap, cliprect);
|
|
}
|
|
|
|
|
|
|
|
// mix screen
|
|
int xsize = 0, ysize = 0;
|
|
// int tilemap_num;
|
|
int which_tilemap_size;
|
|
int priority = 0;
|
|
|
|
|
|
for (int pri=7;pri>=0;pri--)
|
|
{
|
|
|
|
for (int layer = 3; layer >=0; layer--)
|
|
{
|
|
// popmessage("%04x\n",m_video_flags);
|
|
int enabled = 0;
|
|
|
|
if(m_video_flags & 0x04)
|
|
if (layer==3) enabled = 1;
|
|
|
|
if(m_video_flags & 0x80)
|
|
if (layer==0) enabled = 1;
|
|
|
|
if(m_video_flags & 0x40)
|
|
if (layer==1) enabled = 1;
|
|
|
|
if(m_video_flags & 0x20)
|
|
if (layer==2) enabled = 1;
|
|
|
|
|
|
if (layer==3) priority = ((m_roz_mode >> 13) & 7); // roz case
|
|
else priority = ((m_tilemap_flags[layer] >> 13) & 7); // normal cases
|
|
|
|
|
|
if (priority==pri)
|
|
{
|
|
// tilemap_num = layer;
|
|
which_tilemap_size = get_tilemap_dimensions(machine(), xsize, ysize, layer);
|
|
bitmap_ind16 &src_bitmap = m_tilemap_sizes[layer][which_tilemap_size]->pixmap();
|
|
int gfx_region = supracan_tilemap_get_region(machine(), layer);
|
|
int transmask = 0xff;
|
|
|
|
switch (gfx_region)
|
|
{
|
|
case 0:transmask = 0xff; break;
|
|
case 1:transmask = 0x0f; break;
|
|
case 2:transmask = 0x03; break;
|
|
case 3:transmask = 0x01; break;
|
|
case 4:transmask = 0x01; break;
|
|
}
|
|
|
|
if (enabled)
|
|
{
|
|
if (layer != 3) // standard layers, NOT roz
|
|
{
|
|
|
|
int wrap = (m_tilemap_flags[layer] & 0x20);
|
|
|
|
int scrollx = m_tilemap_scrollx[layer];
|
|
int scrolly = m_tilemap_scrolly[layer];
|
|
|
|
if (scrollx&0x8000) scrollx-= 0x10000;
|
|
if (scrolly&0x8000) scrolly-= 0x10000;
|
|
|
|
int mosaic_count = (m_tilemap_flags[layer] & 0x001c) >> 2;
|
|
int mosaic_mask = 0xffffffff << mosaic_count;
|
|
|
|
int y,x;
|
|
// yes, it will draw a single line if you specify a cliprect as such (partial updates...)
|
|
|
|
for (y=cliprect.min_y;y<=cliprect.max_y;y++)
|
|
{
|
|
// these will have to change to ADDR32 etc. once alpha blending is supported
|
|
UINT16* screen = &bitmap.pix16(y);
|
|
|
|
int actualy = y&mosaic_mask;
|
|
|
|
int realy = actualy+scrolly;
|
|
|
|
if (!wrap)
|
|
if (scrolly+y < 0 || scrolly+y > ((ysize*8)-1))
|
|
continue;
|
|
|
|
|
|
UINT16* src = &src_bitmap.pix16((realy)&((ysize*8)-1));
|
|
|
|
for (x=cliprect.min_x;x<=cliprect.max_x;x++)
|
|
{
|
|
int actualx = x & mosaic_mask;
|
|
int realx = actualx+scrollx;
|
|
|
|
if (!wrap)
|
|
if (scrollx+x < 0 || scrollx+x > ((xsize*8)-1))
|
|
continue;
|
|
|
|
UINT16 srcpix = src[(realx)&((xsize*8)-1)];
|
|
|
|
if ((srcpix & transmask) != 0)
|
|
screen[x] = srcpix;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int wrap = m_roz_mode & 0x20;
|
|
|
|
int incxx = (m_roz_coeffa);
|
|
int incyy = (m_roz_coeffd);
|
|
|
|
int incxy = (m_roz_coeffc);
|
|
int incyx = (m_roz_coeffb);
|
|
|
|
int scrollx = (m_roz_scrollx);
|
|
int scrolly = (m_roz_scrolly);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (incyx & 0x8000) incyx -= 0x10000;
|
|
if (incxy & 0x8000) incxy -= 0x10000;
|
|
|
|
if (incyy & 0x8000) incyy -= 0x10000;
|
|
if (incxx & 0x8000) incxx -= 0x10000;
|
|
|
|
//popmessage("%04x %04x\n",m_video_flags, m_roz_mode);
|
|
|
|
// roz mode..
|
|
//4020 = enabled speedyd
|
|
//6c22 = enabled speedyd
|
|
//2c22 = enabled speedyd
|
|
//4622 = disabled jttlaugh
|
|
//2602 = disabled monopoly
|
|
//0402 = disabled (sango title)
|
|
// or is it always enabled, and only corrupt because we don't clear ram properly?
|
|
// (probably not this register?)
|
|
|
|
if (!(m_roz_mode & 0x0200) && (m_roz_mode&0xf000) ) // HACK - Not Trusted, Acan Logo, Speedy Dragon Intro ,Speed Dragon Bonus stage need it. Monopoly and JTT *don't* causes graphical issues
|
|
{
|
|
// NOT accurate, causes issues when the attract mode loops and the logo is shown the 2nd time in some games - investigate
|
|
for (int y=cliprect.min_y;y<=cliprect.max_y;y++)
|
|
{
|
|
rectangle clip(cliprect.min_x, cliprect.max_x, y, y);
|
|
|
|
scrollx = (m_roz_scrollx);
|
|
scrolly = (m_roz_scrolly);
|
|
incxx = (m_roz_coeffa);
|
|
|
|
incxx += m_vram[m_roz_unk_base0/2 + y];
|
|
|
|
scrollx += m_vram[m_roz_unk_base1/2 + y*2] << 16;
|
|
scrollx += m_vram[m_roz_unk_base1/2 + y*2 + 1];
|
|
|
|
scrolly += m_vram[m_roz_unk_base2/2 + y*2] << 16;
|
|
scrolly += m_vram[m_roz_unk_base2/2 + y*2 + 1];
|
|
|
|
if (incxx & 0x8000) incxx -= 0x10000;
|
|
|
|
|
|
if (m_vram[m_roz_unk_base0/2 + y]) // incxx = 0, no draw?
|
|
supracan_suprnova_draw_roz(machine(), bitmap, clip, m_tilemap_sizes[layer][which_tilemap_size], scrollx<<8, scrolly<<8, incxx<<8, incxy<<8, incyx<<8, incyy<<8, wrap, transmask);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
supracan_suprnova_draw_roz(machine(), bitmap, cliprect, m_tilemap_sizes[layer][which_tilemap_size], scrollx<<8, scrolly<<8, incxx<<8, incxy<<8, incyx<<8, incyy<<8, wrap, transmask);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// just draw the sprites on top for now
|
|
if(m_video_flags & 0x08)
|
|
{
|
|
for (int y=cliprect.min_y;y<=cliprect.max_y;y++)
|
|
{
|
|
UINT16* src = &m_sprite_final_bitmap.pix16(y);
|
|
UINT16* dst = &bitmap.pix16(y);
|
|
|
|
for (int x=cliprect.min_x;x<=cliprect.max_x;x++)
|
|
{
|
|
UINT16 dat = src[x];
|
|
if (dat) dst[x] = dat;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
WRITE16_MEMBER( supracan_state::supracan_dma_w )
|
|
{
|
|
acan_dma_regs_t *acan_dma_regs = &m_acan_dma_regs;
|
|
int ch = (offset < 0x10/2) ? 0 : 1;
|
|
address_space *mem = m_maincpu->space(AS_PROGRAM);
|
|
|
|
switch(offset)
|
|
{
|
|
case 0x00/2: // Source address MSW
|
|
case 0x10/2:
|
|
verboselog("maincpu", machine(), 0, "supracan_dma_w: source msw %d: %04x\n", ch, data);
|
|
acan_dma_regs->source[ch] &= 0x0000ffff;
|
|
acan_dma_regs->source[ch] |= data << 16;
|
|
break;
|
|
case 0x02/2: // Source address LSW
|
|
case 0x12/2:
|
|
verboselog("maincpu", machine(), 0, "supracan_dma_w: source lsw %d: %04x\n", ch, data);
|
|
acan_dma_regs->source[ch] &= 0xffff0000;
|
|
acan_dma_regs->source[ch] |= data;
|
|
break;
|
|
case 0x04/2: // Destination address MSW
|
|
case 0x14/2:
|
|
verboselog("maincpu", machine(), 0, "supracan_dma_w: dest msw %d: %04x\n", ch, data);
|
|
acan_dma_regs->dest[ch] &= 0x0000ffff;
|
|
acan_dma_regs->dest[ch] |= data << 16;
|
|
break;
|
|
case 0x06/2: // Destination address LSW
|
|
case 0x16/2:
|
|
verboselog("maincpu", machine(), 0, "supracan_dma_w: dest lsw %d: %04x\n", ch, data);
|
|
acan_dma_regs->dest[ch] &= 0xffff0000;
|
|
acan_dma_regs->dest[ch] |= data;
|
|
break;
|
|
case 0x08/2: // Byte count
|
|
case 0x18/2:
|
|
verboselog("maincpu", machine(), 0, "supracan_dma_w: count %d: %04x\n", ch, data);
|
|
acan_dma_regs->count[ch] = data;
|
|
break;
|
|
case 0x0a/2: // Control
|
|
case 0x1a/2:
|
|
verboselog("maincpu", machine(), 0, "supracan_dma_w: control %d: %04x\n", ch, data);
|
|
if(data & 0x8800)
|
|
{
|
|
// if(data & 0x2000)
|
|
// acan_dma_regs->source-=2;
|
|
logerror("supracan_dma_w: Kicking off a DMA from %08x to %08x, %d bytes (%04x)\n", acan_dma_regs->source[ch], acan_dma_regs->dest[ch], acan_dma_regs->count[ch] + 1, data);
|
|
|
|
for(int i = 0; i <= acan_dma_regs->count[ch]; i++)
|
|
{
|
|
if(data & 0x1000)
|
|
{
|
|
mem->write_word(acan_dma_regs->dest[ch], mem->read_word(acan_dma_regs->source[ch]));
|
|
acan_dma_regs->dest[ch]+=2;
|
|
acan_dma_regs->source[ch]+=2;
|
|
if(data & 0x0100)
|
|
if((acan_dma_regs->dest[ch] & 0xf) == 0)
|
|
acan_dma_regs->dest[ch]-=0x10;
|
|
}
|
|
else
|
|
{
|
|
mem->write_byte(acan_dma_regs->dest[ch], mem->read_byte(acan_dma_regs->source[ch]));
|
|
acan_dma_regs->dest[ch]++;
|
|
acan_dma_regs->source[ch]++;
|
|
}
|
|
}
|
|
}
|
|
else if(data != 0x0000) // fake DMA, used by C.U.G.
|
|
{
|
|
verboselog("maincpu", machine(), 0, "supracan_dma_w: Unknown DMA kickoff value of %04x (other regs %08x, %08x, %d)\n", data, acan_dma_regs->source[ch], acan_dma_regs->dest[ch], acan_dma_regs->count[ch] + 1);
|
|
fatalerror("supracan_dma_w: Unknown DMA kickoff value of %04x (other regs %08x, %08x, %d)\n",data, acan_dma_regs->source[ch], acan_dma_regs->dest[ch], acan_dma_regs->count[ch] + 1);
|
|
}
|
|
break;
|
|
default:
|
|
verboselog("maincpu", machine(), 0, "supracan_dma_w: Unknown register: %08x = %04x & %04x\n", 0xe90020 + (offset << 1), data, mem_mask);
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
WRITE16_MEMBER( supracan_state::supracan_pram_w )
|
|
{
|
|
m_pram[offset] &= ~mem_mask;
|
|
m_pram[offset] |= data & mem_mask;
|
|
}
|
|
#endif
|
|
|
|
// swap address around so that 64x64 tile can be decoded as 8x8 tiles..
|
|
void supracan_state::write_swapped_byte( int offset, UINT8 byte )
|
|
{
|
|
int swapped_offset = BITSWAP32(offset, 31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,2,1,0,6,5,4,3);
|
|
|
|
m_vram_addr_swapped[swapped_offset] = byte;
|
|
}
|
|
|
|
|
|
READ16_MEMBER( supracan_state::supracan_vram_r )
|
|
{
|
|
return m_vram[offset];
|
|
}
|
|
|
|
|
|
WRITE16_MEMBER( supracan_state::supracan_vram_w )
|
|
{
|
|
COMBINE_DATA(&m_vram[offset]);
|
|
|
|
// store a byteswapped vesrion for easier gfx-decode
|
|
data = m_vram[offset];
|
|
data = ((data & 0x00ff)<<8) | ((data & 0xff00)>>8);
|
|
m_vram_swapped[offset] = data;
|
|
|
|
// hack for 1bpp layer at startup
|
|
write_swapped_byte(offset*2+1, (data & 0xff00)>>8);
|
|
write_swapped_byte(offset*2, (data & 0x00ff));
|
|
|
|
// mark tiles of each depth as dirty
|
|
machine().gfx[0]->mark_dirty((offset*2)/(64));
|
|
machine().gfx[1]->mark_dirty((offset*2)/(32));
|
|
machine().gfx[2]->mark_dirty((offset*2)/(16));
|
|
machine().gfx[3]->mark_dirty((offset*2)/(512));
|
|
machine().gfx[4]->mark_dirty((offset*2)/(8));
|
|
|
|
}
|
|
|
|
static ADDRESS_MAP_START( supracan_mem, AS_PROGRAM, 16, supracan_state )
|
|
AM_RANGE( 0x000000, 0x3fffff ) AM_ROM AM_REGION( "cart", 0 )
|
|
AM_RANGE( 0xe80200, 0xe80201 ) AM_READ_PORT("P1")
|
|
AM_RANGE( 0xe80202, 0xe80203 ) AM_READ_PORT("P2")
|
|
AM_RANGE( 0xe80208, 0xe80209 ) AM_READ_PORT("P3")
|
|
AM_RANGE( 0xe8020c, 0xe8020d ) AM_READ_PORT("P4")
|
|
AM_RANGE( 0xe80000, 0xe8ffff ) AM_READWRITE( supracan_68k_soundram_r, supracan_68k_soundram_w )
|
|
AM_RANGE( 0xe90000, 0xe9001f ) AM_READWRITE( supracan_sound_r, supracan_sound_w )
|
|
AM_RANGE( 0xe90020, 0xe9003f ) AM_WRITE( supracan_dma_w )
|
|
AM_RANGE( 0xf00000, 0xf001ff ) AM_READWRITE( supracan_video_r, supracan_video_w )
|
|
AM_RANGE( 0xf00200, 0xf003ff ) AM_RAM AM_WRITE(paletteram_xBBBBBGGGGGRRRRR_word_w) AM_SHARE("paletteram")
|
|
AM_RANGE( 0xf40000, 0xf5ffff ) AM_READWRITE(supracan_vram_r, supracan_vram_w)
|
|
AM_RANGE( 0xfc0000, 0xfdffff ) AM_MIRROR(0x30000) AM_RAM /* System work ram */
|
|
ADDRESS_MAP_END
|
|
|
|
READ8_MEMBER( supracan_state::supracan_6502_soundmem_r )
|
|
{
|
|
address_space *mem = m_maincpu->space(AS_PROGRAM);
|
|
UINT8 data = m_soundram[offset];
|
|
|
|
switch(offset)
|
|
{
|
|
#if SOUNDCPU_BOOT_HACK
|
|
case 0x300: // HACK to make games think the sound CPU is always reporting 'OK'.
|
|
return 0xff;
|
|
#endif
|
|
|
|
case 0x410: // Sound IRQ enable
|
|
data = m_sound_irq_enable_reg;
|
|
if(!mem->debugger_access()) verboselog(m_hack_68k_to_6502_access ? "maincpu" : "soundcpu", machine(), 0, "supracan_soundreg_r: IRQ enable: %04x\n", data);
|
|
if(!mem->debugger_access())
|
|
{
|
|
if(m_sound_irq_enable_reg & m_sound_irq_source_reg)
|
|
{
|
|
machine().device("soundcpu")->execute().set_input_line(0, ASSERT_LINE);
|
|
}
|
|
else
|
|
{
|
|
machine().device("soundcpu")->execute().set_input_line(0, CLEAR_LINE);
|
|
}
|
|
}
|
|
break;
|
|
case 0x411: // Sound IRQ source
|
|
data = m_sound_irq_source_reg;
|
|
m_sound_irq_source_reg = 0;
|
|
if(!mem->debugger_access()) verboselog(m_hack_68k_to_6502_access ? "maincpu" : "soundcpu", machine(), 3, "supracan_soundreg_r: IRQ source: %04x\n", data);
|
|
if(!mem->debugger_access())
|
|
{
|
|
machine().device("soundcpu")->execute().set_input_line(0, CLEAR_LINE);
|
|
}
|
|
break;
|
|
case 0x420:
|
|
if(!mem->debugger_access()) verboselog(m_hack_68k_to_6502_access ? "maincpu" : "soundcpu", machine(), 3, "supracan_soundreg_r: Sound hardware status? (not yet implemented): %02x\n", 0);
|
|
break;
|
|
case 0x422:
|
|
if(!mem->debugger_access()) verboselog(m_hack_68k_to_6502_access ? "maincpu" : "soundcpu", machine(), 3, "supracan_soundreg_r: Sound hardware data? (not yet implemented): %02x\n", 0);
|
|
break;
|
|
case 0x404:
|
|
case 0x405:
|
|
case 0x409:
|
|
case 0x414:
|
|
case 0x416:
|
|
// Intentional fall-through
|
|
default:
|
|
if(offset >= 0x300 && offset < 0x500)
|
|
{
|
|
if(!mem->debugger_access()) verboselog(m_hack_68k_to_6502_access ? "maincpu" : "soundcpu", machine(), 0, "supracan_soundreg_r: Unknown register %04x\n", offset);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
WRITE8_MEMBER( supracan_state::supracan_6502_soundmem_w )
|
|
{
|
|
switch(offset)
|
|
{
|
|
case 0x407:
|
|
if(m_sound_cpu_68k_irq_reg &~ data)
|
|
{
|
|
verboselog(m_hack_68k_to_6502_access ? "maincpu" : "soundcpu", machine(), 0, "supracan_soundreg_w: sound_cpu_68k_irq_reg: %04x: Triggering M68k IRQ\n", data);
|
|
m_maincpu->set_input_line(7, HOLD_LINE);
|
|
}
|
|
else
|
|
{
|
|
verboselog(m_hack_68k_to_6502_access ? "maincpu" : "soundcpu", machine(), 0, "supracan_soundreg_w: sound_cpu_68k_irq_reg: %04x\n", data);
|
|
}
|
|
m_sound_cpu_68k_irq_reg = data;
|
|
break;
|
|
case 0x410:
|
|
m_sound_irq_enable_reg = data;
|
|
verboselog(m_hack_68k_to_6502_access ? "maincpu" : "soundcpu", machine(), 0, "supracan_soundreg_w: IRQ enable: %02x\n", data);
|
|
break;
|
|
case 0x420:
|
|
verboselog(m_hack_68k_to_6502_access ? "maincpu" : "soundcpu", machine(), 3, "supracan_soundreg_w: Sound hardware reg data? (not yet implemented): %02x\n", data);
|
|
break;
|
|
case 0x422:
|
|
verboselog(m_hack_68k_to_6502_access ? "maincpu" : "soundcpu", machine(), 3, "supracan_soundreg_w: Sound hardware reg addr? (not yet implemented): %02x\n", data);
|
|
break;
|
|
default:
|
|
if(offset >= 0x300 && offset < 0x500)
|
|
{
|
|
verboselog(m_hack_68k_to_6502_access ? "maincpu" : "soundcpu", machine(), 0, "supracan_soundreg_w: Unknown register %04x = %02x\n", offset, data);
|
|
}
|
|
m_soundram[offset] = data;
|
|
break;
|
|
}
|
|
}
|
|
|
|
static ADDRESS_MAP_START( supracan_sound_mem, AS_PROGRAM, 8, supracan_state )
|
|
AM_RANGE( 0x0000, 0xffff ) AM_READWRITE(supracan_6502_soundmem_r, supracan_6502_soundmem_w) AM_SHARE("soundram")
|
|
ADDRESS_MAP_END
|
|
|
|
static INPUT_PORTS_START( supracan )
|
|
PORT_START("P1")
|
|
PORT_DIPNAME( 0x01, 0x00, "SYSTEM" )
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x01, DEF_STR( On ) )
|
|
PORT_DIPNAME( 0x02, 0x00, DEF_STR( Unknown ) )
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x02, DEF_STR( On ) )
|
|
PORT_DIPNAME( 0x04, 0x00, DEF_STR( Unknown ) )
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x04, DEF_STR( On ) )
|
|
PORT_DIPNAME( 0x08, 0x00, DEF_STR( Unknown ) )
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x08, DEF_STR( On ) )
|
|
PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_PLAYER(1) PORT_NAME("P1 Button R")
|
|
PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_PLAYER(1) PORT_NAME("P1 Button L")
|
|
PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_PLAYER(1) PORT_NAME("P1 Button Y")
|
|
PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(1) PORT_NAME("P1 Button X")
|
|
PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_NAME("P1 Joypad Right")
|
|
PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_NAME("P1 Joypad Left")
|
|
PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_NAME("P1 Joypad Down")
|
|
PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_NAME("P1 Joypad Up")
|
|
PORT_DIPNAME( 0x1000, 0x0000, "SYSTEM" )
|
|
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x1000, DEF_STR( On ) )
|
|
PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_START1 )
|
|
PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_PLAYER(1) PORT_NAME("P1 Button B")
|
|
PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(1) PORT_NAME("P1 Button A")
|
|
|
|
PORT_START("P2")
|
|
PORT_DIPNAME( 0x01, 0x00, "SYSTEM" )
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x01, DEF_STR( On ) )
|
|
PORT_DIPNAME( 0x02, 0x00, DEF_STR( Unknown ) )
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x02, DEF_STR( On ) )
|
|
PORT_DIPNAME( 0x04, 0x00, DEF_STR( Unknown ) )
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x04, DEF_STR( On ) )
|
|
PORT_DIPNAME( 0x08, 0x00, DEF_STR( Unknown ) )
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x08, DEF_STR( On ) )
|
|
PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_PLAYER(2) PORT_NAME("P2 Button R")
|
|
PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_PLAYER(2) PORT_NAME("P2 Button L")
|
|
PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_PLAYER(2) PORT_NAME("P2 Button Y")
|
|
PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(2) PORT_NAME("P2 Button X")
|
|
PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_NAME("P2 Joypad Right")
|
|
PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) PORT_NAME("P2 Joypad Left")
|
|
PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) PORT_NAME("P2 Joypad Down")
|
|
PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(2) PORT_NAME("P2 Joypad Up")
|
|
PORT_DIPNAME( 0x1000, 0x0000, "SYSTEM" )
|
|
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x1000, DEF_STR( On ) )
|
|
PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_START2 )
|
|
PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_PLAYER(2) PORT_NAME("P2 Button B")
|
|
PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(2) PORT_NAME("P2 Button A")
|
|
|
|
PORT_START("P3")
|
|
PORT_DIPNAME( 0x01, 0x00, "SYSTEM" )
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x01, DEF_STR( On ) )
|
|
PORT_DIPNAME( 0x02, 0x00, DEF_STR( Unknown ) )
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x02, DEF_STR( On ) )
|
|
PORT_DIPNAME( 0x04, 0x00, DEF_STR( Unknown ) )
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x04, DEF_STR( On ) )
|
|
PORT_DIPNAME( 0x08, 0x00, DEF_STR( Unknown ) )
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x08, DEF_STR( On ) )
|
|
PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_PLAYER(3) PORT_NAME("P3 Button R")
|
|
PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_PLAYER(3) PORT_NAME("P3 Button L")
|
|
PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_PLAYER(3) PORT_NAME("P3 Button Y")
|
|
PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(3) PORT_NAME("P3 Button X")
|
|
PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(3) PORT_NAME("P3 Joypad Right")
|
|
PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(3) PORT_NAME("P3 Joypad Left")
|
|
PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(3) PORT_NAME("P3 Joypad Down")
|
|
PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(3) PORT_NAME("P3 Joypad Up")
|
|
PORT_DIPNAME( 0x1000, 0x0000, "SYSTEM" )
|
|
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x1000, DEF_STR( On ) )
|
|
PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_START3 )
|
|
PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_PLAYER(3) PORT_NAME("P3 Button B")
|
|
PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(3) PORT_NAME("P3 Button A")
|
|
|
|
PORT_START("P4")
|
|
PORT_DIPNAME( 0x01, 0x00, "SYSTEM" )
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x01, DEF_STR( On ) )
|
|
PORT_DIPNAME( 0x02, 0x00, DEF_STR( Unknown ) )
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x02, DEF_STR( On ) )
|
|
PORT_DIPNAME( 0x04, 0x00, DEF_STR( Unknown ) )
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x04, DEF_STR( On ) )
|
|
PORT_DIPNAME( 0x08, 0x00, DEF_STR( Unknown ) )
|
|
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x08, DEF_STR( On ) )
|
|
PORT_BIT(0x0010, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_PLAYER(4) PORT_NAME("P4 Button R")
|
|
PORT_BIT(0x0020, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_PLAYER(4) PORT_NAME("P4 Button L")
|
|
PORT_BIT(0x0040, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_PLAYER(4) PORT_NAME("P4 Button Y")
|
|
PORT_BIT(0x0080, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_PLAYER(4) PORT_NAME("P4 Button X")
|
|
PORT_BIT(0x0100, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(4) PORT_NAME("P4 Joypad Right")
|
|
PORT_BIT(0x0200, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(4) PORT_NAME("P4 Joypad Left")
|
|
PORT_BIT(0x0400, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(4) PORT_NAME("P4 Joypad Down")
|
|
PORT_BIT(0x0800, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(4) PORT_NAME("P4 Joypad Up")
|
|
PORT_DIPNAME( 0x1000, 0x0000, "SYSTEM" )
|
|
PORT_DIPSETTING( 0x0000, DEF_STR( Off ) )
|
|
PORT_DIPSETTING( 0x1000, DEF_STR( On ) )
|
|
PORT_BIT(0x2000, IP_ACTIVE_HIGH, IPT_START4 )
|
|
PORT_BIT(0x4000, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_PLAYER(4) PORT_NAME("P4 Button B")
|
|
PORT_BIT(0x8000, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_PLAYER(4) PORT_NAME("P4 Button A")
|
|
INPUT_PORTS_END
|
|
|
|
void supracan_state::palette_init()
|
|
{
|
|
// Used for debugging purposes for now
|
|
//#if 0
|
|
int i, r, g, b;
|
|
|
|
for( i = 0; i < 32768; i++ )
|
|
{
|
|
r = (i & 0x1f) << 3;
|
|
g = ((i >> 5) & 0x1f) << 3;
|
|
b = ((i >> 10) & 0x1f) << 3;
|
|
palette_set_color_rgb( machine(), i, r, g, b );
|
|
}
|
|
//#endif
|
|
}
|
|
|
|
WRITE16_MEMBER( supracan_state::supracan_68k_soundram_w )
|
|
{
|
|
address_space *mem = m_maincpu->space(AS_PROGRAM);
|
|
m_soundram[offset*2 + 1] = data & 0xff;
|
|
m_soundram[offset*2 + 0] = data >> 8;
|
|
|
|
if(offset*2 < 0x500 && offset*2 >= 0x300)
|
|
{
|
|
if(mem_mask & 0xff00)
|
|
{
|
|
m_hack_68k_to_6502_access = true;
|
|
supracan_6502_soundmem_w(*mem, offset*2, data >> 8);
|
|
m_hack_68k_to_6502_access = false;
|
|
}
|
|
if(mem_mask & 0x00ff)
|
|
{
|
|
m_hack_68k_to_6502_access = true;
|
|
supracan_6502_soundmem_w(*mem, offset*2 + 1, data & 0xff);
|
|
m_hack_68k_to_6502_access = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
READ16_MEMBER( supracan_state::supracan_68k_soundram_r )
|
|
{
|
|
address_space *mem = m_maincpu->space(AS_PROGRAM);
|
|
UINT16 val = m_soundram[offset*2 + 0] << 8;
|
|
val |= m_soundram[offset*2 + 1];
|
|
|
|
if(offset*2 >= 0x300 && offset*2 < 0x500)
|
|
{
|
|
val = 0;
|
|
if(mem_mask & 0xff00)
|
|
{
|
|
m_hack_68k_to_6502_access = true;
|
|
val |= supracan_6502_soundmem_r(*mem, offset*2) << 8;
|
|
m_hack_68k_to_6502_access = false;
|
|
}
|
|
if(mem_mask & 0x00ff)
|
|
{
|
|
m_hack_68k_to_6502_access = true;
|
|
val |= supracan_6502_soundmem_r(*mem, offset*2 + 1);
|
|
m_hack_68k_to_6502_access = false;
|
|
}
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
READ16_MEMBER( supracan_state::supracan_sound_r )
|
|
{
|
|
UINT16 data = 0;
|
|
|
|
switch( offset )
|
|
{
|
|
default:
|
|
verboselog("maincpu", machine(), 0, "supracan_sound_r: Unknown register: (%08x) & %04x\n", 0xe90000 + (offset << 1), mem_mask);
|
|
break;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
WRITE16_MEMBER( supracan_state::supracan_sound_w )
|
|
{
|
|
switch ( offset )
|
|
{
|
|
case 0x000a/2: /* Sound cpu IRQ request. */
|
|
machine().device("soundcpu")->execute().set_input_line(0, ASSERT_LINE);
|
|
break;
|
|
case 0x001c/2: /* Sound cpu control. Bit 0 tied to sound cpu RESET line */
|
|
if(data & 0x01)
|
|
{
|
|
if(!m_m6502_reset)
|
|
{
|
|
/* Reset and enable the sound cpu */
|
|
#if !(SOUNDCPU_BOOT_HACK)
|
|
machine().device("soundcpu")->execute().set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
|
|
machine().device("soundcpu")->reset();
|
|
#endif
|
|
}
|
|
m_m6502_reset = data & 0x01;
|
|
}
|
|
else
|
|
{
|
|
/* Halt the sound cpu */
|
|
machine().device("soundcpu")->execute().set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
|
|
}
|
|
verboselog("maincpu", machine(), 0, "sound cpu ctrl: %04x\n", data);
|
|
break;
|
|
default:
|
|
verboselog("maincpu", machine(), 0, "supracan_sound_w: Unknown register: %08x = %04x & %04x\n", 0xe90000 + (offset << 1), data, mem_mask);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
READ16_MEMBER( supracan_state::supracan_video_r )
|
|
{
|
|
address_space *mem = m_maincpu->space(AS_PROGRAM);
|
|
UINT16 data = m_video_regs[offset];
|
|
|
|
switch(offset)
|
|
{
|
|
case 0x00/2: // Video IRQ flags
|
|
if(!mem->debugger_access())
|
|
{
|
|
//verboselog("maincpu", machine(), 0, "read video IRQ flags (%04x)\n", data);
|
|
m_maincpu->set_input_line(7, CLEAR_LINE);
|
|
}
|
|
break;
|
|
case 0x02/2: // Current scanline
|
|
break;
|
|
case 0x08/2: // Unknown (not video flags!)
|
|
data = 0;
|
|
break;
|
|
case 0x100/2:
|
|
if(!mem->debugger_access()) verboselog("maincpu", machine(), 0, "read tilemap_flags[0] (%04x)\n", data);
|
|
break;
|
|
case 0x106/2:
|
|
if(!mem->debugger_access()) verboselog("maincpu", machine(), 0, "read tilemap_scrolly[0] (%04x)\n", data);
|
|
break;
|
|
case 0x120/2:
|
|
if(!mem->debugger_access()) verboselog("maincpu", machine(), 0, "read tilemap_flags[1] (%04x)\n", data);
|
|
break;
|
|
default:
|
|
if(!mem->debugger_access()) verboselog("maincpu", machine(), 0, "supracan_video_r: Unknown register: %08x (%04x & %04x)\n", 0xf00000 + (offset << 1), data, mem_mask);
|
|
break;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
static TIMER_CALLBACK( supracan_hbl_callback )
|
|
{
|
|
supracan_state *state = machine.driver_data<supracan_state>();
|
|
|
|
state->m_maincpu->set_input_line(3, HOLD_LINE);
|
|
|
|
state->m_hbl_timer->adjust(attotime::never);
|
|
}
|
|
|
|
static TIMER_CALLBACK( supracan_line_on_callback )
|
|
{
|
|
supracan_state *state = machine.driver_data<supracan_state>();
|
|
|
|
state->m_maincpu->set_input_line(5, HOLD_LINE);
|
|
|
|
state->m_line_on_timer->adjust(attotime::never);
|
|
}
|
|
|
|
static TIMER_CALLBACK( supracan_line_off_callback )
|
|
{
|
|
supracan_state *state = machine.driver_data<supracan_state>();
|
|
|
|
state->m_maincpu->set_input_line(5, CLEAR_LINE);
|
|
|
|
state->m_line_on_timer->adjust(attotime::never);
|
|
}
|
|
|
|
static TIMER_CALLBACK( supracan_video_callback )
|
|
{
|
|
supracan_state *state = machine.driver_data<supracan_state>();
|
|
int vpos = machine.primary_screen->vpos();
|
|
|
|
state->m_video_regs[0] &= ~0x0002;
|
|
|
|
switch( vpos )
|
|
{
|
|
case 0:
|
|
state->m_video_regs[0] &= 0x7fff;
|
|
|
|
// we really need better management of this
|
|
mark_active_tilemap_all_dirty(machine, 0);
|
|
mark_active_tilemap_all_dirty(machine, 1);
|
|
mark_active_tilemap_all_dirty(machine, 2);
|
|
mark_active_tilemap_all_dirty(machine, 3);
|
|
|
|
|
|
break;
|
|
|
|
case 224://FIXME: Son of Evil is pretty picky about this one, a timing of 240 makes it to crash
|
|
state->m_video_regs[0] |= 0x8000;
|
|
break;
|
|
|
|
case 240:
|
|
if(state->m_irq_mask & 1)
|
|
{
|
|
verboselog("maincpu", machine, 0, "Triggering VBL IRQ\n\n");
|
|
state->m_maincpu->set_input_line(7, HOLD_LINE);
|
|
}
|
|
break;
|
|
}
|
|
|
|
state->m_video_regs[1] = machine.primary_screen->vpos()-16; // for son of evil, wants vblank active around 224 instead...
|
|
|
|
state->m_hbl_timer->adjust( machine.primary_screen->time_until_pos( vpos, 320 ) );
|
|
state->m_video_timer->adjust( machine.primary_screen->time_until_pos( ( vpos + 1 ) % 256, 0 ) );
|
|
}
|
|
|
|
WRITE16_MEMBER( supracan_state::supracan_video_w )
|
|
{
|
|
address_space *mem = m_maincpu->space(AS_PROGRAM);
|
|
acan_sprdma_regs_t *acan_sprdma_regs = &m_acan_sprdma_regs;
|
|
int i;
|
|
|
|
// if any of this changes we need a partial update (see sango fighters intro)
|
|
machine().primary_screen->update_partial(machine().primary_screen->vpos());
|
|
|
|
switch(offset)
|
|
{
|
|
case 0x10/2: // Byte count
|
|
verboselog("maincpu", machine(), 0, "sprite dma word count: %04x\n", data);
|
|
acan_sprdma_regs->count = data;
|
|
break;
|
|
case 0x12/2: // Destination address MSW
|
|
acan_sprdma_regs->dst &= 0x0000ffff;
|
|
acan_sprdma_regs->dst |= data << 16;
|
|
verboselog("maincpu", machine(), 0, "sprite dma dest msw: %04x\n", data);
|
|
break;
|
|
case 0x14/2: // Destination address LSW
|
|
acan_sprdma_regs->dst &= 0xffff0000;
|
|
acan_sprdma_regs->dst |= data;
|
|
verboselog("maincpu", machine(), 0, "sprite dma dest lsw: %04x\n", data);
|
|
break;
|
|
case 0x16/2: // Source word increment
|
|
verboselog("maincpu", machine(), 0, "sprite dma dest word inc: %04x\n", data);
|
|
acan_sprdma_regs->dst_inc = data;
|
|
break;
|
|
case 0x18/2: // Source address MSW
|
|
acan_sprdma_regs->src &= 0x0000ffff;
|
|
acan_sprdma_regs->src |= data << 16;
|
|
verboselog("maincpu", machine(), 0, "sprite dma src msw: %04x\n", data);
|
|
break;
|
|
case 0x1a/2: // Source address LSW
|
|
verboselog("maincpu", machine(), 0, "sprite dma src lsw: %04x\n", data);
|
|
acan_sprdma_regs->src &= 0xffff0000;
|
|
acan_sprdma_regs->src |= data;
|
|
break;
|
|
case 0x1c/2: // Source word increment
|
|
verboselog("maincpu", machine(), 0, "sprite dma src word inc: %04x\n", data);
|
|
acan_sprdma_regs->src_inc = data;
|
|
break;
|
|
case 0x1e/2:
|
|
logerror( "supracan_video_w: Kicking off a DMA from %08x to %08x, %d bytes (%04x)\n", acan_sprdma_regs->src, acan_sprdma_regs->dst, acan_sprdma_regs->count, data);
|
|
|
|
/* TODO: what's 0x2000 and 0x4000 for? */
|
|
if(data & 0x8000)
|
|
{
|
|
if(data & 0x2000 || data & 0x4000)
|
|
{
|
|
acan_sprdma_regs->dst |= 0xf40000;
|
|
}
|
|
|
|
if(data & 0x2000)
|
|
{
|
|
//acan_sprdma_regs->count <<= 1;
|
|
}
|
|
|
|
for(i = 0; i <= acan_sprdma_regs->count; i++)
|
|
{
|
|
if(data & 0x0100) //dma 0x00 fill (or fixed value?)
|
|
{
|
|
mem->write_word(acan_sprdma_regs->dst, 0);
|
|
acan_sprdma_regs->dst+=2 * acan_sprdma_regs->dst_inc;
|
|
//memset(supracan_vram,0x00,0x020000);
|
|
}
|
|
else
|
|
{
|
|
mem->write_word(acan_sprdma_regs->dst, mem->read_word(acan_sprdma_regs->src));
|
|
acan_sprdma_regs->dst+=2 * acan_sprdma_regs->dst_inc;
|
|
acan_sprdma_regs->src+=2 * acan_sprdma_regs->src_inc;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
verboselog("maincpu", machine(), 0, "supracan_dma_w: Attempting to kick off a DMA without bit 15 set! (%04x)\n", data);
|
|
}
|
|
break;
|
|
case 0x08/2:
|
|
{
|
|
verboselog("maincpu", machine(), 3, "video_flags = %04x\n", data);
|
|
m_video_flags = data;
|
|
|
|
rectangle visarea = machine().primary_screen->visible_area();
|
|
|
|
visarea.set(0, ((m_video_flags & 0x100) ? 320 : 256) - 1, 8, 232 - 1);
|
|
machine().primary_screen->configure(348, 256, visarea, machine().primary_screen->frame_period().attoseconds);
|
|
}
|
|
break;
|
|
case 0x0a/2:
|
|
{
|
|
// raster interrupt
|
|
verboselog("maincpu", machine(), 0, "IRQ Trigger? = %04x\n", data);
|
|
if(data & 0x8000)
|
|
{
|
|
m_line_on_timer->adjust(machine().primary_screen->time_until_pos((data & 0x00ff), 0));
|
|
}
|
|
else
|
|
{
|
|
m_line_on_timer->adjust(attotime::never);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 0x0c/2:
|
|
{
|
|
verboselog("maincpu", machine(), 0, "IRQ De-Trigger? = %04x\n", data);
|
|
if(data & 0x8000)
|
|
{
|
|
m_line_off_timer->adjust(machine().primary_screen->time_until_pos(data & 0x00ff, 0));
|
|
}
|
|
else
|
|
{
|
|
m_line_off_timer->adjust(attotime::never);
|
|
}
|
|
}
|
|
break;
|
|
|
|
/* Sprites */
|
|
case 0x20/2: m_sprite_base_addr = data << 2; verboselog("maincpu", machine(), 0, "sprite_base_addr = %04x\n", data); break;
|
|
case 0x22/2: m_sprite_count = data+1; verboselog("maincpu", machine(), 0, "sprite_count = %d\n", data+1); break;
|
|
case 0x26/2: m_sprite_flags = data; verboselog("maincpu", machine(), 0, "sprite_flags = %04x\n", data); break;
|
|
|
|
/* Tilemap 0 */
|
|
case 0x100/2: m_tilemap_flags[0] = data; verboselog("maincpu", machine(), 3, "tilemap_flags[0] = %04x\n", data); break;
|
|
case 0x104/2: m_tilemap_scrollx[0] = data; verboselog("maincpu", machine(), 3, "tilemap_scrollx[0] = %04x\n", data); break;
|
|
case 0x106/2: m_tilemap_scrolly[0] = data; verboselog("maincpu", machine(), 3, "tilemap_scrolly[0] = %04x\n", data); break;
|
|
case 0x108/2: m_tilemap_base_addr[0] = (data) << 1; verboselog("maincpu", machine(), 3, "tilemap_base_addr[0] = %05x\n", data << 2); break;
|
|
case 0x10a/2: m_tilemap_mode[0] = data; verboselog("maincpu", machine(), 3, "tilemap_mode[0] = %04x\n", data); break;
|
|
|
|
/* Tilemap 1 */
|
|
case 0x120/2: m_tilemap_flags[1] = data; verboselog("maincpu", machine(), 3, "tilemap_flags[1] = %04x\n", data); break;
|
|
case 0x124/2: m_tilemap_scrollx[1] = data; verboselog("maincpu", machine(), 3, "tilemap_scrollx[1] = %04x\n", data); break;
|
|
case 0x126/2: m_tilemap_scrolly[1] = data; verboselog("maincpu", machine(), 3, "tilemap_scrolly[1] = %04x\n", data); break;
|
|
case 0x128/2: m_tilemap_base_addr[1] = (data) << 1; verboselog("maincpu", machine(), 3, "tilemap_base_addr[1] = %05x\n", data << 2); break;
|
|
case 0x12a/2: m_tilemap_mode[1] = data; verboselog("maincpu", machine(), 3, "tilemap_mode[1] = %04x\n", data); break;
|
|
|
|
/* Tilemap 2? */
|
|
case 0x140/2: m_tilemap_flags[2] = data; verboselog("maincpu", machine(), 0, "tilemap_flags[2] = %04x\n", data); break;
|
|
case 0x144/2: m_tilemap_scrollx[2] = data; verboselog("maincpu", machine(), 0, "tilemap_scrollx[2] = %04x\n", data); break;
|
|
case 0x146/2: m_tilemap_scrolly[2] = data; verboselog("maincpu", machine(), 0, "tilemap_scrolly[2] = %04x\n", data); break;
|
|
case 0x148/2: m_tilemap_base_addr[2] = (data) << 1; verboselog("maincpu", machine(), 0, "tilemap_base_addr[2] = %05x\n", data << 2); break;
|
|
case 0x14a/2: m_tilemap_mode[2] = data; verboselog("maincpu", machine(), 0, "tilemap_mode[2] = %04x\n", data); break;
|
|
|
|
/* ROZ */
|
|
case 0x180/2: m_roz_mode = data; verboselog("maincpu", machine(), 3, "roz_mode = %04x\n", data); break;
|
|
case 0x184/2: m_roz_scrollx = (data << 16) | (m_roz_scrollx & 0xffff); m_roz_changed |= 1; verboselog("maincpu", machine(), 3, "roz_scrollx = %08x\n", m_roz_scrollx); break;
|
|
case 0x186/2: m_roz_scrollx = (data) | (m_roz_scrollx & 0xffff0000); m_roz_changed |= 1; verboselog("maincpu", machine(), 3, "roz_scrollx = %08x\n", m_roz_scrollx); break;
|
|
case 0x188/2: m_roz_scrolly = (data << 16) | (m_roz_scrolly & 0xffff); m_roz_changed |= 2; verboselog("maincpu", machine(), 3, "roz_scrolly = %08x\n", m_roz_scrolly); break;
|
|
case 0x18a/2: m_roz_scrolly = (data) | (m_roz_scrolly & 0xffff0000); m_roz_changed |= 2; verboselog("maincpu", machine(), 3, "roz_scrolly = %08x\n", m_roz_scrolly); break;
|
|
case 0x18c/2: m_roz_coeffa = data; verboselog("maincpu", machine(), 3, "roz_coeffa = %04x\n", data); break;
|
|
case 0x18e/2: m_roz_coeffb = data; verboselog("maincpu", machine(), 3, "roz_coeffb = %04x\n", data); break;
|
|
case 0x190/2: m_roz_coeffc = data; verboselog("maincpu", machine(), 3, "roz_coeffc = %04x\n", data); break;
|
|
case 0x192/2: m_roz_coeffd = data; verboselog("maincpu", machine(), 3, "roz_coeffd = %04x\n", data); break;
|
|
case 0x194/2: m_roz_base_addr = (data) << 1; verboselog("maincpu", machine(), 3, "roz_base_addr = %05x\n", data << 2); break;
|
|
case 0x196/2: m_roz_tile_bank = data; verboselog("maincpu", machine(), 3, "roz_tile_bank = %04x\n", data); break; //tile bank
|
|
case 0x198/2: m_roz_unk_base0 = data << 2; verboselog("maincpu", machine(), 3, "roz_unk_base0 = %05x\n", data << 2); break;
|
|
case 0x19a/2: m_roz_unk_base1 = data << 2; verboselog("maincpu", machine(), 3, "roz_unk_base1 = %05x\n", data << 2); break;
|
|
case 0x19e/2: m_roz_unk_base2 = data << 2; verboselog("maincpu", machine(), 3, "roz_unk_base2 = %05x\n", data << 2); break;
|
|
|
|
case 0x1d0/2: m_unk_1d0 = data; verboselog("maincpu", machine(), 3, "unk_1d0 = %04x\n", data); break;
|
|
|
|
|
|
|
|
|
|
case 0x1f0/2: //FIXME: this register is mostly not understood
|
|
m_irq_mask = data;//(data & 8) ? 0 : 1;
|
|
#if 0
|
|
if(!m_irq_mask && !m_hbl_mask)
|
|
{
|
|
m_maincpu->set_input_line(7, CLEAR_LINE);
|
|
}
|
|
#endif
|
|
verboselog("maincpu", machine(), 3, "irq_mask = %04x\n", data);
|
|
break;
|
|
default:
|
|
verboselog("maincpu", machine(), 0, "supracan_video_w: Unknown register: %08x = %04x & %04x\n", 0xf00000 + (offset << 1), data, mem_mask);
|
|
break;
|
|
}
|
|
m_video_regs[offset] = data;
|
|
}
|
|
|
|
|
|
static DEVICE_IMAGE_LOAD( supracan_cart )
|
|
{
|
|
UINT8 *cart = image.device().machine().root_device().memregion("cart")->base();
|
|
UINT32 size = 0;
|
|
|
|
if (image.software_entry() == NULL)
|
|
{
|
|
size = image.length();
|
|
|
|
if (size > 0x400000)
|
|
{
|
|
image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unsupported cartridge size");
|
|
return IMAGE_INIT_FAIL;
|
|
}
|
|
|
|
if (image.fread(cart, size) != size)
|
|
{
|
|
image.seterror(IMAGE_ERROR_UNSPECIFIED, "Unable to fully read from file");
|
|
return IMAGE_INIT_FAIL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
size = image.get_software_region_length("rom");
|
|
memcpy(cart, image.get_software_region("rom"), size);
|
|
}
|
|
|
|
return IMAGE_INIT_PASS;
|
|
}
|
|
|
|
|
|
void supracan_state::machine_start()
|
|
{
|
|
|
|
m_video_timer = machine().scheduler().timer_alloc(FUNC(supracan_video_callback));
|
|
m_hbl_timer = machine().scheduler().timer_alloc(FUNC(supracan_hbl_callback));
|
|
m_line_on_timer = machine().scheduler().timer_alloc(FUNC(supracan_line_on_callback));
|
|
m_line_off_timer = machine().scheduler().timer_alloc(FUNC(supracan_line_off_callback));
|
|
}
|
|
|
|
|
|
void supracan_state::machine_reset()
|
|
{
|
|
|
|
machine().device("soundcpu")->execute().set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
|
|
|
|
m_video_timer->adjust( machine().primary_screen->time_until_pos( 0, 0 ) );
|
|
m_irq_mask = 0;
|
|
}
|
|
|
|
/* gfxdecode is retained for reference purposes but not otherwise used by the driver */
|
|
static const gfx_layout supracan_gfx8bpp =
|
|
{
|
|
8,8,
|
|
RGN_FRAC(1,1),
|
|
8,
|
|
{ 0,1,2,3,4,5,6,7 },
|
|
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
|
|
{ STEP8(0,8*8) },
|
|
8*8*8
|
|
};
|
|
|
|
|
|
|
|
static const gfx_layout supracan_gfx4bpp =
|
|
{
|
|
8,8,
|
|
RGN_FRAC(1,1),
|
|
4,
|
|
{ 0,1,2,3 },
|
|
{ 0*4, 1*4, 2*4, 3*4, 4*4, 5*4, 6*4, 7*4 },
|
|
{ 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32 },
|
|
8*32
|
|
};
|
|
|
|
static const gfx_layout supracan_gfx2bpp =
|
|
{
|
|
8,8,
|
|
RGN_FRAC(1,1),
|
|
2,
|
|
{ 0,1 },
|
|
{ 0*2, 1*2, 2*2, 3*2, 4*2, 5*2, 6*2, 7*2 },
|
|
{ 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16 },
|
|
8*16
|
|
};
|
|
|
|
|
|
static const UINT32 xtexlayout_xoffset[64] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,
|
|
24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,
|
|
45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63 };
|
|
|
|
static const UINT32 xtexlayout_yoffset[64] = { 0*64,1*64,2*64,3*64,4*64,5*64,6*64,7*64,8*64,
|
|
9*64,10*64,11*64,12*64,13*64,14*64,15*64,
|
|
16*64,17*64,18*64,19*64,20*64,21*64,22*64,23*64,
|
|
24*64,25*64,26*64,27*64,28*64,29*64,30*64,31*64,
|
|
32*64,33*64,34*64,35*64,36*64,37*64,38*64,39*64,
|
|
40*64,41*64,42*64,43*64,44*64,45*64,46*64,47*64,
|
|
48*64,49*64,50*64,51*64,52*64,53*64,54*64,55*64,
|
|
56*64,57*64,58*64,59*64,60*64,61*64,62*64,63*64 };
|
|
static const gfx_layout supracan_gfx1bpp =
|
|
{
|
|
64,64,
|
|
RGN_FRAC(1,1),
|
|
1,
|
|
{ 0 },
|
|
EXTENDED_XOFFS,
|
|
EXTENDED_YOFFS,
|
|
64*64,
|
|
xtexlayout_xoffset,
|
|
xtexlayout_yoffset
|
|
};
|
|
|
|
static const gfx_layout supracan_gfx1bpp_alt =
|
|
{
|
|
8,8,
|
|
RGN_FRAC(1,1),
|
|
1,
|
|
{ 0 },
|
|
{ 0,1,2,3,4,5,6,7 },
|
|
{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 },
|
|
8*8
|
|
};
|
|
|
|
|
|
static GFXDECODE_START( supracan )
|
|
GFXDECODE_ENTRY( "ram_gfx2", 0, supracan_gfx8bpp, 0, 1 )
|
|
GFXDECODE_ENTRY( "ram_gfx2", 0, supracan_gfx4bpp, 0, 0x10 )
|
|
GFXDECODE_ENTRY( "ram_gfx2", 0, supracan_gfx2bpp, 0, 0x40 )
|
|
GFXDECODE_ENTRY( "ram_gfx2", 0, supracan_gfx1bpp, 0, 0x80 )
|
|
GFXDECODE_ENTRY( "ram_gfx3", 0, supracan_gfx1bpp_alt, 0, 0x80 )
|
|
GFXDECODE_END
|
|
|
|
INTERRUPT_GEN_MEMBER(supracan_state::supracan_irq)
|
|
{
|
|
#if 0
|
|
|
|
if(m_irq_mask)
|
|
{
|
|
device.execute().set_input_line(7, HOLD_LINE);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
INTERRUPT_GEN_MEMBER(supracan_state::supracan_sound_irq)
|
|
{
|
|
|
|
m_sound_irq_source_reg |= 0x80;
|
|
|
|
if(m_sound_irq_enable_reg & m_sound_irq_source_reg)
|
|
{
|
|
machine().device("soundcpu")->execute().set_input_line(0, ASSERT_LINE);
|
|
}
|
|
else
|
|
{
|
|
machine().device("soundcpu")->execute().set_input_line(0, CLEAR_LINE);
|
|
}
|
|
}
|
|
|
|
static MACHINE_CONFIG_START( supracan, supracan_state )
|
|
|
|
MCFG_CPU_ADD( "maincpu", M68000, XTAL_10_738635MHz ) /* Correct frequency unknown */
|
|
MCFG_CPU_PROGRAM_MAP( supracan_mem )
|
|
MCFG_CPU_VBLANK_INT_DRIVER("screen", supracan_state, supracan_irq)
|
|
|
|
MCFG_CPU_ADD( "soundcpu", M6502, XTAL_3_579545MHz ) /* TODO: Verify actual clock */
|
|
MCFG_CPU_PROGRAM_MAP( supracan_sound_mem )
|
|
MCFG_CPU_VBLANK_INT_DRIVER("screen", supracan_state, supracan_sound_irq)
|
|
|
|
#if !(SOUNDCPU_BOOT_HACK)
|
|
MCFG_QUANTUM_PERFECT_CPU("maincpu")
|
|
MCFG_QUANTUM_PERFECT_CPU("soundcpu")
|
|
#endif
|
|
|
|
|
|
MCFG_SCREEN_ADD( "screen", RASTER )
|
|
MCFG_SCREEN_RAW_PARAMS(XTAL_10_738635MHz/2, 348, 0, 256, 256, 0, 240 ) /* No idea if this is correct */
|
|
MCFG_SCREEN_UPDATE_DRIVER(supracan_state, screen_update_supracan)
|
|
MCFG_PALETTE_LENGTH( 32768 )
|
|
MCFG_GFXDECODE(supracan)
|
|
|
|
MCFG_CARTSLOT_ADD("cart")
|
|
MCFG_CARTSLOT_EXTENSION_LIST("bin")
|
|
MCFG_CARTSLOT_INTERFACE("supracan_cart")
|
|
MCFG_CARTSLOT_LOAD(supracan_cart)
|
|
|
|
MCFG_SOFTWARE_LIST_ADD("cart_list","supracan")
|
|
MACHINE_CONFIG_END
|
|
|
|
|
|
ROM_START( supracan )
|
|
ROM_REGION( 0x400000, "cart", ROMREGION_ERASEFF )
|
|
ROM_REGION( 0x20000, "ram_gfx", ROMREGION_ERASEFF )
|
|
ROM_REGION( 0x20000, "ram_gfx2", ROMREGION_ERASEFF )
|
|
ROM_REGION( 0x20000, "ram_gfx3", ROMREGION_ERASEFF )
|
|
ROM_END
|
|
|
|
|
|
/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */
|
|
CONS( 1995, supracan, 0, 0, supracan, supracan, driver_device, 0, "Funtech Entertainment", "Super A'Can", GAME_NO_SOUND | GAME_IMPERFECT_GRAPHICS | GAME_NOT_WORKING )
|