#include "driver.h"
#include "deprecat.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;
}