diff options
author | 2012-08-21 10:41:19 +0000 | |
---|---|---|
committer | 2012-08-21 10:41:19 +0000 | |
commit | 7285b359d259b2ae0fdf85096571c386ec8c991a (patch) | |
tree | a027aff57f1a255f9ec6cfd3b68cabe4b6683998 /src/mess/video/samcoupe.c | |
parent | 67c425e90757876a6716b7867df30c0149912e74 (diff) |
Merge of MESS sources (no whatsnew)
Diffstat (limited to 'src/mess/video/samcoupe.c')
-rw-r--r-- | src/mess/video/samcoupe.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/src/mess/video/samcoupe.c b/src/mess/video/samcoupe.c new file mode 100644 index 00000000000..4f8c05e25e9 --- /dev/null +++ b/src/mess/video/samcoupe.c @@ -0,0 +1,176 @@ +/*************************************************************************** + + SAM Coupe + + Functions to emulate the video hardware + +***************************************************************************/ + +#include "emu.h" +#include "includes/samcoupe.h" + + +/*************************************************************************** + MACROS +***************************************************************************/ + +/* border color from border register */ +#define BORDER_COLOR(x) ((x & 0x20) >> 2 | (x & 0x07)) + +/* foreground and background color from attribute byte in mode 1 and 2 */ +#define ATTR_BG(x) ((x >> 3) & 0x07) +#define ATTR_FG(x) (((x >> 3) & 0x08) | (x & 0x07)) + + +/*************************************************************************** + IMPLEMENTATION +***************************************************************************/ + +void samcoupe_state::video_start() +{ + machine().primary_screen->register_screen_bitmap(m_bitmap); +} + +UINT32 samcoupe_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +{ + copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect); + return 0; +} + +static void draw_mode4_line(running_machine &machine, int y, int hpos) +{ + samcoupe_state *state = machine.driver_data<samcoupe_state>(); + UINT8 *videoram = state->m_videoram; + + /* get start address */ + UINT8 *vram = videoram + ((y - SAM_BORDER_TOP) * 128) + ((hpos - SAM_BORDER_LEFT) / 4); + + for (int i = 0; i < (SAM_BLOCK*2)/4; i++) + { + /* draw 2 pixels (doublewidth) */ + state->m_bitmap.pix16(y, hpos + i * 4 + 0) = state->m_clut[(*vram >> 4) & 0x0f]; + state->m_bitmap.pix16(y, hpos + i * 4 + 1) = state->m_clut[(*vram >> 4) & 0x0f]; + state->m_bitmap.pix16(y, hpos + i * 4 + 2) = state->m_clut[(*vram >> 0) & 0x0f]; + state->m_bitmap.pix16(y, hpos + i * 4 + 3) = state->m_clut[(*vram >> 0) & 0x0f]; + + /* move to next address */ + vram++; + + /* attribute register contains the third displayed byte */ + if (i == 2) + state->m_attribute = *vram; + } +} + +static void draw_mode3_line(running_machine &machine, int y, int hpos) +{ + samcoupe_state *state = machine.driver_data<samcoupe_state>(); + UINT8 *videoram = state->m_videoram; + + /* get start address */ + UINT8 *vram = videoram + ((y - SAM_BORDER_TOP) * 128) + ((hpos - SAM_BORDER_LEFT) / 4); + + for (int i = 0; i < (SAM_BLOCK*2)/4; i++) + { + /* draw 4 pixels */ + state->m_bitmap.pix16(y, hpos + i * 4 + 0) = state->m_clut[(*vram >> 6) & 0x03]; + state->m_bitmap.pix16(y, hpos + i * 4 + 1) = state->m_clut[(*vram >> 4) & 0x03]; + state->m_bitmap.pix16(y, hpos + i * 4 + 2) = state->m_clut[(*vram >> 2) & 0x03]; + state->m_bitmap.pix16(y, hpos + i * 4 + 3) = state->m_clut[(*vram >> 0) & 0x03]; + + /* move to next address */ + vram++; + + /* attribute register contains the third displayed byte */ + if (i == 2) + state->m_attribute = *vram; + } +} + +static void draw_mode12_block(samcoupe_state *state, bitmap_ind16 &bitmap, int vpos, int hpos, UINT8 mask) +{ + /* extract colors from attribute */ + UINT8 ink = state->m_clut[ATTR_FG(state->m_attribute)]; + UINT8 pap = state->m_clut[ATTR_BG(state->m_attribute)]; + + /* draw block of 8 pixels (doubled to 16) */ + for (int i = 0; i < SAM_BLOCK; i++) + { + bitmap.pix16(vpos, hpos + i*2 + 0) = BIT(mask, 7 - i) ? ink : pap; + bitmap.pix16(vpos, hpos + i*2 + 1) = BIT(mask, 7 - i) ? ink : pap; + } +} + +static void draw_mode2_line(running_machine &machine, int y, int hpos) +{ + samcoupe_state *state = machine.driver_data<samcoupe_state>(); + UINT8 *videoram = state->m_videoram; + + int cell = (y - SAM_BORDER_TOP) * 32 + (hpos - SAM_BORDER_LEFT) / SAM_BLOCK / 2; + + UINT8 mask = videoram[cell]; + state->m_attribute = videoram[cell + 0x2000]; + + draw_mode12_block(state, state->m_bitmap, y, hpos, mask); +} + +static void draw_mode1_line(running_machine &machine, int y, int hpos) +{ + samcoupe_state *state = machine.driver_data<samcoupe_state>(); + UINT8 *videoram = state->m_videoram; + + UINT8 mask = videoram[((((y - SAM_BORDER_TOP) & 0xc0) << 5) | (((y - SAM_BORDER_TOP) & 0x07) << 8) | (((y - SAM_BORDER_TOP) & 0x38) << 2)) + (hpos - SAM_BORDER_LEFT) / SAM_BLOCK / 2]; + state->m_attribute = videoram[32*192 + (((y - SAM_BORDER_TOP) & 0xf8) << 2) + (hpos - SAM_BORDER_LEFT) / SAM_BLOCK / 2]; + + draw_mode12_block(state, state->m_bitmap, y, hpos, mask); +} + +TIMER_CALLBACK( sam_video_update_callback ) +{ + samcoupe_state *state = machine.driver_data<samcoupe_state>(); + int vpos = machine.primary_screen->vpos(); + int hpos = machine.primary_screen->hpos(); + + int next_vpos = vpos; + int next_hpos = hpos + SAM_BLOCK*2; + + /* next scanline? */ + if (next_hpos >= SAM_BORDER_LEFT + SAM_SCREEN_WIDTH + SAM_BORDER_RIGHT) + { + next_vpos = (vpos + 1) % (SAM_BORDER_TOP + SAM_SCREEN_HEIGHT + SAM_BORDER_BOTTOM); + next_hpos = 0; + } + + /* display disabled? (only in mode 3 or 4) */ + if (BIT(state->m_vmpr, 6) && BIT(state->m_border, 7)) + { + state->m_bitmap.plot_box(hpos, vpos, SAM_BLOCK*2, 1, 0); + } + else + { + /* border area? */ + if (vpos < SAM_BORDER_TOP || vpos >= SAM_BORDER_TOP + SAM_SCREEN_HEIGHT || hpos < SAM_BORDER_LEFT || hpos >= SAM_BORDER_LEFT + SAM_SCREEN_WIDTH) + { + state->m_attribute = 0xff; + state->m_bitmap.plot_box(hpos, vpos, SAM_BLOCK*2, 1, state->m_clut[BORDER_COLOR(state->m_border)]); + } + else + { + /* main screen area */ + switch ((state->m_vmpr & 0x60) >> 5) + { + case 0: draw_mode1_line(machine, vpos, hpos); break; + case 1: draw_mode2_line(machine, vpos, hpos); break; + case 2: draw_mode3_line(machine, vpos, hpos); break; + case 3: draw_mode4_line(machine, vpos, hpos); break; + } + } + } + + /* do we need to trigger the scanline interrupt (interrupt happens at the start of the right border before the specified line)? */ + if (state->m_line_int < SAM_SCREEN_HEIGHT && hpos == SAM_BORDER_LEFT + SAM_SCREEN_WIDTH && vpos == (state->m_line_int + SAM_BORDER_TOP - 1)) + samcoupe_irq(machine.firstcpu, SAM_LINE_INT); + + /* schedule next update */ + state->m_video_update_timer->adjust(machine.primary_screen->time_until_pos(next_vpos, next_hpos)); +} |