summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/video/fmtowns.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/video/fmtowns.cpp')
-rw-r--r--src/mame/video/fmtowns.cpp1567
1 files changed, 0 insertions, 1567 deletions
diff --git a/src/mame/video/fmtowns.cpp b/src/mame/video/fmtowns.cpp
deleted file mode 100644
index 34b912b54f9..00000000000
--- a/src/mame/video/fmtowns.cpp
+++ /dev/null
@@ -1,1567 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Barry Rodewald
-
-/*
- * FM Towns video hardware
- *
- * Resolution: from 320x200 to 768x512
- *
- * Up to two graphics layers
- *
- * Sprites
- *
- * CRTC registers (16-bit):
- *
- * 0: HSync width 1
- * 1: HSync width 2
- * 4: HSync total
- * 5: VSync period 1
- * 6: VSync period 2
- * 7: Equalising pulse accountable time (what?)
- * 8: VSync total
- *
- * 9:
- * 10: Graphic layer 0 horizontal start/end
- * 11:
- * 12: Graphic layer 1 horizontal start/end
- *
- * 13:
- * 14: Graphic layer 0 vertical start/end
- * 15:
- * 16: Graphic layer 1 vertical start/end
- *
- * 17: Graphic layer 0 frame start address
- * 18: Graphic layer 0 horizontal adjust
- * 19: Graphic layer 0 field indirect address offset
- * 20: Graphic layer 0 line indirect address offset
- *
- * 21-24: As above, but for Graphic layer 1
- *
- * 27: Layer zoom. bits 0-3 = horizontal zoom layer 0
- * (0 = x1, 1 = x2, bits 4-7 = vertical zoom layer 0
- * 2 = x3...) bits 8-11 = horizontal zoom layer 1
- * bits 12-15 = vertical zoom layer 1
- *
- * 28: Control register 0
- * VSync enable (bit 15) (blank display?)
- * Scroll type (layer 0 = bit 4, layer 1 = bit 5)
- * 0 = spherical scroll, 1 = cylindrical scroll
- *
- * 29: Control register 1
- * Dot clock (bits 1 and 0)
- * 0x00 = 28.6363MHz
- * 0x01 = 24.5454MHz
- * 0x02 = 25.175MHz
- * 0x03 = 21.0525MHz (default?)
- *
- * 30: Dummy register
- *
- * 31: Control register 2
- *
- * Video registers:
- *
- * 0: Control register:
- * bit 4 = PMODE - enable 2 layers
- * bits 2-3 = layer 1 mode
- * bits 0-1 = layer 0 mode
- * mode: 1 = 16 colours (PMODE=1 only), 2 = 256 colours (PMODE=0 only),
- * 3 = highcolour (16-bit), 0 = display off
- *
- * 1: Priority register (bit 0)
- * bit 0: PR1 - layer priority (0 = layer 0 before)
- * bit 2: YM - screen brightness (0 = high brightness)
- * bit 3: YS - 0 = valid. Used for 256 colour external sync
- * bits 4-5: Palette select
- * 0 = layer 0, 16 colours, 1 or 3 = 256 colours
- * 2 = layer 1, 16 colours
- *
- *
- * Sprite registers:
- *
- * 0,1: Maximum sprite (last one to render?) (10-bit)
- *
- * 1 (bit 7): Enable sprite display
- *
- * 2,3: X offset (9-bit)
- *
- * 4,5: Y offset (9-bit)
- *
- * 6 (bit 4): VRAM location (0=0x40000,1=0x60000)
- *
- */
-
-#include "emu.h"
-#include "includes/fmtowns.h"
-
-#include "machine/pic8259.h"
-#include "machine/ram.h"
-#include "screen.h"
-
-
-//#define CRTC_REG_DISP 1
-//#define SPR_DEBUG 1
-#define LAYER_DISABLE 0 // for debugging, allow the Q and W keys to be used for disabling graphic layers
-#define LOG_VID 0
-
-//static uint32_t pshift; // for debugging
-
-void towns_state::towns_crtc_refresh_mode()
-{
- rectangle scr(0, m_video.towns_crtc_reg[4] - m_video.towns_crtc_reg[0], 0, m_video.towns_crtc_reg[8] / 2);
-
- // layer 0
- m_video.towns_crtc_layerscr[0].min_x = m_video.towns_crtc_reg[9] - m_video.towns_crtc_reg[0];
- m_video.towns_crtc_layerscr[0].min_y = (m_video.towns_crtc_reg[13] - m_video.towns_crtc_reg[6]) / 2;
- m_video.towns_crtc_layerscr[0].max_x = m_video.towns_crtc_reg[10] - m_video.towns_crtc_reg[0];
- m_video.towns_crtc_layerscr[0].max_y = ((m_video.towns_crtc_reg[14] - m_video.towns_crtc_reg[6]) / 2) - 1;
-
- // layer 1
- m_video.towns_crtc_layerscr[1].min_x = m_video.towns_crtc_reg[11] - m_video.towns_crtc_reg[0];
- m_video.towns_crtc_layerscr[1].min_y = (m_video.towns_crtc_reg[15] - m_video.towns_crtc_reg[6]) / 2;
- m_video.towns_crtc_layerscr[1].max_x = m_video.towns_crtc_reg[12] - m_video.towns_crtc_reg[0];
- m_video.towns_crtc_layerscr[1].max_y = ((m_video.towns_crtc_reg[16] - m_video.towns_crtc_reg[6]) / 2) - 1;
-
- // sanity checks
- if(scr.max_x == 0 || scr.max_y == 0)
- return;
- if(scr.max_x <= scr.min_x || scr.max_y <= scr.min_y)
- return;
-
- m_screen->configure(scr.max_x+1,scr.max_y+1,scr,HZ_TO_ATTOSECONDS(60));
-}
-
-uint8_t towns_state::towns_gfx_high_r(offs_t offset)
-{
- return m_towns_gfxvram[offset];
-}
-
-void towns_state::towns_gfx_high_w(offs_t offset, uint8_t data)
-{
- u8 mask = m_vram_mask[offset & 3];
- u8 mem = m_towns_gfxvram[offset];
- m_towns_gfxvram[offset] = (mem & ~mask) | (data & mask);
-}
-
-uint8_t towns_state::towns_gfx_packed_r(offs_t offset)
-{
- return m_towns_gfxvram[bitswap<19>(offset,2,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,1,0)];
-}
-
-void towns_state::towns_gfx_packed_w(offs_t offset, uint8_t data)
-{
- u8 mask = m_vram_mask[offset & 3];
- offset = bitswap<19>(offset,2,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,1,0);
- u8 mem = m_towns_gfxvram[offset];
- m_towns_gfxvram[offset] = (mem & ~mask) | (data & mask);
-}
-
-
-uint8_t towns_state::towns_gfx_r(offs_t offset)
-{
- uint8_t ret = 0;
-
- if(m_towns_mainmem_enable != 0)
- return m_ram->pointer()[offset+0xc0000];
-
- offset = offset << 2;
-
- if(m_video.towns_vram_page_sel != 0)
- offset += 0x20000;
-
- ret = (((m_towns_gfxvram[offset] >> m_video.towns_vram_rplane) << 7) & 0x80)
- | (((m_towns_gfxvram[offset] >> m_video.towns_vram_rplane) << 2) & 0x40)
- | (((m_towns_gfxvram[offset+1] >> m_video.towns_vram_rplane) << 5) & 0x20)
- | (((m_towns_gfxvram[offset+1] >> m_video.towns_vram_rplane)) & 0x10)
- | (((m_towns_gfxvram[offset+2] >> m_video.towns_vram_rplane) << 3) & 0x08)
- | (((m_towns_gfxvram[offset+2] >> m_video.towns_vram_rplane) >> 2) & 0x04)
- | (((m_towns_gfxvram[offset+3] >> m_video.towns_vram_rplane) << 1) & 0x02)
- | (((m_towns_gfxvram[offset+3] >> m_video.towns_vram_rplane) >> 4) & 0x01);
-
- return ret;
-}
-
-void towns_state::towns_gfx_w(offs_t offset, uint8_t data)
-{
- if(m_towns_mainmem_enable != 0)
- {
- m_ram->pointer()[offset+0xc0000] = data;
- return;
- }
- offset = offset << 2;
- if(m_video.towns_vram_page_sel != 0)
- offset += 0x20000;
- if(m_video.towns_vram_wplane & 0x08)
- {
- m_towns_gfxvram[offset] &= ~0x88;
- m_towns_gfxvram[offset] |= ((data & 0x80) >> 4) | ((data & 0x40) << 1);
- m_towns_gfxvram[offset + 1] &= ~0x88;
- m_towns_gfxvram[offset + 1] |= ((data & 0x20) >> 2) | ((data & 0x10) << 3);
- m_towns_gfxvram[offset + 2] &= ~0x88;
- m_towns_gfxvram[offset + 2] |= ((data & 0x08)) | ((data & 0x04) << 5);
- m_towns_gfxvram[offset + 3] &= ~0x88;
- m_towns_gfxvram[offset + 3] |= ((data & 0x02) << 2) | ((data & 0x01) << 7);
- }
- if(m_video.towns_vram_wplane & 0x04)
- {
- m_towns_gfxvram[offset] &= ~0x44;
- m_towns_gfxvram[offset] |= ((data & 0x80) >> 5) | ((data & 0x40));
- m_towns_gfxvram[offset + 1] &= ~0x44;
- m_towns_gfxvram[offset + 1] |= ((data & 0x20) >> 3) | ((data & 0x10) << 2);
- m_towns_gfxvram[offset + 2] &= ~0x44;
- m_towns_gfxvram[offset + 2] |= ((data & 0x08) >> 1) | ((data & 0x04) << 4);
- m_towns_gfxvram[offset + 3] &= ~0x44;
- m_towns_gfxvram[offset + 3] |= ((data & 0x02) << 1) | ((data & 0x01) << 6);
- }
- if(m_video.towns_vram_wplane & 0x02)
- {
- m_towns_gfxvram[offset] &= ~0x22;
- m_towns_gfxvram[offset] |= ((data & 0x80) >> 6) | ((data & 0x40) >> 1);
- m_towns_gfxvram[offset + 1] &= ~0x22;
- m_towns_gfxvram[offset + 1] |= ((data & 0x20) >> 4) | ((data & 0x10) << 1);
- m_towns_gfxvram[offset + 2] &= ~0x22;
- m_towns_gfxvram[offset + 2] |= ((data & 0x08) >> 2) | ((data & 0x04) << 3);
- m_towns_gfxvram[offset + 3] &= ~0x22;
- m_towns_gfxvram[offset + 3] |= ((data & 0x02)) | ((data & 0x01) << 5);
- }
- if(m_video.towns_vram_wplane & 0x01)
- {
- m_towns_gfxvram[offset] &= ~0x11;
- m_towns_gfxvram[offset] |= ((data & 0x80) >> 7) | ((data & 0x40) >> 2);
- m_towns_gfxvram[offset + 1] &= ~0x11;
- m_towns_gfxvram[offset + 1] |= ((data & 0x20) >> 5) | ((data & 0x10));
- m_towns_gfxvram[offset + 2] &= ~0x11;
- m_towns_gfxvram[offset + 2] |= ((data & 0x08) >> 3) | ((data & 0x04) << 2);
- m_towns_gfxvram[offset + 3] &= ~0x11;
- m_towns_gfxvram[offset + 3] |= ((data & 0x02) >> 1) | ((data & 0x01) << 4);
- }
-}
-
-void towns_state::towns_update_kanji_offset()
-{
- // this is a little over the top...
- if(m_video.towns_kanji_code_h < 0x30)
- {
- m_video.towns_kanji_offset = ((m_video.towns_kanji_code_l & 0x1f) << 4)
- | (((m_video.towns_kanji_code_l - 0x20) & 0x20) << 8)
- | (((m_video.towns_kanji_code_l - 0x20) & 0x40) << 6)
- | ((m_video.towns_kanji_code_h & 0x07) << 9);
- }
- else if(m_video.towns_kanji_code_h < 0x70)
- {
- m_video.towns_kanji_offset = (((m_video.towns_kanji_code_l & 0x1f) << 5)
- + (((m_video.towns_kanji_code_l - 0x20) & 0x60) << 9)
- + ((m_video.towns_kanji_code_h & 0x0f) << 10)
- + (((m_video.towns_kanji_code_h - 0x30) & 0x70) * 0xc00)
- + 0x8000) >> 1;
- }
- else
- {
- m_video.towns_kanji_offset = ((m_video.towns_kanji_code_l & 0x1f) << 4)
- | (((m_video.towns_kanji_code_l - 0x20) & 0x20) << 8)
- | (((m_video.towns_kanji_code_l - 0x20) & 0x40) << 6)
- | ((m_video.towns_kanji_code_h & 0x07) << 9)
- | 0x38000;
- }
-}
-
-
-uint8_t towns_state::towns_video_cff80_r(offs_t offset)
-{
- uint8_t const* const ROM = m_user->base();
-
- switch(offset)
- {
- case 0x00: // mix register
- return m_video.towns_crtc_mix;
- case 0x01: // read/write plane select (bit 0-3 write, bit 6-7 read)
- return ((m_video.towns_vram_rplane << 6) & 0xc0) | m_video.towns_vram_wplane;
- case 0x02: // display planes (bits 0-2,5), display page select (bit 4)
- return m_video.towns_display_plane | m_video.towns_display_page_sel;
- case 0x03: // VRAM page select (bit 5)
- if(m_video.towns_vram_page_sel != 0)
- return 0x10;
- else
- return 0x00;
- case 0x06:
- {
- uint8_t ret = 0x10;
- uint16_t const xpos = m_screen->hpos();
- if(xpos < m_video.towns_crtc_layerscr[0].max_x && xpos > m_video.towns_crtc_layerscr[0].min_x)
- ret |= 0x80;
- if(m_video.towns_vblank_flag != 0)
- ret |= 0x04;
- return ret;
- }
- case 0x16: // Kanji character data
- return ROM[(m_video.towns_kanji_offset << 1) + 0x180000];
- case 0x17: // Kanji character data
- return ROM[(m_video.towns_kanji_offset++ << 1) + 0x180001];
- case 0x19: // ANK CG ROM
- if(m_towns_ankcg_enable != 0)
- return 0x01;
- else
- return 0x00;
- default:
- logerror("VGA: read from invalid or unimplemented memory-mapped port %05x\n",0xcff80+offset*4);
- }
-
- return 0;
-}
-
-void towns_state::towns_video_cff80_w(offs_t offset, uint8_t data)
-{
- switch(offset)
- {
- case 0x00: // mix register
- m_video.towns_crtc_mix = data;
- break;
- case 0x01: // read/write plane select (bit 0-3 write, bit 6-7 read)
- m_video.towns_vram_wplane = data & 0x0f;
- m_video.towns_vram_rplane = (data & 0xc0) >> 6;
- towns_update_video_banks();
- //logerror("VGA: VRAM wplane select = 0x%02x\n",towns_vram_wplane);
- break;
- case 0x02: // display plane (bits 0-2), display page select (bit 4)
- m_video.towns_display_plane = data & 0x27;
- m_video.towns_display_page_sel = data & 0x10;
- break;
- case 0x03: // VRAM page select (bit 4)
- m_video.towns_vram_page_sel = data & 0x10;
- break;
- case 0x14: // Kanji offset (high)
- m_video.towns_kanji_code_h = data & 0x7f;
- towns_update_kanji_offset();
- //if(LOG_VID) logerror("VID: Kanji code set (high) = %02x %02x\n",towns_kanji_code_h,towns_kanji_code_l);
- break;
- case 0x15: // Kanji offset (low)
- m_video.towns_kanji_code_l = data & 0x7f;
- towns_update_kanji_offset();
- //if(LOG_VID) logerror("VID: Kanji code set (low) = %02x %02x\n",towns_kanji_code_h,towns_kanji_code_l);
- break;
- case 0x19: // ANK CG ROM
- m_towns_ankcg_enable = data & 0x01;
- towns_update_video_banks();
- break;
- default:
- logerror("VID: write %08x to invalid or unimplemented memory-mapped port %05x\n",data,0xcff80+offset);
- }
-}
-
-uint8_t towns_state::towns_video_cff80_mem_r(offs_t offset)
-{
- if(m_towns_mainmem_enable != 0)
- return m_ram->pointer()[offset+0xcff80];
-
- return towns_video_cff80_r(offset);
-}
-
-void towns_state::towns_video_cff80_mem_w(offs_t offset, uint8_t data)
-{
- if(m_towns_mainmem_enable != 0)
- {
- m_ram->pointer()[offset+0xcff80] = data;
- return;
- }
- towns_video_cff80_w(offset,data);
-}
-
-/*
- * port 0x440-0x443 - CRTC
- * 0x440 = register select
- * 0x442/3 = register data (16-bit)
- * 0x448 = shifter register select
- * 0x44a = shifter register data (8-bit)
- *
- */
-uint8_t towns_state::towns_video_440_r(offs_t offset)
-{
- uint8_t ret = 0;
- uint16_t xpos,ypos;
-
- switch(offset)
- {
- case 0x00:
- return m_video.towns_crtc_sel;
- case 0x02:
-// logerror("CRTC: reading register %i (0x442) [%04x]\n",towns_crtc_sel,towns_crtc_reg[towns_crtc_sel]);
- if(m_video.towns_crtc_sel == 30)
- return 0x00;
- return m_video.towns_crtc_reg[m_video.towns_crtc_sel] & 0x00ff;
- case 0x03:
-// logerror("CRTC: reading register %i (0x443) [%04x]\n",towns_crtc_sel,towns_crtc_reg[towns_crtc_sel]);
- if(m_video.towns_crtc_sel == 30)
- {
- // check video position
- xpos = m_screen->hpos();
- ypos = m_screen->vpos();
-
- if(xpos < (m_video.towns_crtc_reg[0] & 0xfe))
- ret |= 0x02;
- if(ypos < (m_video.towns_crtc_reg[6] & 0x1f))
- ret |= 0x04;
- if(xpos < m_video.towns_crtc_layerscr[0].max_x && xpos > m_video.towns_crtc_layerscr[0].min_x)
- ret |= 0x10;
- if(xpos < m_video.towns_crtc_layerscr[1].max_x && xpos > m_video.towns_crtc_layerscr[1].min_x)
- ret |= 0x20;
- if(ypos < m_video.towns_crtc_layerscr[0].max_y && ypos > m_video.towns_crtc_layerscr[0].min_y)
- ret |= 0x40;
- if(ypos < m_video.towns_crtc_layerscr[1].max_y && ypos > m_video.towns_crtc_layerscr[1].min_y)
- ret |= 0x80;
-
- return ret;
- }
- return (m_video.towns_crtc_reg[m_video.towns_crtc_sel] & 0xff00) >> 8;
- case 0x08:
- return m_video.towns_video_sel;
- case 0x0a:
- if(LOG_VID) logerror("Video: reading register %i (0x44a) [%02x]\n",m_video.towns_video_sel,m_video.towns_video_reg[m_video.towns_video_sel]);
- return m_video.towns_video_reg[m_video.towns_video_sel];
- case 0x0c:
- if(m_video.towns_dpmd_flag != 0)
- {
- m_video.towns_dpmd_flag = 0;
- ret |= 0x80;
- }
- ret |= (m_video.towns_sprite_flag ? 0x02 : 0x00); // Sprite drawing flag
- ret |= (m_video.towns_sprite_page & 0x01) ? 1 : 0;;
- return ret;
- case 0x10:
- return m_video.towns_sprite_sel;
- case 0x12:
- if(LOG_VID) logerror("SPR: reading register %i (0x452) [%02x]\n",m_video.towns_sprite_sel,m_video.towns_sprite_reg[m_video.towns_sprite_sel]);
- if(m_video.towns_sprite_sel == 6)
- return m_video.towns_sprite_page & 0x01 ? 0x10 : 0;
- return m_video.towns_sprite_reg[m_video.towns_sprite_sel];
- case 0x18:
- return m_vram_mask_addr;
- case 0x1a:
- case 0x1b:
- {
- int idx = (m_vram_mask_addr << 1) + offset - 0x1a;
- return m_vram_mask[idx];
- }
- //default:
- //if(LOG_VID) logerror("VID: read port %04x\n",offset+0x440);
- }
- return 0x00;
-}
-
-void towns_state::towns_video_440_w(offs_t offset, uint8_t data)
-{
- switch(offset)
- {
- case 0x00:
- m_video.towns_crtc_sel = data;
- break;
- case 0x02:
-// logerror("CRTC: writing register %i (0x442) [%02x]\n",towns_crtc_sel,data);
- m_video.towns_crtc_reg[m_video.towns_crtc_sel] =
- (m_video.towns_crtc_reg[m_video.towns_crtc_sel] & 0xff00) | data;
- towns_crtc_refresh_mode();
- break;
- case 0x03:
-// logerror("CRTC: writing register %i (0x443) [%02x]\n",towns_crtc_sel,data);
- if((m_video.towns_crtc_sel == 21) && (m_video.towns_sprite_reg[1] & 0x80))
- {
- m_video.towns_crtc_reg[m_video.towns_crtc_sel] =
- (m_video.towns_crtc_reg[m_video.towns_crtc_sel] & 0x80ff) | ((data & 0x7f) << 8);
- return;
- }
- m_video.towns_crtc_reg[m_video.towns_crtc_sel] =
- (m_video.towns_crtc_reg[m_video.towns_crtc_sel] & 0x00ff) | (data << 8);
- towns_crtc_refresh_mode();
- break;
- case 0x08:
- m_video.towns_video_sel = data & 0x01;
- break;
- case 0x0a:
- logerror("Video: writing register %i (0x44a) [%02x]\n",m_video.towns_video_sel,data);
- m_video.towns_video_reg[m_video.towns_video_sel] = data;
- break;
- case 0x10:
- m_video.towns_sprite_sel = data & 0x07;
- break;
- case 0x12:
- logerror("SPR: writing register %i (0x452) [%02x]\n",m_video.towns_sprite_sel,data);
- if(m_video.towns_sprite_sel == 6)
- m_video.towns_sprite_page = data & 0x80 ? 1 : 0;
- else
- m_video.towns_sprite_reg[m_video.towns_sprite_sel] = data;
- break;
- case 0x18:
- m_vram_mask_addr = data & 1;
- break;
- case 0x1a:
- case 0x1b:
- {
- int idx = (m_vram_mask_addr << 1) + offset - 0x1a;
- m_vram_mask[idx] = data;
- break;
- }
- default:
- if(LOG_VID) logerror("VID: wrote 0x%02x to port %04x\n",data,offset+0x440);
- }
-}
-
-uint8_t towns_state::towns_video_5c8_r(offs_t offset)
-{
- //if(LOG_VID) logerror("VID: read port %04x\n",offset+0x5c8);
- switch(offset)
- {
- case 0x00: // 0x5c8 - disable TVRAM?
- if(m_video.towns_tvram_enable != 0)
- {
- m_video.towns_tvram_enable = 0;
- return 0x80;
- }
- else
- return 0x00;
- }
- return 0x00;
-}
-
-void towns_state::towns_video_5c8_w(offs_t offset, uint8_t data)
-{
- switch(offset)
- {
- case 0x02: // 0x5ca - VSync clear?
- m_pic_slave->ir3_w(0);
- if(IRQ_LOG) logerror("PIC: IRQ11 (VSync) set low\n");
- //towns_vblank_flag = 0;
- break;
- }
- if(LOG_VID) logerror("VID: wrote 0x%02x to port %04x\n",data,offset+0x5c8);
-}
-
-void towns_state::towns_update_palette()
-{
- uint8_t entry = m_video.towns_palette_select;
- uint8_t r = m_video.towns_palette_r[entry];
- uint8_t g = m_video.towns_palette_g[entry];
- uint8_t b = m_video.towns_palette_b[entry];
- switch(m_video.towns_video_reg[1] & 0x30) // Palette select
- {
- case 0x00:
- case 0x20:
- m_palette16[(m_video.towns_video_reg[1] & 0x20) >> 5]->set_pen_color(entry & 0x0f, r, g, b);
- break;
- case 0x10:
- case 0x30:
- m_palette->set_pen_color(entry, r, g, b);
- break;
- }
- // chasehq wants the + 8, the real hardware appears to be less consistent, revisit if other software doesn't like it
- if(!m_screen->vblank())
- m_screen->update_partial(m_screen->vpos() + 4);
-}
-
-/* Video/CRTC
- *
- * 0xfd90 - palette colour select
- * 0xfd92/4/6 - BRG value
- * 0xfd98-9f - Digital palette registers (FMR-50 compatibility)
- */
-uint8_t towns_state::towns_video_fd90_r(offs_t offset)
-{
- uint8_t ret = 0;
- uint16_t xpos;
- palette_device* pal;
-
- if(m_video.towns_video_reg[1] & 0x10)
- pal = m_palette;
- else
- pal = m_palette16[(m_video.towns_video_reg[1] & 0x20) >> 5];
-// if(LOG_VID) logerror("VID: read port %04x\n",offset+0xfd90);
- switch(offset)
- {
- case 0x00:
- return m_video.towns_palette_select;
- case 0x02:
- return pal->pen_color(m_video.towns_palette_select).b();
- case 0x04:
- return pal->pen_color(m_video.towns_palette_select).r();
- case 0x06:
- return pal->pen_color(m_video.towns_palette_select).g();
- case 0x08:
- case 0x09:
- case 0x0a:
- case 0x0b:
- case 0x0c:
- case 0x0d:
- case 0x0e:
- case 0x0f:
- return m_video.towns_degipal[offset-0x08];
- case 0x10: // "sub status register"
- // check video position
- xpos = m_screen->hpos();
-
- if(xpos < m_video.towns_crtc_layerscr[0].max_x && xpos > m_video.towns_crtc_layerscr[0].min_x)
- ret |= 0x02;
- if(m_video.towns_vblank_flag)
- ret |= 0x01;
- return ret;
- }
- return 0x00;
-}
-
-void towns_state::towns_video_fd90_w(offs_t offset, uint8_t data)
-{
- switch(offset)
- {
- case 0x00:
- m_video.towns_palette_select = data;
- break;
- case 0x02:
- m_video.towns_palette_b[m_video.towns_palette_select] = data;
- towns_update_palette();
- break;
- case 0x04:
- m_video.towns_palette_r[m_video.towns_palette_select] = data;
- towns_update_palette();
- break;
- case 0x06:
- m_video.towns_palette_g[m_video.towns_palette_select] = data;
- towns_update_palette();
- break;
- case 0x08:
- case 0x09:
- case 0x0a:
- case 0x0b:
- case 0x0c:
- case 0x0d:
- case 0x0e:
- case 0x0f:
- m_video.towns_degipal[offset-0x08] = data;
- m_video.towns_dpmd_flag = 1;
- break;
- case 0x10:
- m_video.towns_layer_ctrl = data;
- break;
- }
- if(LOG_VID) logerror("VID: wrote 0x%02x to port %04x\n",data,offset+0xfd90);
-}
-
-uint8_t towns_state::towns_video_ff81_r()
-{
- return ((m_video.towns_vram_rplane << 6) & 0xc0) | m_video.towns_vram_wplane;
-}
-
-void towns_state::towns_video_ff81_w(uint8_t data)
-{
- m_video.towns_vram_wplane = data & 0x0f;
- m_video.towns_vram_rplane = (data & 0xc0) >> 6;
- towns_update_video_banks();
- logerror("VID: VRAM wplane select (I/O) = 0x%02x\n",m_video.towns_vram_wplane);
-}
-
-uint8_t towns_state::towns_video_unknown_r()
-{
- return 0x00;
-}
-
-/*
- * Sprite RAM, low memory
- * Writing to 0xc8xxx or 0xcaxxx activates TVRAM
- * Writing to I/O port 0x5c8 disables TVRAM
- * (bit 7 returns high if TVRAM was previously active)
- *
- * In TVRAM mode:
- * 0xc8000-0xc8fff: ASCII text (2 bytes each: ISO646 code, then attribute)
- * 0xca000-0xcafff: JIS code
- */
-uint8_t towns_state::towns_spriteram_low_r(offs_t offset)
-{
- uint8_t* RAM = m_ram->pointer();
- uint8_t* ROM = m_user->base();
-
- if(offset < 0x1000)
- { // 0xc8000-0xc8fff
- if(m_towns_mainmem_enable == 0)
- {
-// if(towns_tvram_enable == 0)
-// return towns_sprram[offset];
-// else
- return m_towns_txtvram[offset];
- }
- else
- return RAM[offset + 0xc8000];
- }
- if(offset >= 0x1000 && offset < 0x2000)
- { // 0xc9000-0xc9fff
- return RAM[offset + 0xc9000];
- }
- if(offset >= 0x2000 && offset < 0x3000)
- { // 0xca000-0xcafff
- if(m_towns_mainmem_enable == 0)
- {
- if(m_towns_ankcg_enable != 0 && offset < 0x2800)
- return ROM[0x180000 + 0x3d000 + (offset-0x2000)];
-// if(towns_tvram_enable == 0)
-// return m_towns_sprram[offset];
-// else
- return m_towns_txtvram[offset];
- }
- else
- return RAM[offset + 0xca000];
- }
- return 0x00;
-}
-
-void towns_state::towns_spriteram_low_w(offs_t offset, uint8_t data)
-{
- uint8_t* RAM = m_ram->pointer();
-
- if(offset < 0x1000)
- { // 0xc8000-0xc8fff
- m_video.towns_tvram_enable = 1;
- if(m_towns_mainmem_enable == 0)
- m_towns_txtvram[offset] = data;
- else
- RAM[offset + 0xc8000] = data;
- }
- if(offset >= 0x1000 && offset < 0x2000)
- {
- RAM[offset + 0xc9000] = data;
- }
- if(offset >= 0x2000 && offset < 0x3000)
- { // 0xca000-0xcafff
- m_video.towns_tvram_enable = 1;
- if(m_towns_mainmem_enable == 0)
- m_towns_txtvram[offset] = data;
- else
- RAM[offset + 0xca000] = data;
- }
-}
-
-uint8_t towns_state::towns_spriteram_r(offs_t offset)
-{
- return m_towns_txtvram[offset];
-}
-
-void towns_state::towns_spriteram_w(offs_t offset, uint8_t data)
-{
- m_towns_txtvram[offset] = data;
-}
-
-/*
- * Sprites
- *
- * Max. 1024, 16x16, 16 colours per sprite
- * 128kB Sprite RAM (8kB attributes, 120kB pattern/colour data)
- * Sprites are rendered directly to VRAM layer 1 (VRAM offset 0x40000 or 0x60000)
- *
- * Sprite RAM format:
- * 4 words per sprite
- * +0: X position (10-bit)
- * +2: Y position (10-bit)
- * +4: Sprite Attribute
- * bit 15: enforce offsets (regs 2-5)
- * bit 12,13,14: flip / rotate sprite
- * When the rotate bit (14) is set, the X and Y coordinates are swapped when rendering the sprite to VRAM.
- * By combining it with the flip bits, the sprite can be rotated in 90 degree increments, both mirrored and unmirrored.
- * bits 10,11: half-size
- * bits 9-0: Sprite RAM offset containing sprite pattern
- * +6: Sprite Colour
- * bit 15: use colour data in located in sprite RAM offset in bits 11-0 (x32)
- */
-void towns_state::render_sprite_4(uint32_t poffset, uint32_t coffset, uint16_t x, uint16_t y, bool xflip, bool yflip, bool xhalfsize, bool yhalfsize, bool rotation, const rectangle* rect)
-{
- uint16_t xpos,ypos;
- uint16_t col,pixel;
- uint32_t vbase = m_video.towns_sprite_page ? 0x20000 : 0, voffset;
- uint16_t xstart,xend,ystart,yend;
- int linesize = m_video.towns_crtc_reg[24] * 4;
- int xdir,ydir;
-
- if (rotation)
- {
- std::swap (x,y);
- std::swap (xflip,yflip);
- }
-
- if(xflip)
- {
- if (xhalfsize)
- {
- xstart = x+6;
- xdir = -1;
- }
- else
- {
- xstart = x+14;
- xdir = -2;
- }
- xend = x-2;
- }
- else
- {
- xstart = x+1;
- if (xhalfsize)
- {
- xend = x+9;
- xdir = 1;
- }
- else
- {
- xend = x+17;
- xdir = 2;
- }
- }
- if(yflip)
- {
- if (yhalfsize)
- ystart = y+7;
- else
- ystart = y+15;
- yend = y-1;
- ydir = -1;
- }
- else
- {
- ystart = y;
- if (yhalfsize)
- yend = y+8;
- else
- yend = y+16;
- ydir = 1;
- }
- xstart &= 0x1ff;
- xend &= 0x1ff;
- ystart &= 0x1ff;
- yend &= 0x1ff;
- poffset &= 0x1ffff;
-
- for(ypos=ystart;ypos!=yend;ypos+=ydir,ypos&=0x1ff)
- {
- for(xpos=xstart;xpos!=xend;xpos+=xdir,xpos&=0x1ff)
- {
-
- voffset = 0;
- pixel = (m_towns_txtvram[poffset] & 0xf0) >> 4;
- col = (m_towns_txtvram[coffset+(pixel*2)] | (m_towns_txtvram[coffset+(pixel*2)+1] << 8)) & 0x7fff;
- if (rotation)
- {
- voffset += linesize * (xpos & 0x1ff); // scanline size in bytes * y pos
- voffset += (ypos & 0x1ff) * 2;
- }
- else
- {
- voffset += linesize * (ypos & 0x1ff); // scanline size in bytes * y pos
- voffset += (xpos & 0x1ff) * 2;
- }
- if(voffset < 0x20000 && xpos < 256 && ypos < 256 && pixel != 0 && voffset > linesize)
- {
- m_towns_gfxvram[0x40000+voffset+vbase+1] = (col & 0xff00) >> 8;
- m_towns_gfxvram[0x40000+voffset+vbase] = col & 0x00ff;
- }
-
- if (!xhalfsize)
- {
- if(xflip)
- if (rotation)
- voffset+=(m_video.towns_crtc_reg[24] * 4);
- else
- voffset+=2;
- else
- if (rotation)
- voffset-=(m_video.towns_crtc_reg[24] * 4);
- else
- voffset-=2;
-
- pixel = m_towns_txtvram[poffset] & 0x0f;
- col = (m_towns_txtvram[coffset+(pixel*2)] | (m_towns_txtvram[coffset+(pixel*2)+1] << 8)) & 0x7fff;
- if(voffset < 0x20000 && xpos < 256 && ypos < 256 && pixel != 0 && voffset > linesize)
- {
- m_towns_gfxvram[0x40000+voffset+vbase+1] = (col & 0xff00) >> 8;
- m_towns_gfxvram[0x40000+voffset+vbase] = col & 0x00ff;
- }
- }
-
- poffset++;
- poffset &= 0x1ffff;
- }
- if (yhalfsize)
- {
- poffset+=8;
- }
- }
-}
-
-void towns_state::render_sprite_16(uint32_t poffset, uint16_t x, uint16_t y, bool xflip, bool yflip, bool xhalfsize, bool yhalfsize, bool rotation, const rectangle* rect)
-{
- uint16_t xpos,ypos;
- uint16_t col;
- uint32_t vbase = m_video.towns_sprite_page ? 0x20000 : 0, voffset;
- uint16_t xstart,ystart,xend,yend;
- int linesize = m_video.towns_crtc_reg[24] * 4;
- int xdir,ydir;
-
- if (rotation)
- {
- std::swap (x,y);
- std::swap (xflip,yflip);
- }
-
- if(xflip)
- {
- if (xhalfsize)
- xstart = x+7;
- else
- xstart = x+15;
- xend = x-1;
- xdir = -1;
- }
- else
- {
- xstart = x;
- if (xhalfsize)
- xend = x+8;
- else
- xend = x+16;
- xdir = 1;
- }
- if(yflip)
- {
- if (yhalfsize)
- ystart = y+7;
- else
- ystart = y+15;
- yend = y-1;
- ydir = -1;
- }
- else
- {
- ystart = y;
- if (yhalfsize)
- yend = y+8;
- else
- yend = y+16;
- ydir = 1;
- }
- xstart &= 0x1ff;
- xend &= 0x1ff;
- ystart &= 0x1ff;
- yend &= 0x1ff;
- poffset &= 0x1ffff;
-
- for(ypos=ystart;ypos!=yend;ypos+=ydir,ypos&=0x1ff)
- {
- for(xpos=xstart;xpos!=xend;xpos+=xdir,xpos&=0x1ff)
- {
- voffset = 0;
- col = m_towns_txtvram[poffset] | (m_towns_txtvram[poffset+1] << 8);
- if (rotation)
- {
- voffset += linesize * (xpos & 0x1ff); // scanline size in bytes * y pos
- voffset += (ypos & 0x1ff) * 2;
- }
- else
- {
- voffset += linesize * (ypos & 0x1ff); // scanline size in bytes * y pos
- voffset += (xpos & 0x1ff) * 2;
- }
- if(voffset < 0x20000 && xpos < 256 && ypos < 256 && col< 0x8000 && voffset > linesize)
- {
- m_towns_gfxvram[0x40000+vbase+voffset+1] = (col & 0xff00) >> 8;
- m_towns_gfxvram[0x40000+vbase+voffset] = col & 0x00ff;
- }
- if (xhalfsize)
- poffset+=4;
- else
- poffset+=2;
- poffset &= 0x1ffff;
- }
-
- if (yhalfsize)
- poffset+=16;
- }
-}
-
-void towns_state::draw_sprites()
-{
- uint16_t sprite_limit = (m_video.towns_sprite_reg[0] | (m_video.towns_sprite_reg[1] << 8)) & 0x3ff;
- uint16_t xoff = (m_video.towns_sprite_reg[2] | (m_video.towns_sprite_reg[3] << 8)) & 0x1ff;
- uint16_t yoff = (m_video.towns_sprite_reg[4] | (m_video.towns_sprite_reg[5] << 8)) & 0x1ff;
- uint32_t poffset,coffset;
- const rectangle *rect = &m_video.towns_crtc_layerscr[1];
- int linesize = m_video.towns_crtc_reg[24] * 4;
-
- // TODO: I'm not confident about this but based on the behavior of aburner and rbisland, it's probably in the ballpark
- // aburner writes the backgound color from 0 to 0x400 in both pages while rbisland from 0 to 0x800 (What's the difference?)
- // it's only written when the color changes so the sprite engine has to be prevented from writing there
- uint8_t *vram;
- if(m_video.towns_sprite_page == 0)
- vram = m_towns_gfxvram.get() + 0x40000;
- else
- vram = m_towns_gfxvram.get() + 0x60000;
-
- for(int i = linesize; i < 0x20000; i += linesize)
- memcpy(vram + i, vram, linesize);
-
- for(int n=sprite_limit;n<1024;n++)
- {
- uint16_t x = m_towns_txtvram[8*n] | (m_towns_txtvram[8*n+1] << 8);
- uint16_t y = m_towns_txtvram[8*n+2] | (m_towns_txtvram[8*n+3] << 8);
- uint16_t attr = m_towns_txtvram[8*n+4] | (m_towns_txtvram[8*n+5] << 8);
- uint16_t colour = m_towns_txtvram[8*n+6] | (m_towns_txtvram[8*n+7] << 8);
- bool xflip = (attr & 0x2000) >> 13;
- bool yflip = (attr & 0x1000) >> 12;
- bool rotation = (attr & 0x4000) >> 14;
- bool xhalfsize = (attr & 0x400) >> 10;
- bool yhalfsize = (attr & 0x800) >> 11;
-
- if(attr & 0x8000)
- {
- x += xoff;
- y += yoff;
- }
- x &= 0x1ff;
- y &= 0x1ff;
-
- if(colour & 0x8000)
- {
- poffset = (attr & 0x3ff) << 7;
- coffset = (colour & 0xfff) << 5;
-#ifdef SPR_DEBUG
- logerror("Sprite4 #%i, X %i Y %i Attr %04x Col %04x Poff %08x Coff %08x\n",
- n,x,y,attr,colour,poffset,coffset);
-#endif
- if(!(colour & 0x2000))
- render_sprite_4((poffset)&0x1ffff,coffset,x,y,xflip,yflip,xhalfsize,yhalfsize,rotation,rect);
- }
- else
- {
- poffset = (attr & 0x3ff) << 7;
-#ifdef SPR_DEBUG
- logerror("Sprite16 #%i, X %i Y %i Attr %04x Col %04x Poff %08x\n",
- n,x,y,attr,colour,poffset);
-#endif
- if(!(colour & 0x2000))
- render_sprite_16((poffset)&0x1ffff,x,y,xflip,yflip,xhalfsize,yhalfsize,rotation,rect);
- }
- }
- m_video.towns_sprite_flag = 0;
-}
-
-void towns_state::towns_crtc_draw_scan_layer_hicolour(bitmap_rgb32 &bitmap,const rectangle* rect,int layer,int line,int scanline)
-{
- uint32_t off = 0;
- uint16_t colour;
- int hzoom = 1;
- int linesize;
- uint32_t scroll;
- int page = 0;
- bool sphscroll = !(m_video.towns_crtc_reg[28] & (layer ? 0x20 : 0x10));
-
- if(m_video.towns_video_reg[0] & 0x10)
- {
- if(layer == 0)
- linesize = m_video.towns_crtc_reg[20] * 4;
- else
- linesize = m_video.towns_crtc_reg[24] * 4;
- }
- else
- linesize = m_video.towns_crtc_reg[20] * 8;
-
- if(m_video.towns_display_page_sel != 0)
- {
- off = 0x20000;
- page = 1;
- }
-
-// if((layer == 1) && (m_video.towns_sprite_reg[1] & 0x80) && (m_video.towns_sprite_page == 1))
-// off = 0x20000;
-
- if(layer != 0)
- {
- if(!(m_video.towns_video_reg[0] & 0x10))
- return;
- if(!sphscroll)
- off += (m_video.towns_crtc_reg[21]) << 2; // initial offset
- else
- {
- scroll = ((m_video.towns_crtc_reg[21] & 0xfc00) << 2) | (((m_video.towns_crtc_reg[21] & 0x3ff) << 2));
- off += scroll;
- }
- hzoom = ((m_video.towns_crtc_reg[27] & 0x0f00) >> 8) + 1;
- off += (float)(m_video.towns_crtc_reg[11] - m_video.towns_crtc_reg[22]) * (2.0f / (float)hzoom);
- }
- else
- {
- if(!sphscroll)
- off += (m_video.towns_crtc_reg[17]) << 2; // initial offset
- else
- {
- scroll = ((m_video.towns_crtc_reg[17] & 0xfc00) << 2) | (((m_video.towns_crtc_reg[17] & 0x3ff) << 2));
- off += scroll;
- }
- hzoom = (m_video.towns_crtc_reg[27] & 0x000f) + 1;
- off += (float)(m_video.towns_crtc_reg[9] - m_video.towns_crtc_reg[18]) * (2.0f / (float)hzoom);
- }
-
- off += line * linesize;
- off &= ~1;
-
- for(int x=rect->min_x;x<rect->max_x;x+=hzoom)
- {
- int offpage;
- int curoff;
- if(m_video.towns_video_reg[0] & 0x10)
- {
- curoff = off & 0x3ffff;
- offpage = layer;
- }
- else
- {
- offpage = (off & 4) >> 2;
- curoff = ((off & 0x7fff8) >> 1) | (off & 3);
- }
- colour = (m_towns_gfxvram[curoff+(offpage*0x40000)+1] << 8) | m_towns_gfxvram[curoff+(offpage*0x40000)];
- if(!(m_video.towns_video_reg[0] & 0x10) || (m_video.towns_video_reg[1] & 0x01) != layer || colour < 0x8000)
- {
- for (int pixel = 0; pixel < hzoom; pixel++)
- bitmap.pix(scanline, x+pixel) =
- ((colour & 0x001f) << 3)
- | ((colour & 0x7c00) << 1)
- | ((colour & 0x03e0) << 14);
- }
- off+=2;
- if ((off - (page * 0x20000)) % linesize == 0 && sphscroll)
- off -= linesize;
- }
-}
-
-void towns_state::towns_crtc_draw_scan_layer_256(bitmap_rgb32 &bitmap,const rectangle* rect,int line,int scanline)
-{
- int off = 0;
- uint8_t colour;
- int hzoom = 1;
- int linesize;
- uint32_t scroll;
- int page = 0;
- bool sphscroll = !(m_video.towns_crtc_reg[28] & 0x10);
-
- if(m_video.towns_display_page_sel != 0)
- {
- off = 0x20000;
- page = 1;
- }
-
- linesize = m_video.towns_crtc_reg[20] * 4;
-
- if(!sphscroll)
- off += m_video.towns_crtc_reg[17] << 2; // initial offset
- else
- {
- scroll = ((m_video.towns_crtc_reg[17] & 0xfc00) << 2) | (((m_video.towns_crtc_reg[17] & 0x3ff) << 2));
- off += scroll;
- }
- hzoom = (m_video.towns_crtc_reg[27] & 0x000f) + 1;
- int subpix = (m_video.towns_crtc_reg[9] - m_video.towns_crtc_reg[18]) / hzoom;
-
- off += line * linesize;
- off += (subpix >> 1) & ~3;
- subpix = subpix & 7;
-
- for(int x=rect->min_x;x<rect->max_x;x+=hzoom)
- {
- off &= 0x3ffff;
- colour = m_towns_gfxvram[off+(subpix >= 4 ? (subpix & 3)+0x40000 : subpix)];
- for (int pixel = 0; pixel < hzoom; pixel++)
- bitmap.pix(scanline, x+pixel) = m_palette->pen(colour);
- subpix++;
- if(subpix == 8)
- {
- off += 4;
- subpix = 0;
- }
- if ((off - (page * 0x20000)) % linesize == 0 && subpix == 0 && sphscroll)
- off -= linesize;
- }
-}
-
-void towns_state::towns_crtc_draw_scan_layer_16(bitmap_rgb32 &bitmap,const rectangle* rect,int layer,int line,int scanline)
-{
- int off = 0;
- int hzoom = 1;
- uint32_t scroll;
- int page = 0;
- palette_device* pal = m_palette16[layer];
- bool sphscroll = !(m_video.towns_crtc_reg[28] & (layer ? 0x20 : 0x10));
-
- if(m_video.towns_display_page_sel != 0)
- {
- off = 0x20000;
- page = 1;
- }
-
- bool bottom_layer = (m_video.towns_video_reg[1] & 0x01) != layer;
-
-// if((layer == 1) && (m_video.towns_sprite_reg[1] & 0x80) && (m_video.towns_sprite_page == 1))
-// off = 0x20000;
-
- int linesize;
- if(layer == 0)
- linesize = m_video.towns_crtc_reg[20] * 4;
- else
- linesize = m_video.towns_crtc_reg[24] * 4;
-
- if(layer != 0)
- {
- if(!(m_video.towns_video_reg[0] & 0x10))
- return;
- if(!sphscroll)
- off += m_video.towns_crtc_reg[21] << 2; // initial offset
- else
- {
- scroll = ((m_video.towns_crtc_reg[21] & 0xfc00)<<2) | (((m_video.towns_crtc_reg[21] & 0x3ff)<<2));
- off += scroll;
- }
- hzoom = ((m_video.towns_crtc_reg[27] & 0x0f00) >> 8) + 1;
- off += (m_video.towns_crtc_reg[11] - m_video.towns_crtc_reg[22]) / (hzoom * 2);
- }
- else
- {
- if(!sphscroll)
- off += m_video.towns_crtc_reg[17] << 2; // initial offset
- else
- {
- scroll = ((m_video.towns_crtc_reg[17] & 0xfc00)<<2) | (((m_video.towns_crtc_reg[17] & 0x3ff)<<2));
- off += scroll;
- }
- hzoom = (m_video.towns_crtc_reg[27] & 0x000f) + 1;
- off += (m_video.towns_crtc_reg[9] - m_video.towns_crtc_reg[18]) / (hzoom * 2);
- }
-
- off += line * linesize;
-
- for(int x=rect->min_x;x<rect->max_x;x+=hzoom*2)
- {
- if(m_video.towns_video_reg[0] & 0x10)
- off &= 0x3ffff; // 2 layers
- else
- off &= 0x7ffff; // 1 layer
- uint8_t colour;
- colour = m_towns_gfxvram[off+(layer*0x40000)] >> 4;
- if(colour != 0 || bottom_layer)
- {
- for (int pixel = 0; pixel < hzoom; pixel++)
- bitmap.pix(scanline, x+hzoom+pixel) = pal->pen(colour);
- }
- colour = m_towns_gfxvram[off+(layer*0x40000)] & 0x0f;
- if(colour != 0 || bottom_layer)
- {
- for (int pixel = 0; pixel < hzoom; pixel++)
- bitmap.pix(scanline, x+pixel) = pal->pen(colour);
- }
- off++;
- if ((off - (page * 0x20000)) % linesize == 0 && sphscroll)
- off -= linesize;
- }
-}
-
-void towns_state::towns_crtc_draw_layer(bitmap_rgb32 &bitmap,const rectangle* rect,int layer)
-{
- int scanline;
- int bottom;
- int top;
- uint8_t zoom;
- uint8_t count;
-
- if(layer == 0)
- {
- scanline = rect->min_y;
- top = (scanline - m_video.towns_crtc_layerscr[0].min_y);
- bottom = (rect->max_y - rect->min_y) + top;
- zoom = ((m_video.towns_crtc_reg[27] & 0x00f0) >> 4) + 1;
- count = top % zoom;
- bottom /= zoom;
- top /= zoom;
- switch(m_video.towns_video_reg[0] & 0x03)
- {
- case 0x01:
- for(int line=top;line<=bottom;line++)
- {
- do
- {
- towns_crtc_draw_scan_layer_16(bitmap,rect,layer,line,scanline);
- scanline++;
- count++;
- } while(count < zoom);
- count = 0;
- }
- break;
- case 0x02:
- for(int line=top;line<=bottom;line++)
- {
- do
- {
- towns_crtc_draw_scan_layer_256(bitmap,rect,line,scanline);
- scanline++;
- count++;
- } while(count < zoom);
- count = 0;
- }
- break;
- case 0x03:
- for(int line=top;line<=bottom;line++)
- {
- do
- {
- towns_crtc_draw_scan_layer_hicolour(bitmap,rect,layer,line,scanline);
- scanline++;
- count++;
- } while(count < zoom);
- count = 0;
- }
- break;
- }
- }
- else
- {
- scanline = rect->min_y;
- top = (scanline - m_video.towns_crtc_layerscr[1].min_y);
- bottom = (rect->max_y - rect->min_y) + top;
- zoom = ((m_video.towns_crtc_reg[27] & 0xf000) >> 12) + 1;
- count = top % zoom;
- bottom /= zoom;
- top /= zoom;
- switch(m_video.towns_video_reg[0] & 0x0c)
- {
- case 0x04:
- for(int line=top;line<=bottom;line++)
- {
- do
- {
- towns_crtc_draw_scan_layer_16(bitmap,rect,layer,line,scanline);
- scanline++;
- count++;
- } while(count < zoom);
- count = 0;
- }
- break;
- case 0x0c:
- for(int line=top;line<=bottom;line++)
- {
- do
- {
- towns_crtc_draw_scan_layer_hicolour(bitmap,rect,layer,line,scanline);
- scanline++;
- count++;
- } while(count < zoom);
- count = 0;
- }
- break;
- }
- }
-}
-
-void towns_state::render_text_char(uint8_t x, uint8_t y, uint8_t ascii, uint16_t jis, uint8_t attr)
-{
- uint32_t rom_addr;
- uint32_t vram_addr;
- uint16_t linesize = m_video.towns_crtc_reg[24] * 4;
- uint8_t code_h,code_l;
- uint8_t* font_rom = m_user->base();
-
- // all characters are 16 pixels high
- vram_addr = (x * 4) + (y * (linesize * 16));
-
- if((attr & 0xc0) == 0)
- rom_addr = 0x3d800 + (ascii * 128);
- else
- {
- code_h = (jis & 0xff00) >> 8;
- code_l = jis & 0x00ff;
- if(code_h < 0x30)
- {
- rom_addr = ((code_l & 0x1f) << 4)
- | (((code_l - 0x20) & 0x20) << 8)
- | (((code_l - 0x20) & 0x40) << 6)
- | ((code_h & 0x07) << 9);
- }
- else if(code_h < 0x70)
- {
- rom_addr = ((code_l & 0x1f) << 4)
- + (((code_l - 0x20) & 0x60) << 8)
- + ((code_h & 0x0f) << 9)
- + (((code_h - 0x30) & 0x70) * 0xc00)
- + 0x8000;
- }
- else
- {
- rom_addr = ((code_l & 0x1f) << 4)
- | (((code_l - 0x20) & 0x20) << 8)
- | (((code_l - 0x20) & 0x40) << 6)
- | ((code_h & 0x07) << 9)
- | 0x38000;
- }
- }
- uint8_t colour = attr & 0x07;
- if(attr & 0x20)
- colour |= 0x08;
-
- for(int a=0;a<16;a++) // for each scanline
- {
- uint8_t data;
- if((attr & 0xc0) == 0)
- data = font_rom[0x180000 + rom_addr + a];
- else if((attr & 0xc0) == 0x80)
- data = font_rom[0x180000 + rom_addr + (a*2)];
- else
- data = font_rom[0x180000 + rom_addr + (a*2) + 1];
-
- if(attr & 0x08)
- data = ~data; // inverse
-
- // and finally, put the data in VRAM
- for(int b=0;b<8;b+=2)
- {
- uint8_t temp = 0;
- if(data & (1<<b))
- temp |= ((colour & 0x0f) << 4);
- if(data & (1<<(b+1)))
- temp |= (colour & 0x0f);
- //m_towns_gfxvram[0x40000+vram_addr+(b/2)] = temp;
- }
-
- vram_addr += linesize;
- vram_addr &= 0x3ffff;
- }
-}
-
-void towns_state::draw_text_layer()
-{
-/*
- * Text format
- * 2 bytes per character at both 0xc8000 and 0xca000
- * 0xc8xxx: Byte 1: ASCII character
- * Byte 2: Attributes
- * bits 2-0: GRB (or is it BRG?)
- * bit 3: Inverse
- * bit 4: Blink
- * bit 5: high brightness
- * bits 7-6: Kanji high/low
- *
- * If either bits 6 or 7 are high, then a fullwidth Kanji character is displayed
- * at this location. The character displayed is represented by a 2-byte
- * JIS code at the same offset at 0xca000.
- *
- * The video hardware renders text to VRAM layer 1, there is no separate text layer
- */
- int c = 0;
-
- for(int y=0;y<40;y++)
- {
- for(int x=0;x<80;x++)
- {
- render_text_char(x,y,m_towns_txtvram[c],((m_towns_txtvram[c+0x2000] << 8)|(m_towns_txtvram[c+0x2001])),m_towns_txtvram[c+1]);
- c+=2;
- }
- }
-}
-
-void towns_state::towns_sprite_start()
-{
- uint16_t sprite_limit = (m_video.towns_sprite_reg[0] | (m_video.towns_sprite_reg[1] << 8)) & 0x3ff;
- m_video.towns_sprite_flag = 1; // we are now drawing
- m_video.sprite_timer->adjust(attotime::from_usec(32 + 75 * (1024 - sprite_limit)));
-}
-
-TIMER_CALLBACK_MEMBER(towns_state::towns_vblank_end)
-{
- // here we'll clear the vsync signal, I presume it goes low on it's own eventually
- m_pic_slave->ir3_w(0); // IRQ11 = VSync
- if(IRQ_LOG) logerror("PIC: IRQ11 (VSync) set low\n");
- m_video.towns_vblank_flag = 0;
-}
-
-INTERRUPT_GEN_MEMBER(towns_state::towns_vsync_irq)
-{
- m_pic_slave->ir3_w(1); // IRQ11 = VSync
- if(IRQ_LOG) logerror("PIC: IRQ11 (VSync) set high\n");
- m_video.towns_vblank_flag = 1;
- machine().scheduler().timer_set(m_screen->time_until_vblank_end(), timer_expired_delegate(FUNC(towns_state::towns_vblank_end),this), 0, (void*)m_pic_slave);
- if(m_video.towns_tvram_enable)
- draw_text_layer();
- if((m_video.towns_sprite_reg[1] & 0x80) && !m_video.towns_sprite_flag)
- {
- if(m_video.towns_sprite_page == 0) // flip VRAM page
- {
- m_video.towns_sprite_page = 1;
- m_video.towns_crtc_reg[21] &= ~0x8000;
- }
- else
- {
- m_video.towns_sprite_page = 0;
- m_video.towns_crtc_reg[21] |= 0x8000;
- }
- towns_sprite_start();
- }
-}
-
-void towns_state::video_start()
-{
- m_video.towns_vram_wplane = 0x00;
- m_video.towns_sprite_page = 0;
- m_video.sprite_timer = timer_alloc(TIMER_SPRITES);
-}
-
-uint32_t towns_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
-{
- bool layer1_en = true, layer2_en = true;
- bitmap.fill(0x00000000, cliprect);
-
- if(LAYER_DISABLE)
- {
- if(machine().input().code_pressed(KEYCODE_Q))
- layer1_en = false;
- if(machine().input().code_pressed(KEYCODE_W))
- layer2_en = false;
- }
-
- rectangle cliplayer0 = m_video.towns_crtc_layerscr[0];
- cliplayer0 &= cliprect;
- rectangle cliplayer1 = m_video.towns_crtc_layerscr[1];
- cliplayer1 &= cliprect;
-
- if(!(m_video.towns_video_reg[1] & 0x01))
- {
- if((m_video.towns_layer_ctrl & 0x03) != 0 && layer1_en)
- towns_crtc_draw_layer(bitmap,&cliplayer1,1);
- if((m_video.towns_layer_ctrl & 0x0c) != 0 && layer2_en)
- towns_crtc_draw_layer(bitmap,&cliplayer0,0);
- }
- else
- {
- if((m_video.towns_layer_ctrl & 0x0c) != 0 && layer1_en)
- towns_crtc_draw_layer(bitmap,&cliplayer0,0);
- if((m_video.towns_layer_ctrl & 0x03) != 0 && layer2_en)
- towns_crtc_draw_layer(bitmap,&cliplayer1,1);
- }
-
-#if 0
-#ifdef SPR_DEBUG
- if(machine().input().code_pressed(KEYCODE_O))
- pshift+=0x80;
- if(machine().input().code_pressed(KEYCODE_I))
- pshift-=0x80;
- popmessage("Pixel shift = %08x",pshift);
-#endif
-#endif
-
-#ifdef CRTC_REG_DISP
- popmessage("CRTC: %i %i %i %i %i %i %i %i %i\n%i %i %i %i | %i %i %i %i\n%04x %i %i %i | %04x %i %i %i\nZOOM: %04x\nVideo: %02x %02x\nText=%i Spr=%02x\nReg28=%04x",
- m_video.towns_crtc_reg[0],m_video.towns_crtc_reg[1],m_video.towns_crtc_reg[2],m_video.towns_crtc_reg[3],
- m_video.towns_crtc_reg[4],m_video.towns_crtc_reg[5],m_video.towns_crtc_reg[6],m_video.towns_crtc_reg[7],
- m_video.towns_crtc_reg[8],
- m_video.towns_crtc_reg[9],m_video.towns_crtc_reg[10],m_video.towns_crtc_reg[11],m_video.towns_crtc_reg[12],
- m_video.towns_crtc_reg[13],m_video.towns_crtc_reg[14],m_video.towns_crtc_reg[15],m_video.towns_crtc_reg[16],
- m_video.towns_crtc_reg[17],m_video.towns_crtc_reg[18],m_video.towns_crtc_reg[19],m_video.towns_crtc_reg[20],
- m_video.towns_crtc_reg[21],m_video.towns_crtc_reg[22],m_video.towns_crtc_reg[23],m_video.towns_crtc_reg[24],
- m_video.towns_crtc_reg[27],m_video.towns_video_reg[0],m_video.towns_video_reg[1],m_video.towns_tvram_enable,m_video.towns_sprite_reg[1] & 0x80,
- m_video.towns_crtc_reg[28]);
-#endif
-
- return 0;
-}