summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/drivers/supracan.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/drivers/supracan.cpp')
-rw-r--r--src/mame/drivers/supracan.cpp2153
1 files changed, 0 insertions, 2153 deletions
diff --git a/src/mame/drivers/supracan.cpp b/src/mame/drivers/supracan.cpp
deleted file mode 100644
index 524cfa70056..00000000000
--- a/src/mame/drivers/supracan.cpp
+++ /dev/null
@@ -1,2153 +0,0 @@
-// license:LGPL-2.1+
-// copyright-holders:Angelo Salese,Ryan Holtz
-/***************************************************************************
-
-
- Funtech Super A'Can
- -------------------
-
- Preliminary driver by Angelo Salese
- Improvements by Ryan Holtz
-
-
-*******************************************************************************
-
-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 chip is completely custom, and partially implemented.
-
- 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 used for DMA-driven sample playback. Register 0x16 may contain which DMA-driven samples are active.
- 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 IRQ request from 68k, flags data available in shared-RAM mailbox
- 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 "bus/generic/slot.h"
-#include "bus/generic/carts.h"
-#include "audio/acan.h"
-#include "emupal.h"
-#include "screen.h"
-#include "softlist.h"
-#include "speaker.h"
-#include "tilemap.h"
-
-
-namespace {
-
-#define DRAW_DEBUG_ROZ (0)
-
-#define DRAW_DEBUG_UNK_SPRITE (0)
-
-#define DEBUG_PRIORITY (0)
-#define DEBUG_PRIORITY_INDEX (0) // 0-3
-
-#define LOG_UNKNOWNS (1 << 0)
-#define LOG_DMA (1 << 1)
-#define LOG_SPRDMA (1 << 2)
-#define LOG_SPRITES (1 << 3)
-#define LOG_TILEMAP0 (1 << 4)
-#define LOG_TILEMAP1 (1 << 5)
-#define LOG_TILEMAP2 (1 << 6)
-#define LOG_ROZ (1 << 7)
-#define LOG_HFVIDEO (1 << 8)
-#define LOG_IRQS (1 << 9)
-#define LOG_SOUND (1 << 10)
-#define LOG_HFUNKNOWNS (1 << 11)
-#define LOG_68K_SOUND (1 << 12)
-#define LOG_CONTROLS (1 << 13)
-#define LOG_VIDEO (LOG_SPRDMA | LOG_SPRITES | LOG_TILEMAP0 | LOG_TILEMAP1 | LOG_TILEMAP2 | LOG_ROZ)
-#define LOG_ALL (LOG_UNKNOWNS | LOG_HFUNKNOWNS | LOG_DMA | LOG_VIDEO | LOG_HFVIDEO | LOG_IRQS | LOG_SOUND | LOG_68K_SOUND | LOG_CONTROLS)
-#define LOG_DEFAULT (LOG_ALL & ~(LOG_HFVIDEO | LOG_HFUNKNOWNS))
-
-#define VERBOSE (LOG_UNKNOWNS | LOG_SOUND | LOG_DMA)
-#include "logmacro.h"
-
-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_soundcpu(*this, "soundcpu")
- , m_cart(*this, "cartslot")
- , m_vram(*this, "vram")
- , m_soundram(*this, "soundram")
- , m_sound(*this, "acansnd")
- , m_gfxdecode(*this, "gfxdecode")
- , m_screen(*this, "screen")
- , m_pads(*this, "P%u", 1U)
- {
- }
-
- void supracan(machine_config &config);
-
-protected:
- virtual void machine_start() override;
- virtual void machine_reset() override;
- virtual void video_start() override;
-
-private:
- void supracan_mem(address_map &map);
- void supracan_sound_mem(address_map &map);
-
- uint16_t _68k_soundram_r(offs_t offset, uint16_t mem_mask = ~0);
- void _68k_soundram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
- uint8_t _6502_soundmem_r(offs_t offset);
- void _6502_soundmem_w(offs_t offset, uint8_t data);
-
- void dma_w(int offset, uint16_t data, uint16_t mem_mask, int ch);
- void dma_channel0_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
- void dma_channel1_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
-
- uint16_t sound_r(offs_t offset, uint16_t mem_mask = 0);
- void sound_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
- uint16_t video_r(offs_t offset, uint16_t mem_mask = 0);
- void video_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
- void vram_w(offs_t offset, uint16_t data, uint16_t mem_mask = ~0);
-
- uint8_t sound_ram_read(offs_t offset);
-
- struct dma_regs_t
- {
- uint32_t source[2];
- uint32_t dest[2];
- uint16_t count[2];
- uint16_t control[2];
- };
-
- struct sprdma_regs_t
- {
- uint32_t src;
- uint16_t src_inc;
- uint32_t dst;
- uint16_t dst_inc;
- uint16_t count;
- uint16_t control;
- };
-
- required_device<cpu_device> m_maincpu;
- required_device<cpu_device> m_soundcpu;
- required_device<generic_slot_device> m_cart;
-
- required_shared_ptr<uint16_t> m_vram;
- required_shared_ptr<uint8_t> m_soundram;
- required_device<acan_sound_device> m_sound;
-
- required_device<gfxdecode_device> m_gfxdecode;
- required_device<screen_device> m_screen;
-
- required_ioport_array<2> m_pads;
-
- dma_regs_t m_dma_regs;
- sprdma_regs_t m_sprdma_regs;
-
- uint16_t m_sound_cpu_ctrl;
- uint8_t m_soundcpu_irq_enable;
- uint8_t m_soundcpu_irq_source;
- uint8_t m_sound_cpu_shift_ctrl;
- uint8_t m_sound_cpu_shift_regs[2];
- uint16_t m_latched_controls[2];
- uint8_t m_sound_status;
- uint8_t m_sound_reg_addr;
-
- emu_timer *m_video_timer;
- emu_timer *m_hbl_timer;
- emu_timer *m_line_on_timer;
- emu_timer *m_line_off_timer;
-
- std::vector<uint8_t> m_vram_addr_swapped;
-
-#if 0
- uint16_t *m_pram;
-#endif
-
- uint16_t m_sprite_count;
- uint32_t m_sprite_base_addr;
- uint8_t m_sprite_flags;
-
- uint32_t m_tilemap_base_addr[3];
- int m_tilemap_scrollx[3];
- int m_tilemap_scrolly[3];
- uint16_t m_video_flags;
- uint16_t m_tilemap_flags[3];
- uint16_t m_tilemap_mode[3];
- uint16_t m_irq_mask;
-#if 0
- uint16_t m_hbl_mask;
-#endif
-
- uint32_t m_roz_base_addr;
- uint16_t m_roz_mode;
- uint32_t m_roz_scrollx;
- uint32_t m_roz_scrolly;
- uint16_t m_roz_tile_bank;
- uint32_t m_roz_unk_base0;
- uint32_t m_roz_unk_base1;
- uint32_t m_roz_unk_base2;
- uint16_t m_roz_coeffa;
- uint16_t m_roz_coeffb;
- uint16_t m_roz_coeffc;
- uint16_t m_roz_coeffd;
- int32_t m_roz_changed;
- uint16_t m_unk_1d0;
-
- uint16_t m_video_regs[256];
-
- tilemap_t *m_tilemap_sizes[4][4];
- bitmap_ind16 m_sprite_final_bitmap;
- bitmap_ind8 m_sprite_mask_bitmap;
- bitmap_ind8 m_prio_bitmap;
-
- void write_swapped_byte(int offset, uint8_t byte);
- TILE_GET_INFO_MEMBER(get_tilemap0_tile_info);
- TILE_GET_INFO_MEMBER(get_tilemap1_tile_info);
- TILE_GET_INFO_MEMBER(get_tilemap2_tile_info);
- TILE_GET_INFO_MEMBER(get_roz_tile_info);
- void palette_init(palette_device &palette) const;
- void sound_timer_irq(int state);
- void sound_dma_irq(int state);
- uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
- TIMER_CALLBACK_MEMBER(hbl_callback);
- TIMER_CALLBACK_MEMBER(line_on_callback);
- TIMER_CALLBACK_MEMBER(line_off_callback);
- TIMER_CALLBACK_MEMBER(video_callback);
- DECLARE_DEVICE_IMAGE_LOAD_MEMBER(cart_load);
- int get_tilemap_region(int layer);
- void get_tilemap_info_common(int layer, tile_data &tileinfo, int count);
- void get_roz_tilemap_info(int layer, tile_data &tileinfo, int count);
- int get_tilemap_dimensions(int &xsize, int &ysize, int layer);
- void draw_sprite_tile(bitmap_ind16 &dst, bitmap_ind8 &priomap, const rectangle &cliprect, gfx_element *gfx, int tile, int palette, bool xflip, bool yflip, int dstx, int dsty, int prio);
- void draw_sprite_tile_mask(bitmap_ind8 &dst, const rectangle &cliprect, gfx_element *gfx, int tile, bool xflip, bool yflip, int dstx, int dsty);
- void draw_sprite_tile_masked(bitmap_ind16 &dst, bitmap_ind8 &mask, bitmap_ind8 &priomap, const rectangle &cliprect, gfx_element *gfx, int tile, int palette, bool xflip, bool yflip, int dstx, int dsty, int prio);
- void draw_sprites(bitmap_ind16 &bitmap, bitmap_ind8 &maskmap, bitmap_ind8 &priomap, const rectangle &cliprect);
- void mark_active_tilemap_all_dirty(int layer);
- void draw_roz_layer(bitmap_ind16 &bitmap, const rectangle &cliprect, tilemap_t *tmap, uint32_t startx, uint32_t starty, int incxx, int incxy, int incyx, int incyy, int wraparound/*, int columnscroll, uint32_t* scrollram*/, int transmask);
-
- void set_sound_irq(uint8_t bit, uint8_t state);
-};
-
-
-int supracan_state::get_tilemap_region(int layer)
-{
- // HACK!!!
- if (layer == 2)
- {
- return 2;
- }
-
- if (layer == 3)
- {
- // roz layer
- static const int s_roz_mode_lut[4] = { 4, 2, 1, 0 };
- return s_roz_mode_lut[m_roz_mode & 3];
- }
- else
- {
- // normal layers
- if ((m_tilemap_mode[layer] & 0x7000) == 0x7000)
- {
- return 2;
- }
- return 1;
- }
-
-}
-
-void supracan_state::get_tilemap_info_common(int layer, tile_data &tileinfo, int count)
-{
- uint16_t* supracan_vram = m_vram;
-
- uint32_t base = m_tilemap_base_addr[layer];
- int gfx_mode = (m_tilemap_mode[layer] & 0x7000) >> 12;
- int region = get_tilemap_region(layer);
-
- count += base;
-
- uint16_t tile_bank = 0;
- uint16_t palette_bank = 0;
- switch (gfx_mode)
- {
- case 7:
- tile_bank = 0x1c00;
- palette_bank = 0x00;
- break;
-
- case 6: // gambling lord
- tile_bank = 0x0c00;
- 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:
- LOGMASKED(LOG_UNKNOWNS, "Unsupported tilemap mode: %d\n", (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;
-
- tileinfo.set(region, tile, palette, TILE_FLIPXY(flipxy));
-}
-
-// I wonder how different this really is.. my guess, not at all.
-void supracan_state::get_roz_tilemap_info(int layer, tile_data &tileinfo, int count)
-{
- uint16_t* supracan_vram = m_vram;
-
- uint32_t base = m_roz_base_addr;
-
- int region = 1;
- uint16_t tile_bank = 0;
- uint16_t palette_bank = 0;
-
- region = get_tilemap_region(layer);
-
- switch (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;
-
- tileinfo.set(region, tile, 0, 0);
- return;
- }
-
- case 1:
- tile_bank = (m_roz_tile_bank & 0xf000) >> 3;
- break;
-
- case 2:
- tile_bank = (m_roz_tile_bank & 0xf000) >> 3;
- break;
-
- case 3:
- tile_bank = (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;
-
- tileinfo.set(region, tile, palette, TILE_FLIPXY(flipxy));
-}
-
-
-
-TILE_GET_INFO_MEMBER(supracan_state::get_tilemap0_tile_info)
-{
- get_tilemap_info_common(0, tileinfo, tile_index);
-}
-
-TILE_GET_INFO_MEMBER(supracan_state::get_tilemap1_tile_info)
-{
- get_tilemap_info_common(1, tileinfo, tile_index);
-}
-
-TILE_GET_INFO_MEMBER(supracan_state::get_tilemap2_tile_info)
-{
- get_tilemap_info_common(2, tileinfo, tile_index);
-}
-
-TILE_GET_INFO_MEMBER(supracan_state::get_roz_tile_info)
-{
- get_roz_tilemap_info(3, tileinfo, tile_index);
-}
-
-
-void supracan_state::video_start()
-{
- m_sprite_final_bitmap.allocate(1024, 1024, BITMAP_FORMAT_IND16);
- m_sprite_mask_bitmap.allocate(1024, 1024, BITMAP_FORMAT_IND8);
- m_prio_bitmap.allocate(1024, 1024, BITMAP_FORMAT_IND8);
-
- m_vram_addr_swapped.resize(0x20000); // hack for 1bpp layer at startup
- m_gfxdecode->gfx(4)->set_source(&m_vram_addr_swapped[0]);
- m_gfxdecode->gfx(4)->set_xormask(0);
-
- m_tilemap_sizes[0][0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(supracan_state::get_tilemap0_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
- m_tilemap_sizes[0][1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(supracan_state::get_tilemap0_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
- m_tilemap_sizes[0][2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(supracan_state::get_tilemap0_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 128, 32);
- m_tilemap_sizes[0][3] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(supracan_state::get_tilemap0_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64);
-
- m_tilemap_sizes[1][0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(supracan_state::get_tilemap1_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
- m_tilemap_sizes[1][1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(supracan_state::get_tilemap1_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
- m_tilemap_sizes[1][2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(supracan_state::get_tilemap1_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 128, 32);
- m_tilemap_sizes[1][3] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(supracan_state::get_tilemap1_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64);
-
- m_tilemap_sizes[2][0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(supracan_state::get_tilemap2_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
- m_tilemap_sizes[2][1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(supracan_state::get_tilemap2_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
- m_tilemap_sizes[2][2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(supracan_state::get_tilemap2_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 128, 32);
- m_tilemap_sizes[2][3] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(supracan_state::get_tilemap2_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64);
-
- m_tilemap_sizes[3][0] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(supracan_state::get_roz_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 32, 32);
- m_tilemap_sizes[3][1] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(supracan_state::get_roz_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 32);
- m_tilemap_sizes[3][2] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(supracan_state::get_roz_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 128, 32);
- m_tilemap_sizes[3][3] = &machine().tilemap().create(*m_gfxdecode, tilemap_get_info_delegate(*this, FUNC(supracan_state::get_roz_tile_info)), TILEMAP_SCAN_ROWS, 8, 8, 64, 64);
-}
-
-int supracan_state::get_tilemap_dimensions(int &xsize, int &ysize, int layer)
-{
- xsize = 32;
- ysize = 32;
-
- int select;
- if (layer == 3)
- select = m_roz_mode & 0x0f00;
- else
- select = 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:
- LOGMASKED(LOG_HFUNKNOWNS, "Unsupported tilemap size for layer %d: %04x\n", layer, select);
- return 0;
- }
-}
-
-void supracan_state::draw_sprite_tile(bitmap_ind16 &dst, bitmap_ind8 &priomap, const rectangle &cliprect, gfx_element *gfx, int tile, int palette,
- bool xflip, bool yflip, int dstx, int dsty, int prio)
-{
- // compute final pixel in X and exit if we are entirely clipped
- int dstendx = dstx + 7;
- if (dstx > cliprect.right() || dstendx < cliprect.left())
- return;
-
- // apply left clip
- int srcx = 0;
- if (dstx < cliprect.left())
- {
- srcx = cliprect.left() - dstx;
- dstx = cliprect.left();
- }
-
- // apply right clip
- if (dstendx > cliprect.right())
- dstendx = cliprect.right();
-
- // compute final pixel in Y and exit if we are entirely clipped
- int dstendy = dsty + 7;
- if (dsty > cliprect.bottom() || dstendy < cliprect.top())
- return;
-
- // apply top clip
- int srcy = 0;
- if (dsty < cliprect.top())
- {
- srcy = cliprect.top() - dsty;
- dsty = cliprect.top();
- }
-
- // apply bottom clip
- if (dstendy > cliprect.bottom())
- dstendy = cliprect.bottom();
-
- // apply X flipping
- int dx = 1;
- if (xflip)
- {
- srcx = 7 - srcx;
- dx = -dx;
- }
-
- // apply Y flipping
- int dy = gfx->rowbytes();
- if (yflip)
- {
- srcy = 7 - srcy;
- dy = -dy;
- }
-
- const int color = gfx->colorbase() + gfx->granularity() * (palette % gfx->colors());
- const uint8_t *src_data = &gfx->get_data(tile % gfx->elements())[srcy * gfx->rowbytes()];
- for (int y = dsty; y <= dstendy; y++)
- {
- const uint8_t *srcp = &src_data[srcx];
- uint8_t *priop = &priomap.pix(y, dstx);
- uint16_t *dstp = &dst.pix(y, dstx);
- for (int x = dstx; x <= dstendx; x++)
- {
- const uint32_t srcdata = *srcp;
- if (srcdata != 0)
- {
- *dstp = (uint16_t)(srcdata + color);
- *priop = (*priop & 0xf0) | (uint8_t)prio;
- }
- srcp += dx;
- priop++;
- dstp++;
- }
- src_data += dy;
- }
-}
-
-void supracan_state::draw_sprite_tile_mask(bitmap_ind8 &dst, const rectangle &cliprect, gfx_element *gfx, int tile, bool xflip, bool yflip, int dstx, int dsty)
-{
- // compute final pixel in X and exit if we are entirely clipped
- int dstendx = dstx + 7;
- if (dstx > cliprect.right() || dstendx < cliprect.left())
- return;
-
- // apply left clip
- int srcx = 0;
- if (dstx < cliprect.left())
- {
- srcx = cliprect.left() - dstx;
- dstx = cliprect.left();
- }
-
- // apply right clip
- if (dstendx > cliprect.right())
- dstendx = cliprect.right();
-
- // compute final pixel in Y and exit if we are entirely clipped
- int dstendy = dsty + 7;
- if (dsty > cliprect.bottom() || dstendy < cliprect.top())
- return;
-
- // apply top clip
- int srcy = 0;
- if (dsty < cliprect.top())
- {
- srcy = cliprect.top() - dsty;
- dsty = cliprect.top();
- }
-
- // apply bottom clip
- if (dstendy > cliprect.bottom())
- dstendy = cliprect.bottom();
-
- // apply X flipping
- int dx = 1;
- if (xflip)
- {
- srcx = 7 - srcx;
- dx = -dx;
- }
-
- // apply Y flipping
- int dy = gfx->rowbytes();
- if (yflip)
- {
- srcy = 7 - srcy;
- dy = -dy;
- }
-
- const uint8_t *src_data = &gfx->get_data(tile % gfx->elements())[srcy * gfx->rowbytes()];
- for (int y = dsty; y <= dstendy; y++)
- {
- const uint8_t *srcp = &src_data[srcx];
- uint8_t *dstp = &dst.pix(y, dstx);
- for (int x = dstx; x <= dstendx; x++)
- {
- if (*srcp)
- *dstp = 1;
- srcp += dx;
- dstp++;
- }
- src_data += dy;
- }
-}
-
-void supracan_state::draw_sprite_tile_masked(bitmap_ind16 &dst, bitmap_ind8 &mask, bitmap_ind8 &priomap, const rectangle &cliprect, gfx_element *gfx, int tile,
- int palette, bool xflip, bool yflip, int dstx, int dsty, int prio)
-{
- // compute final pixel in X and exit if we are entirely clipped
- int dstendx = dstx + 7;
- if (dstx > cliprect.right() || dstendx < cliprect.left())
- return;
-
- // apply left clip
- int srcx = 0;
- if (dstx < cliprect.left())
- {
- srcx = cliprect.left() - dstx;
- dstx = cliprect.left();
- }
-
- // apply right clip
- if (dstendx > cliprect.right())
- dstendx = cliprect.right();
-
- // compute final pixel in Y and exit if we are entirely clipped
- int dstendy = dsty + 7;
- if (dsty > cliprect.bottom() || dstendy < cliprect.top())
- return;
-
- // apply top clip
- int srcy = 0;
- if (dsty < cliprect.top())
- {
- srcy = cliprect.top() - dsty;
- dsty = cliprect.top();
- }
-
- // apply bottom clip
- if (dstendy > cliprect.bottom())
- dstendy = cliprect.bottom();
-
- // apply X flipping
- int dx = 1;
- if (xflip)
- {
- srcx = 7 - srcx;
- dx = -dx;
- }
-
- // apply Y flipping
- int dy = gfx->rowbytes();
- if (yflip)
- {
- srcy = 7 - srcy;
- dy = -dy;
- }
-
- const int color = gfx->colorbase() + gfx->granularity() * (palette % gfx->colors());
- const uint8_t *src_data = &gfx->get_data(tile % gfx->elements())[srcy * gfx->rowbytes()];
- for (int y = dsty; y <= dstendy; y++)
- {
- const uint8_t *srcp = &src_data[srcx];
- uint16_t *dstp = &dst.pix(y, dstx);
- uint8_t *priop = &priomap.pix(y, dstx);
- uint8_t *maskp = &mask.pix(y, dstx);
- for (int x = dstx; x <= dstendx; x++)
- {
- const uint32_t srcdata = *srcp;
- if (srcdata != 0 && *maskp != 0)
- {
- *dstp = (uint16_t)(srcdata + color);
- *priop = (*priop & 0xf0) | (uint8_t)prio;
- }
- srcp += dx;
- dstp++;
- priop++;
- maskp++;
- }
- src_data += dy;
- }
-}
-
-void supracan_state::draw_sprites(bitmap_ind16 &bitmap, bitmap_ind8 &maskmap, bitmap_ind8 &priomap, const rectangle &cliprect)
-{
- uint16_t *supracan_vram = 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]
-// zzz- ---- ---- ---- X scale
-// ---- ???- ---- ---- Unknown, but often written.
-// Values include 111 and 110 for the Super A'Can logo, 110 in the Sango Fighter intro, and 101/100 in the Boom Zoo intro.
-// ---- ---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_t skip_count = 0;
- uint32_t start_word = (m_sprite_base_addr >> 1) + skip_count * 4;
- uint32_t end_word = start_word + (m_sprite_count - skip_count) * 4;
- int region = (m_sprite_flags & 1) ? 0 : 1; // 8bpp : 4bpp
-
- static const uint16_t 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 prio = (supracan_vram[i + 2] >> 9) & 3;
- //int xscale = supracan_vram[i + 2] >> 13;
- gfx_element *gfx = m_gfxdecode->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_t 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] );
-
- if (mask > 1)
- draw_sprite_tile_mask(maskmap, cliprect, gfx, tile, sprite_xflip, sprite_yflip, x, y);
- else if (mask == 1)
- draw_sprite_tile_masked(bitmap, maskmap, priomap, cliprect, gfx, tile, palette, sprite_xflip, sprite_yflip, x, y, prio);
- else
- draw_sprite_tile(bitmap, priomap, cliprect, gfx, tile, palette, sprite_xflip, sprite_yflip, x, y, prio);
- }
- 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_t data = supracan_vram[(sprite_offset + ytile * xsize + xtile) & VRAM_MASK];
- int tile = (bank * 0x200) + (data & 0x03ff);
- int palette = (data & 0xf000) >> 12;
-
- int xpos = sprite_xflip ? (x - (xtile + 1) * 8 + xsize * 8) : (x + xtile * 8);
- int ypos = sprite_yflip ? (y - (ytile + 1) * 8 + ysize * 8) : (y + ytile * 8);
-
- int tile_xflip = sprite_xflip ^ ((data & 0x0800) >> 11);
- int tile_yflip = sprite_yflip ^ ((data & 0x0400) >> 10);
-
- if (mask > 1)
- draw_sprite_tile_mask(maskmap, cliprect, gfx, tile, tile_xflip, tile_yflip, xpos, ypos);
- else if (mask == 1)
- draw_sprite_tile_masked(bitmap, maskmap, priomap, cliprect, gfx, tile, palette, tile_xflip, tile_yflip, xpos, ypos, prio);
- else
- draw_sprite_tile(bitmap, priomap, cliprect, gfx, tile, palette, tile_xflip, tile_yflip, xpos, ypos, prio);
- }
- }
- }
-
-#if 0
- if (xscale == 0) continue;
- uint32_t delta = (1 << 17) / xscale;
- for (int sy = 0; sy < ysize * 8; sy++)
- {
- uint16_t *src = &sprite_bitmap->pix(sy);
- uint16_t *dst = &bitmap.pix(y + sy);
- uint32_t dx = x << 16;
- for (int sx = 0; sx < xsize * 8; sx++)
- {
- dst[dx >> 16] = src[sx];
- dx += delta;
- }
- }
-#endif
-
- }
- }
-}
-
-
-
-void supracan_state::mark_active_tilemap_all_dirty(int layer)
-{
- int xsize = 0;
- int ysize = 0;
-
- int which_tilemap_size = get_tilemap_dimensions(xsize, ysize, layer);
-// for (int i=0;i<4;i++)
-// tilemap_mark_all_tiles_dirty(m_tilemap_sizes[layer][i]);
- m_tilemap_sizes[layer][which_tilemap_size]->mark_all_dirty();
-}
-
-
-
-/* draws tilemap with linescroll OR columnscroll to 16-bit indexed bitmap */
-void supracan_state::draw_roz_layer(bitmap_ind16 &bitmap, const rectangle &cliprect, tilemap_t *tmap, uint32_t startx, uint32_t starty, int incxx, int incxy, int incyx, int incyy, int wraparound/*, int columnscroll, uint32_t* scrollram*/, int transmask)
-{
- bitmap_ind16 &srcbitmap = tmap->pixmap();
- const int xmask = srcbitmap.width() - 1;
- const int ymask = srcbitmap.height() - 1;
- const int widthshifted = srcbitmap.width() << 16;
- const int heightshifted = srcbitmap.height() << 16;
-
- /* 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 */
- int sx = cliprect.min_x;
- int sy = cliprect.min_y;
- int ex = cliprect.max_x;
- int ey = cliprect.max_y;
-
- {
- /* loop over rows */
- while (sy <= ey)
- {
- /* initialize X counters */
- int x = sx;
- uint32_t cx = startx;
- uint32_t cy = starty;
-
- /* get dest and priority pointers */
- uint16_t *dest = &bitmap.pix(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_t data = &srcbitmap.pix(((cy >> 16) - scroll) & ymask, (cx >> 16) & xmask)[0];
-
- if ((data & transmask) != 0)
- dest[0] = data;
- }
- else
- #endif
- {
- int scroll = 0;//scrollram[(cy>>16)&0x3ff]);
- uint16_t data = srcbitmap.pix((cy >> 16) & ymask, ((cx >> 16) - scroll) & xmask);
-
- if ((data & transmask) != 0)
- *dest = data;
- }
- }
-
- /* advance in X */
- cx += incxx;
- cy += incxy;
- x++;
- dest++;
- }
-
- /* 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_t supracan_state::screen_update(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);
- m_sprite_mask_bitmap.fill(0x00, cliprect);
- m_prio_bitmap.fill(0xff, cliprect);
- bitmap.fill(0x80, visarea);
-
- draw_sprites(m_sprite_final_bitmap, m_sprite_mask_bitmap, m_prio_bitmap, visarea);
- }
- }
- else
- {
- m_sprite_final_bitmap.fill(0x00, cliprect);
- m_sprite_mask_bitmap.fill(0x00, cliprect);
- m_prio_bitmap.fill(0xff, cliprect);
- bitmap.fill(0x80, cliprect);
-
- draw_sprites(m_sprite_final_bitmap, m_sprite_mask_bitmap, m_prio_bitmap, cliprect);
- }
-
- // mix screen
- int xsize = 0, ysize = 0;
-// int tilemap_num;
- 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;
- int which_tilemap_size = get_tilemap_dimensions(xsize, ysize, layer);
- bitmap_ind16 &src_bitmap = m_tilemap_sizes[layer][which_tilemap_size]->pixmap();
- int gfx_region = get_tilemap_region(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;
-
- // yes, it will draw a single line if you specify a cliprect as such (partial updates...)
-
- for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
- {
- // these will have to change to uint32_t* etc. once alpha blending is supported
- uint16_t* screen = &bitmap.pix(y);
-
- int actualy = y & mosaic_mask;
- int realy = actualy + scrolly;
-
- if (!wrap)
- if (scrolly + y < 0 || scrolly + y > ((ysize * 8) - 1))
- continue;
-
- uint16_t* src = &src_bitmap.pix(realy & ((ysize * 8) - 1));
- uint8_t* priop = &m_prio_bitmap.pix(y);
-
- for (int 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_t srcpix = src[realx & ((xsize * 8) - 1)];
-
- if ((srcpix & transmask) != 0 && priority < (priop[x] >> 4))
- {
- screen[x] = srcpix;
- priop[x] = (priop[x] & 0x0f) | (priority << 4);
- }
- }
- }
- }
- 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?
- draw_roz_layer(bitmap, clip, m_tilemap_sizes[layer][which_tilemap_size], scrollx<<8, scrolly<<8, incxx<<8, incxy<<8, incyx<<8, incyy<<8, wrap, transmask);
- }
- }
- else
- {
- draw_roz_layer(bitmap, cliprect, m_tilemap_sizes[layer][which_tilemap_size], scrollx<<8, scrolly<<8, incxx<<8, incxy<<8, incyx<<8, incyy<<8, wrap, transmask);
- }
- }
- }
- }
- }
- }
-
-
- // combine sprites
- if (m_video_flags & 0x08)
- {
- for (int y = cliprect.min_y; y <= cliprect.max_y; y++)
- {
- uint16_t* dstp = &bitmap.pix(y);
- uint8_t* priop = &m_prio_bitmap.pix(y);
- uint16_t* spritep = &m_sprite_final_bitmap.pix(y);
-
- for (int x = cliprect.min_x; x <= cliprect.max_x; x++)
- {
- uint16_t sprite_pix = spritep[x];
- uint8_t tile_prio = priop[x] >> 4;
- uint8_t sprite_prio = priop[x] & 0x0f;
- if (sprite_pix != 0 && sprite_prio <= tile_prio)
- {
- dstp[x] = sprite_pix;
- }
- }
- }
- }
-
- return 0;
-}
-
-void supracan_state::sound_timer_irq(int state)
-{
- set_sound_irq(7, state);
-}
-
-void supracan_state::sound_dma_irq(int state)
-{
- set_sound_irq(6, state);
-}
-
-void supracan_state::dma_w(int offset, uint16_t data, uint16_t mem_mask, int ch)
-{
- address_space &mem = m_maincpu->space(AS_PROGRAM);
-
- switch (offset)
- {
- case 0x00/2: // Source address MSW
- LOGMASKED(LOG_DMA, "dma_w: source msw %d: %04x\n", ch, data);
- m_dma_regs.source[ch] &= 0x0000ffff;
- m_dma_regs.source[ch] |= data << 16;
- break;
- case 0x02/2: // Source address LSW
- LOGMASKED(LOG_DMA, "dma_w: source lsw %d: %04x\n", ch, data);
- m_dma_regs.source[ch] &= 0xffff0000;
- m_dma_regs.source[ch] |= data;
- break;
- case 0x04/2: // Destination address MSW
- LOGMASKED(LOG_DMA, "dma_w: dest msw %d: %04x\n", ch, data);
- m_dma_regs.dest[ch] &= 0x0000ffff;
- m_dma_regs.dest[ch] |= data << 16;
- break;
- case 0x06/2: // Destination address LSW
- LOGMASKED(LOG_DMA, "dma_w: dest lsw %d: %04x\n", ch, data);
- m_dma_regs.dest[ch] &= 0xffff0000;
- m_dma_regs.dest[ch] |= data;
- break;
- case 0x08/2: // Byte count
- LOGMASKED(LOG_DMA, "dma_w: count %d: %04x\n", ch, data);
- m_dma_regs.count[ch] = data;
- break;
- case 0x0a/2: // Control
- LOGMASKED(LOG_DMA, "dma_w: control %d: %04x\n", ch, data);
- if (data & 0x8800)
- {
-// if (data & 0x2000)
-// m_dma_regs.source-=2;
- LOGMASKED(LOG_DMA, "dma_w: Kicking off a DMA from %08x to %08x, %d bytes (%04x)\n", m_dma_regs.source[ch], m_dma_regs.dest[ch], m_dma_regs.count[ch] + 1, data);
-
- for (int i = 0; i <= m_dma_regs.count[ch]; i++)
- {
- if (data & 0x1000)
- {
- mem.write_word(m_dma_regs.dest[ch], mem.read_word(m_dma_regs.source[ch]));
- m_dma_regs.dest[ch] += 2;
- m_dma_regs.source[ch] += 2;
- if (data & 0x0100)
- if ((m_dma_regs.dest[ch] & 0xf) == 0)
- m_dma_regs.dest[ch] -= 0x10;
- }
- else
- {
- mem.write_byte(m_dma_regs.dest[ch], mem.read_byte(m_dma_regs.source[ch]));
- m_dma_regs.dest[ch]++;
- m_dma_regs.source[ch]++;
- }
- }
- }
- else if (data != 0x0000) // fake DMA, used by C.U.G.
- {
- LOGMASKED(LOG_UNKNOWNS | LOG_DMA, "dma_w: Unknown DMA kickoff value of %04x (other regs %08x, %08x, %d)\n", data, m_dma_regs.source[ch], m_dma_regs.dest[ch], m_dma_regs.count[ch] + 1);
- fatalerror("dma_w: Unknown DMA kickoff value of %04x (other regs %08x, %08x, %d)\n",data, m_dma_regs.source[ch], m_dma_regs.dest[ch], m_dma_regs.count[ch] + 1);
- }
- break;
- default:
- LOGMASKED(LOG_UNKNOWNS | LOG_DMA, "dma_w: Unknown register: %08x = %04x & %04x\n", 0xe90020 + (offset << 1), data, mem_mask);
- break;
- }
-}
-
-void supracan_state::dma_channel0_w(offs_t offset, uint16_t data, uint16_t mem_mask)
-{
- dma_w(offset, data, mem_mask, 0);
-}
-
-void supracan_state::dma_channel1_w(offs_t offset, uint16_t data, uint16_t mem_mask)
-{
- dma_w(offset, data, mem_mask, 1);
-}
-
-
-#if 0
-void supracan_state::supracan_pram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
-{
- 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_t byte)
-{
- int swapped_offset = bitswap<32>(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;
-}
-
-void supracan_state::vram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
-{
- COMBINE_DATA(&m_vram[offset]);
-
- // hack for 1bpp layer at startup
- write_swapped_byte(offset * 2, data >> 8);
- write_swapped_byte(offset * 2 + 1, (data & 0x00ff));
-
- // mark tiles of each depth as dirty
- m_gfxdecode->gfx(0)->mark_dirty((offset * 2) / 64);
- m_gfxdecode->gfx(1)->mark_dirty((offset * 2) / 32);
- m_gfxdecode->gfx(2)->mark_dirty((offset * 2) / 16);
- m_gfxdecode->gfx(3)->mark_dirty((offset * 2) / 512);
- m_gfxdecode->gfx(4)->mark_dirty((offset * 2) / 8);
-
-}
-
-void supracan_state::supracan_mem(address_map &map)
-{
- // 0x000000..0x3fffff is mapped by the cartslot
- map(0xe80000, 0xe8ffff).rw(FUNC(supracan_state::_68k_soundram_r), FUNC(supracan_state::_68k_soundram_w));
- map(0xe90000, 0xe9001f).rw(FUNC(supracan_state::sound_r), FUNC(supracan_state::sound_w));
- map(0xe90020, 0xe9002f).w(FUNC(supracan_state::dma_channel0_w));
- map(0xe90030, 0xe9003f).w(FUNC(supracan_state::dma_channel1_w));
-
- map(0xf00000, 0xf001ff).rw(FUNC(supracan_state::video_r), FUNC(supracan_state::video_w));
- map(0xf00200, 0xf003ff).ram().w("palette", FUNC(palette_device::write16)).share("palette");
- map(0xf40000, 0xf5ffff).ram().w(FUNC(supracan_state::vram_w)).share("vram");
- map(0xfc0000, 0xfcffff).mirror(0x30000).ram(); /* System work ram */
-}
-
-uint8_t supracan_state::sound_ram_read(offs_t offset)
-{
- return m_soundram[offset];
-}
-
-void supracan_state::set_sound_irq(uint8_t bit, uint8_t state)
-{
- const uint8_t old = m_soundcpu_irq_source;
- if (state)
- m_soundcpu_irq_source |= 1 << bit;
- else
- m_soundcpu_irq_source &= ~(1 << bit);
- const uint8_t changed = old ^ m_soundcpu_irq_source;
- if (changed)
- {
- m_soundcpu->set_input_line(0, (m_soundcpu_irq_enable & m_soundcpu_irq_source) ? ASSERT_LINE : CLEAR_LINE);
- }
-}
-
-uint8_t supracan_state::_6502_soundmem_r(offs_t offset)
-{
- uint8_t data = m_soundram[offset];
-
- switch (offset)
- {
- case 0x300: // Boot OK status
- break;
- case 0x402:
- case 0x403:
- {
- const uint8_t index = offset - 0x402;
- data = m_sound_cpu_shift_regs[index];
- if (!machine().side_effects_disabled())
- {
- LOGMASKED(LOG_SOUND, "%s: 6502_soundmem_r: Shift register %d read: %02x\n", machine().describe_context(), index, data);
- }
- break;
- }
- case 0x410:
- data = m_soundcpu_irq_enable;
- if (!machine().side_effects_disabled())
- {
- LOGMASKED(LOG_SOUND, "%s: 6502_soundmem_r: IRQ enable read: %02x\n", machine().describe_context(), data);
- }
- break;
- case 0x411:
- data = m_soundcpu_irq_source;
- m_soundcpu_irq_source = 0;
- if (!machine().side_effects_disabled())
- {
- LOGMASKED(LOG_SOUND, "%s: %s: 6502_soundmem_r: Sound IRQ source read + clear: %02x\n", machine().describe_context(), machine().time().to_string(), data);
- m_soundcpu->set_input_line(0, CLEAR_LINE);
- }
- break;
- case 0x420:
- if (!machine().side_effects_disabled())
- {
- data = m_sound_status;
- LOGMASKED(LOG_SOUND, "%s: %s: 6502_soundmem_r: Sound hardware status read: 0420 = %02x\n", machine().describe_context(), machine().time().to_string(), m_sound_status);
- }
- break;
- case 0x422:
- if (!machine().side_effects_disabled())
- {
- data = m_sound->read(m_sound_reg_addr);
- LOGMASKED(LOG_SOUND, "%s: %s: 6502_soundmem_r: Sound hardware reg data read: 0422 = %02x\n", machine().describe_context(), machine().time().to_string(), data);
- }
- break;
- case 0x404:
- case 0x405:
- case 0x409:
- case 0x414:
- case 0x416:
- // Intentional fall-through
- default:
- if (offset >= 0x400 && offset < 0x500)
- {
- if (!machine().side_effects_disabled())
- {
- LOGMASKED(LOG_SOUND | LOG_UNKNOWNS, "%s: 6502_soundmem_r: Unknown register %04x (%02x)\n", machine().describe_context(), offset, data);
- }
- }
- break;
- }
-
- return data;
-}
-
-void supracan_state::_6502_soundmem_w(offs_t offset, uint8_t data)
-{
- static attotime s_curr_time = attotime::zero;
- attotime now = machine().time();
-
- switch (offset)
- {
- case 0x407:
- {
- LOGMASKED(LOG_CONTROLS, "%s: 6502_soundmem_w: Shift register control: %02x\n", machine().describe_context(), data);
- const uint8_t old = m_sound_cpu_shift_ctrl;
- m_sound_cpu_shift_ctrl = data;
- const uint8_t lowered = old & ~m_sound_cpu_shift_ctrl;
- for (uint8_t pad = 0; pad < 2; pad++)
- {
- if (BIT(lowered, pad + 0))
- {
- m_latched_controls[pad] = m_pads[pad]->read();
- }
- if (BIT(lowered, pad + 2))
- {
- m_sound_cpu_shift_regs[pad] <<= 1;
- m_sound_cpu_shift_regs[pad] |= BIT(m_latched_controls[pad], 15);
- m_latched_controls[pad] <<= 1;
- }
- if (BIT(lowered, pad + 4))
- {
- m_sound_cpu_shift_regs[pad] = 0;
- }
- }
- break;
- }
- case 0x410:
- m_soundcpu_irq_enable = data;
- LOGMASKED(LOG_SOUND | LOG_IRQS, "%s: 6502_soundmem_w: IRQ enable: %02x\n", machine().describe_context(), data);
- break;
- case 0x420:
- LOGMASKED(LOG_SOUND, "%s: %s: 6502_soundmem_w: Sound addr write: 0420 = %02x\n", machine().describe_context(), now.to_string(), data);
- m_sound_reg_addr = data;
- break;
- case 0x422:
- {
- attotime delta = (s_curr_time == attotime::zero ? attotime::zero : (now - s_curr_time));
- s_curr_time = now;
- LOGMASKED(LOG_SOUND, "%s: %s: 6502_soundmem_w: Sound data write: 0422 = %02x (delta %0.3f)\n", machine().describe_context(), now.to_string(), data, (float)delta.as_double());
- m_sound->write(m_sound_reg_addr, data);
- break;
- }
- default:
- if (offset >= 0x400 && offset < 0x500)
- {
- LOGMASKED(LOG_SOUND | LOG_UNKNOWNS, "%s: 6502_soundmem_w: Unknown register %04x = %02x\n", machine().describe_context(), offset, data);
- }
- m_soundram[offset] = data;
- break;
- }
-}
-
-void supracan_state::supracan_sound_mem(address_map &map)
-{
- map(0x0000, 0xffff).rw(FUNC(supracan_state::_6502_soundmem_r), FUNC(supracan_state::_6502_soundmem_w)).share("soundram");
-}
-
-static INPUT_PORTS_START( supracan )
- PORT_START("P1")
- PORT_BIT(0x000f, IP_ACTIVE_LOW, IPT_UNUSED)
- PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_BUTTON6) PORT_PLAYER(1) PORT_NAME("P1 Button R")
- PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_BUTTON5) PORT_PLAYER(1) PORT_NAME("P1 Button L")
- PORT_BIT(0x0040, IP_ACTIVE_LOW, IPT_BUTTON4) PORT_PLAYER(1) PORT_NAME("P1 Button Y")
- PORT_BIT(0x0080, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_PLAYER(1) PORT_NAME("P1 Button X")
- PORT_BIT(0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_PLAYER(1) PORT_NAME("P1 Joypad Right")
- PORT_BIT(0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_PLAYER(1) PORT_NAME("P1 Joypad Left")
- PORT_BIT(0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_PLAYER(1) PORT_NAME("P1 Joypad Down")
- PORT_BIT(0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_PLAYER(1) PORT_NAME("P1 Joypad Up")
- PORT_BIT(0x1000, IP_ACTIVE_LOW, IPT_UNUSED)
- PORT_BIT(0x2000, IP_ACTIVE_LOW, IPT_START1)
- PORT_BIT(0x4000, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_PLAYER(1) PORT_NAME("P1 Button B")
- PORT_BIT(0x8000, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(1) PORT_NAME("P1 Button A")
-
- PORT_START("P2")
- PORT_BIT(0x000f, IP_ACTIVE_LOW, IPT_UNUSED)
- PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_BUTTON6) PORT_PLAYER(2) PORT_NAME("P2 Button R")
- PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_BUTTON5) PORT_PLAYER(2) PORT_NAME("P2 Button L")
- PORT_BIT(0x0040, IP_ACTIVE_LOW, IPT_BUTTON4) PORT_PLAYER(2) PORT_NAME("P2 Button Y")
- PORT_BIT(0x0080, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_PLAYER(2) PORT_NAME("P2 Button X")
- PORT_BIT(0x0100, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT) PORT_PLAYER(2) PORT_NAME("P2 Joypad Right")
- PORT_BIT(0x0200, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT) PORT_PLAYER(2) PORT_NAME("P2 Joypad Left")
- PORT_BIT(0x0400, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN) PORT_PLAYER(2) PORT_NAME("P2 Joypad Down")
- PORT_BIT(0x0800, IP_ACTIVE_LOW, IPT_JOYSTICK_UP) PORT_PLAYER(2) PORT_NAME("P2 Joypad Up")
- PORT_BIT(0x1000, IP_ACTIVE_LOW, IPT_UNUSED)
- PORT_BIT(0x2000, IP_ACTIVE_LOW, IPT_START2)
- PORT_BIT(0x4000, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_PLAYER(2) PORT_NAME("P2 Button B")
- PORT_BIT(0x8000, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(2) PORT_NAME("P2 Button A")
-INPUT_PORTS_END
-
-void supracan_state::palette_init(palette_device &palette) const
-{
- // Used for debugging purposes for now
- for (int i = 0; i < 32768; i++)
- {
- int const r = (i & 0x1f) << 3;
- int const g = ((i >> 5) & 0x1f) << 3;
- int const b = ((i >> 10) & 0x1f) << 3;
- palette.set_pen_color(i, r, g, b);
- }
-}
-
-void supracan_state::_68k_soundram_w(offs_t offset, uint16_t data, uint16_t mem_mask)
-{
- m_soundram[offset * 2 + 1] = data & 0xff;
- m_soundram[offset * 2] = data >> 8;
-
- if (offset * 2 < 0x500 && offset * 2 >= 0x400)
- {
- if (ACCESSING_BITS_8_15)
- {
- _6502_soundmem_w(offset * 2, data >> 8);
- }
- if (ACCESSING_BITS_0_7)
- {
- _6502_soundmem_w(offset * 2 + 1, data & 0xff);
- }
- }
- LOGMASKED(LOG_68K_SOUND, "%s: 68k sound RAM write: %04x & %04x = %04x\n", machine().describe_context(), offset << 1, mem_mask, (uint16_t)data);
-}
-
-uint16_t supracan_state::_68k_soundram_r(offs_t offset, uint16_t mem_mask)
-{
- uint16_t data = m_soundram[offset * 2] << 8;
- data |= m_soundram[offset * 2 + 1];
-
- if (offset * 2 >= 0x400 && offset * 2 < 0x500)
- {
- data = 0;
- if (ACCESSING_BITS_8_15)
- {
- data |= _6502_soundmem_r(offset * 2) << 8;
- }
- if (ACCESSING_BITS_0_7)
- {
- data |= _6502_soundmem_r(offset * 2 + 1);
- }
- }
- //LOGMASKED(LOG_68K_SOUND, "%s: 68k sound RAM read: %04x & %04x (%04x)\n", machine().describe_context(), offset << 1, mem_mask, data);
-
- return data;
-}
-
-uint16_t supracan_state::sound_r(offs_t offset, uint16_t mem_mask)
-{
- uint16_t data = 0;
-
- switch (offset)
- {
- case 0x04/2:
- data = (m_soundram[0x40c] << 8) | m_soundram[0x40d];
- LOGMASKED(LOG_SOUND, "%s: sound_r: DMA Request address from 6502, %08x: %04x & %04x\n", machine().describe_context(), 0xe90000 + (offset << 1), data, mem_mask);
- break;
-
- case 0x0c/2:
- data = m_soundram[0x40a];
- LOGMASKED(LOG_SOUND, "%s: sound_r: DMA Request flag from 6502, %08x: %04x & %04x\n", machine().describe_context(), 0xe90000 + (offset << 1), data, mem_mask);
- machine().debug_break();
- break;
-
- default:
- LOGMASKED(LOG_SOUND | LOG_UNKNOWNS, "%s: sound_r: Unknown register: %08x & %04x\n", machine().describe_context(), 0xe90000 + (offset << 1), mem_mask);
- break;
- }
-
- return data;
-}
-
-void supracan_state::sound_w(offs_t offset, uint16_t data, uint16_t mem_mask)
-{
- switch (offset)
- {
- case 0x000a/2: /* Sound cpu IRQ request. */
- LOGMASKED(LOG_SOUND, "%s: Sound CPU IRQ request: %04x\n", machine().describe_context(), data);
- set_sound_irq(5, 1);
- //m_soundcpu->set_input_line(0, ASSERT_LINE);
- break;
- case 0x001c/2: /* Sound cpu control. Bit 0 tied to sound cpu RESET line */
- {
- const uint16_t old = m_sound_cpu_ctrl;
- m_sound_cpu_ctrl = data;
- const uint16_t changed = old ^ m_sound_cpu_ctrl;
- if (BIT(changed, 0))
- {
- if (BIT(m_sound_cpu_ctrl, 0))
- {
- /* Reset and enable the sound cpu */
- m_soundcpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
- m_soundcpu->reset();
- }
- else
- {
- /* Halt the sound cpu */
- m_soundcpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
- }
- }
- LOGMASKED(LOG_SOUND, "%s: Sound CPU ctrl write: %04x\n", machine().describe_context(), data);
- break;
- }
- default:
- LOGMASKED(LOG_SOUND | LOG_UNKNOWNS, "%s: sound_w: Unknown register: %08x = %04x & %04x\n", machine().describe_context(), 0xe90000 + (offset << 1), data, mem_mask);
- break;
- }
-}
-
-
-uint16_t supracan_state::video_r(offs_t offset, uint16_t mem_mask)
-{
- uint16_t data = m_video_regs[offset];
-
- switch (offset)
- {
- case 0x00/2: // Video IRQ flags
- if (!machine().side_effects_disabled())
- {
- LOGMASKED(LOG_HFVIDEO, "read video IRQ flags (%04x)\n", data);
- m_maincpu->set_input_line(7, CLEAR_LINE);
- }
- break;
- case 0x02/2: // Current scanline
- LOGMASKED(LOG_VIDEO, "read current scanline (%04x)\n", data);
- break;
- case 0x08/2: // Unknown (not video flags!) - gambling lord disagrees, it MUST read back what it wrote because it reads it before turning on/off layers and writes it back
- LOGMASKED(LOG_VIDEO, "read unkown 0x08 (%04x)\n", data);
- break;
- case 0x100/2:
- if (!machine().side_effects_disabled())
- {
- LOGMASKED(LOG_TILEMAP0, "read tilemap_flags[0] (%04x)\n", data);
- }
- break;
- case 0x106/2:
- if (!machine().side_effects_disabled())
- {
- LOGMASKED(LOG_TILEMAP0, "read tilemap_scrolly[0] (%04x)\n", data);
- }
- break;
- case 0x120/2:
- if (!machine().side_effects_disabled())
- {
- LOGMASKED(LOG_TILEMAP1, "read tilemap_flags[1] (%04x)\n", data);
- }
- break;
- default:
- if (!machine().side_effects_disabled())
- {
- LOGMASKED(LOG_UNKNOWNS, "video_r: Unknown register: %08x (%04x & %04x)\n", 0xf00000 + (offset << 1), data, mem_mask);
- }
- break;
- }
-
- return data;
-}
-
-TIMER_CALLBACK_MEMBER(supracan_state::hbl_callback)
-{
- m_maincpu->set_input_line(3, HOLD_LINE);
-
- m_hbl_timer->adjust(attotime::never);
-}
-
-TIMER_CALLBACK_MEMBER(supracan_state::line_on_callback)
-{
- m_maincpu->set_input_line(5, HOLD_LINE);
-
- m_line_on_timer->adjust(attotime::never);
-}
-
-TIMER_CALLBACK_MEMBER(supracan_state::line_off_callback)
-{
- m_maincpu->set_input_line(5, CLEAR_LINE);
-
- m_line_on_timer->adjust(attotime::never);
-}
-
-TIMER_CALLBACK_MEMBER(supracan_state::video_callback)
-{
- int vpos = m_screen->vpos();
-
- m_video_regs[0] &= ~0x0002;
-
- switch (vpos)
- {
- case 0:
- m_video_regs[0] &= 0x7fff;
-
- // we really need better management of this
- mark_active_tilemap_all_dirty(0);
- mark_active_tilemap_all_dirty(1);
- mark_active_tilemap_all_dirty(2);
- mark_active_tilemap_all_dirty(3);
- break;
-
- case 224: // FIXME: Son of Evil is pretty picky about this one, a timing of 240 makes it crash
- m_video_regs[0] |= 0x8000;
- break;
-
- case 240:
- if (m_irq_mask & 1)
- {
- LOGMASKED(LOG_IRQS, "Triggering VBL IRQ\n\n");
- m_maincpu->set_input_line(7, HOLD_LINE);
- }
- break;
- }
-
- m_video_regs[1] = m_screen->vpos() - 16; // for son of evil, wants vblank active around 224 instead...
-
- m_hbl_timer->adjust(m_screen->time_until_pos(vpos, 320));
- m_video_timer->adjust(m_screen->time_until_pos((vpos + 1) % 256, 0));
-}
-
-void supracan_state::video_w(offs_t offset, uint16_t data, uint16_t mem_mask)
-{
- address_space &mem = m_maincpu->space(AS_PROGRAM);
-
- // if any of this changes we need a partial update (see sango fighters intro)
- m_screen->update_partial(m_screen->vpos());
-
- COMBINE_DATA(&m_video_regs[offset]);
- data = m_video_regs[offset];
-
- switch (offset)
- {
- case 0x10/2: // Byte count
- LOGMASKED(LOG_SPRDMA, "sprite dma word count: %04x\n", data);
- m_sprdma_regs.count = data;
- break;
- case 0x12/2: // Destination address MSW
- m_sprdma_regs.dst &= 0x0000ffff;
- m_sprdma_regs.dst |= data << 16;
- LOGMASKED(LOG_SPRDMA, "sprite dma dest msw: %04x\n", data);
- break;
- case 0x14/2: // Destination address LSW
- m_sprdma_regs.dst &= 0xffff0000;
- m_sprdma_regs.dst |= data;
- LOGMASKED(LOG_SPRDMA, "sprite dma dest lsw: %04x\n", data);
- break;
- case 0x16/2: // Source word increment
- LOGMASKED(LOG_SPRDMA, "sprite dma dest word inc: %04x\n", data);
- m_sprdma_regs.dst_inc = data;
- break;
- case 0x18/2: // Source address MSW
- m_sprdma_regs.src &= 0x0000ffff;
- m_sprdma_regs.src |= data << 16;
- LOGMASKED(LOG_SPRDMA, "sprite dma src msw: %04x\n", data);
- break;
- case 0x1a/2: // Source address LSW
- LOGMASKED(LOG_SPRDMA, "sprite dma src lsw: %04x\n", data);
- m_sprdma_regs.src &= 0xffff0000;
- m_sprdma_regs.src |= data;
- break;
- case 0x1c/2: // Source word increment
- LOGMASKED(LOG_SPRDMA, "sprite dma src word inc: %04x\n", data);
- m_sprdma_regs.src_inc = data;
- break;
- case 0x1e/2:
- LOGMASKED(LOG_SPRDMA, "video_w: Kicking off a DMA from %08x to %08x, %d bytes (%04x)\n", m_sprdma_regs.src, m_sprdma_regs.dst, m_sprdma_regs.count, data);
-
- /* TODO: what's 0x2000 and 0x4000 for? */
- if (data & 0x8000)
- {
- if (data & 0x2000 || data & 0x4000)
- {
- m_sprdma_regs.dst |= 0xf40000;
- }
-
- if (data & 0x2000)
- {
- //m_sprdma_regs.count <<= 1;
- }
-
- for (int i = 0; i <= m_sprdma_regs.count; i++)
- {
- if (data & 0x0100) // dma 0x00 fill (or fixed value?)
- {
- mem.write_word(m_sprdma_regs.dst, 0);
- m_sprdma_regs.dst += 2 * m_sprdma_regs.dst_inc;
- //memset(supracan_vram, 0x00, 0x020000);
- }
- else
- {
- mem.write_word(m_sprdma_regs.dst, mem.read_word(m_sprdma_regs.src));
- m_sprdma_regs.dst += 2 * m_sprdma_regs.dst_inc;
- m_sprdma_regs.src += 2 * m_sprdma_regs.src_inc;
- }
- }
- }
- else
- {
- LOGMASKED(LOG_SPRDMA | LOG_UNKNOWNS, "dma_w: Attempting to kick off a DMA without bit 15 set! (%04x)\n", data);
- }
- break;
- case 0x08/2:
- if (data != m_video_flags)
- {
- LOGMASKED(LOG_VIDEO, "video_flags = %04x\n", data);
-
- m_video_flags = data;
-
- rectangle visarea = m_screen->visible_area();
-
- visarea.set(0, ((m_video_flags & 0x100) ? 320 : 256) - 1, 8, 232 - 1);
- m_screen->configure(348, 256, visarea, m_screen->frame_period().attoseconds());
- }
- break;
- case 0x0a/2:
- // raster interrupt
- LOGMASKED(LOG_IRQS, "Raster 'line on' IRQ Trigger write? = %04x\n", data);
- if (data & 0x8000)
- {
- m_line_on_timer->adjust(m_screen->time_until_pos((data & 0x00ff), 0));
- }
- else
- {
- m_line_on_timer->adjust(attotime::never);
- }
- break;
-
- case 0x0c/2:
- LOGMASKED(LOG_IRQS, "Raster 'line off' IRQ Trigger write? = %04x\n", data);
- if (data & 0x8000)
- {
- m_line_off_timer->adjust(m_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; LOGMASKED(LOG_SPRITES, "sprite_base_addr = %04x\n", data); break;
- case 0x22/2: m_sprite_count = data + 1; LOGMASKED(LOG_SPRITES, "sprite_count = %d\n", data + 1); break;
- case 0x26/2: m_sprite_flags = data; LOGMASKED(LOG_SPRITES, "sprite_flags = %04x\n", data); break;
-
- /* Tilemap 0 */
- case 0x100/2: m_tilemap_flags[0] = data; LOGMASKED(LOG_TILEMAP0, "tilemap_flags[0] = %04x\n", data); break;
- case 0x104/2: m_tilemap_scrollx[0] = data; LOGMASKED(LOG_TILEMAP0, "tilemap_scrollx[0] = %04x\n", data); break;
- case 0x106/2: m_tilemap_scrolly[0] = data; LOGMASKED(LOG_TILEMAP0, "tilemap_scrolly[0] = %04x\n", data); break;
- case 0x108/2: m_tilemap_base_addr[0] = data << 1; LOGMASKED(LOG_TILEMAP0, "tilemap_base_addr[0] = %05x\n", data << 2); break;
- case 0x10a/2: m_tilemap_mode[0] = data; LOGMASKED(LOG_TILEMAP0, "tilemap_mode[0] = %04x\n", data); break;
-
- /* Tilemap 1 */
- case 0x120/2: m_tilemap_flags[1] = data; LOGMASKED(LOG_TILEMAP1, "tilemap_flags[1] = %04x\n", data); break;
- case 0x124/2: m_tilemap_scrollx[1] = data; LOGMASKED(LOG_TILEMAP1, "tilemap_scrollx[1] = %04x\n", data); break;
- case 0x126/2: m_tilemap_scrolly[1] = data; LOGMASKED(LOG_TILEMAP1, "tilemap_scrolly[1] = %04x\n", data); break;
- case 0x128/2: m_tilemap_base_addr[1] = data << 1; LOGMASKED(LOG_TILEMAP1, "tilemap_base_addr[1] = %05x\n", data << 2); break;
- case 0x12a/2: m_tilemap_mode[1] = data; LOGMASKED(LOG_TILEMAP1, "tilemap_mode[1] = %04x\n", data); break;
-
- /* Tilemap 2? */
- case 0x140/2: m_tilemap_flags[2] = data; LOGMASKED(LOG_TILEMAP2, "tilemap_flags[2] = %04x\n", data); break;
- case 0x144/2: m_tilemap_scrollx[2] = data; LOGMASKED(LOG_TILEMAP2, "tilemap_scrollx[2] = %04x\n", data); break;
- case 0x146/2: m_tilemap_scrolly[2] = data; LOGMASKED(LOG_TILEMAP2, "tilemap_scrolly[2] = %04x\n", data); break;
- case 0x148/2: m_tilemap_base_addr[2] = data << 1; LOGMASKED(LOG_TILEMAP2, "tilemap_base_addr[2] = %05x\n", data << 2); break;
- case 0x14a/2: m_tilemap_mode[2] = data; LOGMASKED(LOG_TILEMAP2, "tilemap_mode[2] = %04x\n", data); break;
-
- /* ROZ */
- case 0x180/2: m_roz_mode = data; LOGMASKED(LOG_ROZ, "roz_mode = %04x\n", data); break;
- case 0x184/2: m_roz_scrollx = (data << 16) | (m_roz_scrollx & 0xffff); m_roz_changed |= 1; LOGMASKED(LOG_ROZ, "roz_scrollx = %08x\n", m_roz_scrollx); break;
- case 0x186/2: m_roz_scrollx = (data) | (m_roz_scrollx & 0xffff0000); m_roz_changed |= 1; LOGMASKED(LOG_ROZ, "roz_scrollx = %08x\n", m_roz_scrollx); break;
- case 0x188/2: m_roz_scrolly = (data << 16) | (m_roz_scrolly & 0xffff); m_roz_changed |= 2; LOGMASKED(LOG_ROZ, "roz_scrolly = %08x\n", m_roz_scrolly); break;
- case 0x18a/2: m_roz_scrolly = (data) | (m_roz_scrolly & 0xffff0000); m_roz_changed |= 2; LOGMASKED(LOG_ROZ, "roz_scrolly = %08x\n", m_roz_scrolly); break;
- case 0x18c/2: m_roz_coeffa = data; LOGMASKED(LOG_ROZ, "roz_coeffa = %04x\n", data); break;
- case 0x18e/2: m_roz_coeffb = data; LOGMASKED(LOG_ROZ, "roz_coeffb = %04x\n", data); break;
- case 0x190/2: m_roz_coeffc = data; LOGMASKED(LOG_ROZ, "roz_coeffc = %04x\n", data); break;
- case 0x192/2: m_roz_coeffd = data; LOGMASKED(LOG_ROZ, "roz_coeffd = %04x\n", data); break;
- case 0x194/2: m_roz_base_addr = data << 1; LOGMASKED(LOG_ROZ, "roz_base_addr = %05x\n", data << 2); break;
- case 0x196/2: m_roz_tile_bank = data; LOGMASKED(LOG_ROZ, "roz_tile_bank = %04x\n", data); break; //tile bank
- case 0x198/2: m_roz_unk_base0 = data << 2; LOGMASKED(LOG_ROZ, "roz_unk_base0 = %05x\n", data << 2); break;
- case 0x19a/2: m_roz_unk_base1 = data << 2; LOGMASKED(LOG_ROZ, "roz_unk_base1 = %05x\n", data << 2); break;
- case 0x19e/2: m_roz_unk_base2 = data << 2; LOGMASKED(LOG_ROZ, "roz_unk_base2 = %05x\n", data << 2); break;
-
- case 0x1d0/2: m_unk_1d0 = data; LOGMASKED(LOG_UNKNOWNS, "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
- LOGMASKED(LOG_IRQS, "irq_mask = %04x\n", data);
- break;
- default:
- LOGMASKED(LOG_UNKNOWNS, "video_w: Unknown register: %08x = %04x & %04x\n", 0xf00000 + (offset << 1), data, mem_mask);
- break;
- }
-// m_video_regs[offset] = data;
-}
-
-
-DEVICE_IMAGE_LOAD_MEMBER(supracan_state::cart_load)
-{
- uint32_t size = m_cart->common_get_size("rom");
-
- if (size > 0x400000)
- {
- image.seterror(image_error::INVALIDIMAGE, "Unsupported cartridge size");
- return image_init_result::FAIL;
- }
-
- m_cart->rom_alloc(size, GENERIC_ROM16_WIDTH, ENDIANNESS_BIG);
- m_cart->common_load_rom(m_cart->get_rom_base(), size, "rom");
-
- return image_init_result::PASS;
-}
-
-
-void supracan_state::machine_start()
-{
- save_item(NAME(m_dma_regs.source));
- save_item(NAME(m_dma_regs.dest));
- save_item(NAME(m_dma_regs.count));
- save_item(NAME(m_dma_regs.control));
-
- save_item(NAME(m_sprdma_regs.src));
- save_item(NAME(m_sprdma_regs.src_inc));
- save_item(NAME(m_sprdma_regs.dst));
- save_item(NAME(m_sprdma_regs.dst_inc));
- save_item(NAME(m_sprdma_regs.count));
- save_item(NAME(m_sprdma_regs.control));
-
- save_item(NAME(m_sound_cpu_ctrl));
- save_item(NAME(m_soundcpu_irq_enable));
- save_item(NAME(m_soundcpu_irq_source));
- save_item(NAME(m_sound_cpu_shift_ctrl));
- save_item(NAME(m_sound_cpu_shift_regs));
- save_item(NAME(m_latched_controls));
- save_item(NAME(m_sound_status));
- save_item(NAME(m_sound_reg_addr));
-
- save_item(NAME(m_sprite_count));
- save_item(NAME(m_sprite_base_addr));
- save_item(NAME(m_sprite_flags));
-
- save_item(NAME(m_tilemap_base_addr));
- save_item(NAME(m_tilemap_scrollx));
- save_item(NAME(m_tilemap_scrolly));
- save_item(NAME(m_video_flags));
- save_item(NAME(m_tilemap_flags));
- save_item(NAME(m_tilemap_mode));
- save_item(NAME(m_irq_mask));
-#if 0
- save_item(NAME(m_hbl_mask));
-#endif
-
- save_item(NAME(m_roz_base_addr));
- save_item(NAME(m_roz_mode));
- save_item(NAME(m_roz_scrollx));
- save_item(NAME(m_roz_scrolly));
- save_item(NAME(m_roz_tile_bank));
- save_item(NAME(m_roz_unk_base0));
- save_item(NAME(m_roz_unk_base1));
- save_item(NAME(m_roz_unk_base2));
- save_item(NAME(m_roz_coeffa));
- save_item(NAME(m_roz_coeffb));
- save_item(NAME(m_roz_coeffc));
- save_item(NAME(m_roz_coeffd));
- save_item(NAME(m_roz_changed));
- save_item(NAME(m_unk_1d0));
-
- save_item(NAME(m_video_regs));
-
- m_video_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(supracan_state::video_callback), this));
- m_hbl_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(supracan_state::hbl_callback), this));
- m_line_on_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(supracan_state::line_on_callback), this));
- m_line_off_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(supracan_state::line_off_callback), this));
-
- if (m_cart->exists())
- m_maincpu->space(AS_PROGRAM).install_read_handler(0x000000, 0x3fffff, read16s_delegate(*m_cart, FUNC(generic_slot_device::read16_rom)));
-}
-
-
-void supracan_state::machine_reset()
-{
- m_sprite_count = 0;
- m_sprite_base_addr = 0;
- m_sprite_flags = 0;
-
- m_sound_cpu_ctrl = 0;
- m_soundcpu_irq_enable = 0;
- m_soundcpu_irq_source = 0;
- m_sound_cpu_shift_ctrl = 0;
- std::fill(std::begin(m_sound_cpu_shift_regs), std::end(m_sound_cpu_shift_regs), 0);
- std::fill(std::begin(m_latched_controls), std::end(m_latched_controls), 0);
- m_sound_status = 0;
- m_sound_reg_addr = 0;
-
- m_soundcpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
-
- m_video_timer->adjust(m_screen->time_until_pos(0, 0));
- m_irq_mask = 0;
-
- m_roz_base_addr = 0;
- m_roz_mode = 0;
- std::fill(std::begin(m_tilemap_base_addr), std::end(m_tilemap_base_addr), 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_t 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_t 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( gfx_supracan )
- GFXDECODE_RAM( "vram", 0, supracan_gfx8bpp, 0, 1 )
- GFXDECODE_RAM( "vram", 0, supracan_gfx4bpp, 0, 0x10 )
- GFXDECODE_RAM( "vram", 0, supracan_gfx2bpp, 0, 0x40 )
- GFXDECODE_RAM( "vram", 0, supracan_gfx1bpp, 0, 0x80 )
- GFXDECODE_RAM( "vram", 0, supracan_gfx1bpp_alt, 0, 0x80 )
-GFXDECODE_END
-
-void supracan_state::supracan(machine_config &config)
-{
- M68000(config, m_maincpu, XTAL(10'738'635)); /* Correct frequency unknown */
- m_maincpu->set_addrmap(AS_PROGRAM, &supracan_state::supracan_mem);
-
- M6502(config, m_soundcpu, XTAL(3'579'545)); /* TODO: Verify actual clock */
- m_soundcpu->set_addrmap(AS_PROGRAM, &supracan_state::supracan_sound_mem);
-
- config.set_perfect_quantum(m_soundcpu);
-
- SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
- m_screen->set_raw(XTAL(10'738'635)/2, 348, 0, 256, 256, 0, 240); /* No idea if this is correct */
- m_screen->set_screen_update(FUNC(supracan_state::screen_update));
- m_screen->set_palette("palette");
- //m_screen->screen_vblank().set(FUNC(supracan_state::screen_vblank));
-
- PALETTE(config, "palette", FUNC(supracan_state::palette_init)).set_format(palette_device::xBGR_555, 32768);
-
- GFXDECODE(config, m_gfxdecode, "palette", gfx_supracan);
-
- SPEAKER(config, "lspeaker").front_left();
- SPEAKER(config, "rspeaker").front_right();
-
- ACANSND(config, m_sound, XTAL(3'579'545));
- m_sound->ram_read().set(FUNC(supracan_state::sound_ram_read));
- m_sound->timer_irq_handler().set(FUNC(supracan_state::sound_timer_irq));
- m_sound->dma_irq_handler().set(FUNC(supracan_state::sound_dma_irq));
- m_sound->add_route(0, "lspeaker", 1.0);
- m_sound->add_route(1, "rspeaker", 1.0);
-
- generic_cartslot_device &cartslot(GENERIC_CARTSLOT(config, "cartslot", generic_plain_slot, "supracan_cart"));
- cartslot.set_width(GENERIC_ROM16_WIDTH);
- cartslot.set_endian(ENDIANNESS_BIG);
- cartslot.set_device_load(FUNC(supracan_state::cart_load));
-
- SOFTWARE_LIST(config, "cart_list").set_original("supracan");
-}
-
-ROM_START( supracan )
-ROM_END
-
-} // Anonymous namespace
-
-
-/* YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS */
-CONS( 1995, supracan, 0, 0, supracan, supracan, supracan_state, empty_init, "Funtech Entertainment", "Super A'Can", MACHINE_NO_SOUND | MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING )