diff options
Diffstat (limited to 'src/emu/video/cdp1869.c')
-rw-r--r-- | src/emu/video/cdp1869.c | 569 |
1 files changed, 569 insertions, 0 deletions
diff --git a/src/emu/video/cdp1869.c b/src/emu/video/cdp1869.c new file mode 100644 index 00000000000..2c32b4834d5 --- /dev/null +++ b/src/emu/video/cdp1869.c @@ -0,0 +1,569 @@ +#include "driver.h" +#include "cpu/cdp1802/cdp1802.h" +#include "video/cdp1869.h" +#include "sound/cdp1869.h" + +typedef struct +{ + int ntsc_pal; + int dispoff; + int fresvert, freshorz; + int dblpage, line16, line9, cmem, cfc; + UINT8 col, bkg; + UINT16 pma, hma; + UINT8 cram[CDP1869_CHARRAM_SIZE]; + UINT8 pram[CDP1869_PAGERAM_SIZE]; + int cramsize, pramsize; + UINT8 (*color_callback)(UINT8 cramdata, UINT16 cramaddr, UINT16 pramaddr); +} CDP1869_VIDEO_CONFIG; + +static CDP1869_VIDEO_CONFIG cdp1869; + +static UINT16 cdp1802_get_r_x(void) +{ + return activecpu_get_reg(CDP1802_R0 + activecpu_get_reg(CDP1802_X)); +} + +WRITE8_HANDLER ( cdp1869_out3_w ) +{ + /* + bit description + + 0 bkg green + 1 bkg blue + 2 bkg red + 3 cfc + 4 disp off + 5 colb0 + 6 colb1 + 7 fres horz + */ + + cdp1869.bkg = (data & 0x07); + cdp1869.cfc = (data & 0x08) >> 3; + cdp1869.dispoff = (data & 0x10) >> 4; + cdp1869.col = (data & 0x60) >> 5; + cdp1869.freshorz = (data & 0x80) >> 7; +} + +WRITE8_HANDLER ( cdp1869_out4_w ) +{ + UINT16 word = cdp1802_get_r_x(); + + /* + bit description + + 0 tone amp 2^0 + 1 tone amp 2^1 + 2 tone amp 2^2 + 3 tone amp 2^3 + 4 tone freq sel0 + 5 tone freq sel1 + 6 tone freq sel2 + 7 tone off + 8 tone / 2^0 + 9 tone / 2^1 + 10 tone / 2^2 + 11 tone / 2^3 + 12 tone / 2^4 + 13 tone / 2^5 + 14 tone / 2^6 + 15 always 0 + */ + + cdp1869_set_toneamp(0, word & 0x0f); + cdp1869_set_tonefreq(0, (word & 0x70) >> 4); + cdp1869_set_toneoff(0, (word & 0x80) >> 7); + cdp1869_set_tonediv(0, (word & 0x7f00) >> 8); +} + +WRITE8_HANDLER ( cdp1869_out5_w ) +{ + UINT16 word = cdp1802_get_r_x(); + + /* + bit description + + 0 cmem access mode + 1 x + 2 x + 3 9-line + 4 x + 5 16 line hi-res + 6 double page + 7 fres vert + 8 wn amp 2^0 + 9 wn amp 2^1 + 10 wn amp 2^2 + 11 wn amp 2^3 + 12 wn freq sel0 + 13 wn freq sel1 + 14 wn freq sel2 + 15 wn off + */ + + cdp1869.cmem = (word & 0x01); + cdp1869.line9 = (word & 0x08) >> 3; + cdp1869.line16 = (word & 0x20) >> 5; + cdp1869.dblpage = (word & 0x40) >> 6; + cdp1869.fresvert = (word & 0x80) >> 7; + + cdp1869_set_wnamp(0, (word & 0x0f00) >> 8); + cdp1869_set_wnfreq(0, (word & 0x7000) >> 12); + cdp1869_set_wnoff(0, (word & 0x8000) >> 15); +} + +WRITE8_HANDLER ( cdp1869_out6_w ) +{ + UINT16 word = cdp1802_get_r_x(); + + /* + bit description + + 0 pma0 reg + 1 pma1 reg + 2 pma2 reg + 3 pma3 reg + 4 pma4 reg + 5 pma5 reg + 6 pma6 reg + 7 pma7 reg + 8 pma8 reg + 9 pma9 reg + 10 pma10 reg + 11 x + 12 x + 13 x + 14 x + 15 x + */ + + cdp1869.pma = word & 0x7ff; +} + +WRITE8_HANDLER ( cdp1869_out7_w ) +{ + UINT16 word = cdp1802_get_r_x(); + + /* + bit description + + 0 x + 1 x + 2 hma2 reg + 3 hma3 reg + 4 hma4 reg + 5 hma5 reg + 6 hma6 reg + 7 hma7 reg + 8 hma8 reg + 9 hma9 reg + 10 hma10 reg + 11 x + 12 x + 13 x + 14 x + 15 x + */ + + cdp1869.hma = word & 0x7fc; +} + +static void cdp1869_set_color(int i, int c, int l) +{ + int luma = 0, r, g, b; + + luma += (l & 4) ? CDP1869_WEIGHT_RED : 0; + luma += (l & 1) ? CDP1869_WEIGHT_GREEN : 0; + luma += (l & 2) ? CDP1869_WEIGHT_BLUE : 0; + + luma = (luma * 0xff) / 100; + + r = (c & 4) ? luma : 0; + g = (c & 1) ? luma : 0; + b = (c & 2) ? luma : 0; + + palette_set_color( Machine, i, MAKE_RGB(r, g, b) ); +} + +PALETTE_INIT( cdp1869 ) +{ + int i, c, l; + + // color-on-color display (CFC=0) + + for (i = 0; i < 8; i++) + { + cdp1869_set_color(i, i, 15); + } + + // tone-on-tone display (CFC=1) + + for (c = 0; c < 8; c++) + { + for (l = 0; l < 8; l++) + { + cdp1869_set_color(i, c, l); + i++; + } + } +} + +static int cdp1869_get_lines(void) +{ + if (cdp1869.line16 && !cdp1869.dblpage) + { + return 16; + } + else if (!cdp1869.line9) + { + return 9; + } + else + { + return 8; + } +} + +static UINT16 cdp1869_get_pmemsize(int cols, int rows) +{ + int pmemsize = cols * rows; + + if (cdp1869.dblpage) pmemsize *= 2; + if (cdp1869.line16) pmemsize *= 2; + + return pmemsize; +} + +static UINT16 cdp1869_get_pma(void) +{ + if (cdp1869.dblpage) + { + return cdp1869.pma; + } + else + { + return cdp1869.pma & 0x3ff; + } +} + +UINT16 cdp1869_get_cma(UINT16 offset) +{ + int column = cdp1869.pram[cdp1869_get_pma()]; + int row = offset & 0x07; + + int addr = (column << 3) + row; + + if ((offset & 0x08) && (cdp1869_get_lines() > 8)) + { + addr += (CDP1869_CHARRAM_SIZE / 2); + } + + return addr; +} + +static UINT8 cdp1869_read_pageram(UINT16 addr) +{ + if (addr >= cdp1869.pramsize) + { + return 0xff; + } + else + { + return cdp1869.pram[addr]; + } +} + +#ifdef UNUSED_FUNCTION +UINT8 cdp1869_read_charram(UINT16 addr) +{ + if (addr >= cdp1869.cramsize) + { + return 0xff; + } + else + { + return cdp1869.cram[addr]; + } +} +#endif + +WRITE8_HANDLER ( cdp1869_charram_w ) +{ + if (cdp1869.cmem) + { + UINT16 addr = cdp1869_get_cma(offset); + cdp1869.cram[addr] = data; + } +} + +READ8_HANDLER ( cdp1869_charram_r ) +{ + if (cdp1869.cmem) + { + UINT16 addr = cdp1869_get_cma(offset); + return cdp1869.cram[addr]; + } + else + { + return 0xff; + } +} + +WRITE8_HANDLER ( cdp1869_pageram_w ) +{ + UINT16 addr; + + if (cdp1869.cmem) + { + addr = cdp1869_get_pma(); + } + else + { + addr = offset; + } + + cdp1869.pram[addr] = data; +} + +READ8_HANDLER ( cdp1869_pageram_r ) +{ + UINT16 addr; + + if (cdp1869.cmem) + { + addr = cdp1869_get_pma(); + } + else + { + addr = offset; + } + + return cdp1869.pram[addr]; +} + +static int cdp1869_get_color(int ccb0, int ccb1, int pcb) +{ + int r = 0, g = 0, b = 0, color; + + switch (cdp1869.col) + { + case 0: + r = ccb0; + g = pcb; + b = ccb1; + break; + + case 1: + r = ccb0; + g = ccb1; + b = pcb; + break; + + case 2: + case 3: + r = pcb; + g = ccb1; + b = ccb0; + break; + } + + color = (r << 2) + (b << 1) + g; + + if (cdp1869.cfc) + { + return color + ((cdp1869.bkg + 1) * 8); + } + else + { + return color; + } +} + +static void cdp1869_draw_line(running_machine *machine, mame_bitmap *bitmap, int x, int y, int data, int color) +{ + int i; + + data <<= 2; + + for (i = 0; i < CDP1869_CHAR_WIDTH; i++) + { + if (data & 0x80) + { + *BITMAP_ADDR16(bitmap, y, x) = machine->pens[color]; + + if (!cdp1869.fresvert) + { + *BITMAP_ADDR16(bitmap, y + 1, x) = machine->pens[color]; + } + + if (!cdp1869.freshorz) + { + *BITMAP_ADDR16(bitmap, y, x + 1) = machine->pens[color]; + + if (!cdp1869.fresvert) + { + *BITMAP_ADDR16(bitmap, y + 1, x + 1) = machine->pens[color]; + } + } + } + + if (!cdp1869.freshorz) + { + x++; + } + + x++; + + data <<= 1; + } +} + +static void cdp1869_draw_char(running_machine *machine, mame_bitmap *bitmap, int x, int y, UINT16 pramaddr, const rectangle *screenrect) +{ + int i; + UINT8 code = cdp1869_read_pageram(pramaddr); + UINT16 addr = code * 8; + UINT16 addr2 = addr + (CDP1869_CHARRAM_SIZE / 2); + + for (i = 0; i < cdp1869_get_lines(); i++) + { + UINT8 data = cdp1869.cram[addr]; + + UINT8 colorbits = cdp1869.color_callback(data, addr, pramaddr); + + int pcb = colorbits & 0x01; + int ccb1 = (colorbits & 0x02) >> 1; + int ccb0 = (colorbits & 0x04) >> 2; + + int color = cdp1869_get_color(ccb0, ccb1, pcb); + + cdp1869_draw_line(machine, bitmap, screenrect->min_x + x, screenrect->min_y + y, data, color); + + addr++; + y++; + + if (!cdp1869.fresvert) + { + y++; + } + + if (i == 7) + { + addr = addr2; + } + } +} + +VIDEO_START( cdp1869 ) +{ + state_save_register_item("cdp1869", 0, cdp1869.ntsc_pal); + state_save_register_item("cdp1869", 0, cdp1869.dispoff); + state_save_register_item("cdp1869", 0, cdp1869.fresvert); + state_save_register_item("cdp1869", 0, cdp1869.freshorz); + state_save_register_item("cdp1869", 0, cdp1869.dblpage); + state_save_register_item("cdp1869", 0, cdp1869.line16); + state_save_register_item("cdp1869", 0, cdp1869.line9); + state_save_register_item("cdp1869", 0, cdp1869.cmem); + state_save_register_item("cdp1869", 0, cdp1869.cfc); + state_save_register_item("cdp1869", 0, cdp1869.col); + state_save_register_item("cdp1869", 0, cdp1869.bkg); + state_save_register_item("cdp1869", 0, cdp1869.pma); + state_save_register_item("cdp1869", 0, cdp1869.hma); + state_save_register_item_array("cdp1869", 0, cdp1869.cram); + state_save_register_item_array("cdp1869", 0, cdp1869.pram); + state_save_register_item("cdp1869", 0, cdp1869.cramsize); + state_save_register_item("cdp1869", 0, cdp1869.pramsize); +} + +VIDEO_UPDATE( cdp1869 ) +{ + fillbitmap(bitmap, get_black_pen(machine), cliprect); + + if (!cdp1869.dispoff) + { + int sx, sy, rows, cols, width, height; + UINT16 addr, pmemsize; + rectangle screen, outer; + + switch (cdp1869.ntsc_pal) + { + case CDP1869_NTSC: + outer.min_x = CDP1869_HBLANK_END; + outer.max_x = CDP1869_HBLANK_START - 1; + outer.min_y = CDP1869_SCANLINE_VBLANK_END_NTSC; + outer.max_y = CDP1869_SCANLINE_VBLANK_START_NTSC - 1; + screen.min_x = CDP1869_SCREEN_START_NTSC; + screen.max_x = CDP1869_SCREEN_END - 1; + screen.min_y = CDP1869_SCANLINE_DISPLAY_START_NTSC; + screen.max_y = CDP1869_SCANLINE_DISPLAY_END_NTSC - 1; + break; + + default: + case CDP1869_PAL: + outer.min_x = CDP1869_HBLANK_END; + outer.max_x = CDP1869_HBLANK_START - 1; + outer.min_y = CDP1869_SCANLINE_VBLANK_END_PAL; + outer.max_y = CDP1869_SCANLINE_VBLANK_START_PAL - 1; + screen.min_x = CDP1869_SCREEN_START_PAL; + screen.max_x = CDP1869_SCREEN_END - 1; + screen.min_y = CDP1869_SCANLINE_DISPLAY_START_PAL; + screen.max_y = CDP1869_SCANLINE_DISPLAY_END_PAL - 1; + break; + } + + sect_rect(&outer, cliprect); + fillbitmap(bitmap, machine->pens[cdp1869.bkg], &outer); + + width = CDP1869_CHAR_WIDTH; + height = cdp1869_get_lines(); + + if (!cdp1869.freshorz) + { + width *= 2; + } + + if (!cdp1869.fresvert) + { + height *= 2; + } + + cols = cdp1869.freshorz ? CDP1869_COLUMNS_FULL : CDP1869_COLUMNS_HALF; + rows = (screen.max_y - screen.min_y + 1) / height; + + pmemsize = cdp1869_get_pmemsize(cols, rows); + + addr = cdp1869.hma; + + for (sy = 0; sy < rows; sy++) + { + for (sx = 0; sx < cols; sx++) + { + int x = sx * width; + int y = sy * height; + + cdp1869_draw_char(machine, bitmap, x, y, addr, &screen); + + addr++; + + if (addr == pmemsize) addr = 0; + } + } + } + + return 0; +} + +void cdp1869_configure(const CDP1869_interface *intf) +{ + if (intf->charrom_region != REGION_INVALID) + { + UINT8 *memory = memory_region(intf->charrom_region); + memcpy(cdp1869.cram, memory, intf->charram_size); + } + + cdp1869.ntsc_pal = intf->ntsc_pal; + cdp1869.cramsize = intf->charram_size; + cdp1869.pramsize = intf->pageram_size; + cdp1869.color_callback = intf->get_color_bits; +} |