From f26c5bf115ff665d9d29034c35f0b20ba6e15c47 Mon Sep 17 00:00:00 2001 From: Fabio Priuli Date: Wed, 17 Feb 2010 17:07:06 +0000 Subject: [PATCH] attckufo: Imported MOS6560 device emulation from MESS and removed the existent custom audio/video emulation [Fabio Priuli] --- .gitattributes | 4 +- src/emu/sound/mos6560.c | 910 +++++++++++++++++++++++++++++++++++ src/emu/sound/mos6560.h | 116 +++++ src/emu/sound/sound.mak | 11 + src/mame/drivers/attckufo.c | 83 +++- src/mame/includes/attckufo.h | 20 - src/mame/mame.mak | 3 +- src/mame/video/attckufo.c | 171 ------- 8 files changed, 1111 insertions(+), 207 deletions(-) create mode 100644 src/emu/sound/mos6560.c create mode 100644 src/emu/sound/mos6560.h delete mode 100644 src/mame/includes/attckufo.h delete mode 100644 src/mame/video/attckufo.c diff --git a/.gitattributes b/.gitattributes index 1253e4ab4f3..0b8e1223c28 100644 --- a/.gitattributes +++ b/.gitattributes @@ -884,6 +884,8 @@ src/emu/sound/k054539.c svneol=native#text/plain src/emu/sound/k054539.h svneol=native#text/plain src/emu/sound/k056800.c svneol=native#text/plain src/emu/sound/k056800.h svneol=native#text/plain +src/emu/sound/mos6560.c svneol=native#text/plain +src/emu/sound/mos6560.h svneol=native#text/plain src/emu/sound/msm5205.c svneol=native#text/plain src/emu/sound/msm5205.h svneol=native#text/plain src/emu/sound/msm5232.c svneol=native#text/plain @@ -2383,7 +2385,6 @@ src/mame/includes/atarigx2.h svneol=native#text/plain src/mame/includes/atarisy1.h svneol=native#text/plain src/mame/includes/atarisy2.h svneol=native#text/plain src/mame/includes/atetris.h svneol=native#text/plain -src/mame/includes/attckufo.h svneol=native#text/plain src/mame/includes/avalnche.h svneol=native#text/plain src/mame/includes/aztarac.h svneol=native#text/plain src/mame/includes/badlands.h svneol=native#text/plain @@ -3226,7 +3227,6 @@ src/mame/video/atarirle.h svneol=native#text/plain src/mame/video/atarisy1.c svneol=native#text/plain src/mame/video/atarisy2.c svneol=native#text/plain src/mame/video/atetris.c svneol=native#text/plain -src/mame/video/attckufo.c svneol=native#text/plain src/mame/video/avgdvg.c svneol=native#text/plain src/mame/video/avgdvg.h svneol=native#text/plain src/mame/video/awpvid.c svneol=native#text/plain diff --git a/src/emu/sound/mos6560.c b/src/emu/sound/mos6560.c new file mode 100644 index 00000000000..5ef68882a3a --- /dev/null +++ b/src/emu/sound/mos6560.c @@ -0,0 +1,910 @@ +/*************************************************************************** + + MOS 6560 / 6561 Video Interface Chip + + + Original code by PeT (mess@utanet.at), 1999 + + + 2010 FP: converted to a device and merged the video & sound components + + TODO: + - plenty of cleanups! + - investigate attckufo chip features (no invert mode, no multicolor, 16 col chars) + - investigate why some vic20 carts crash emulation + +***************************************************************************/ + +#include "emu.h" +#include "streams.h" +#include "sound/mos6560.h" + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +typedef struct _mos6560_state mos6560_state; +struct _mos6560_state +{ + mos6560_type type; + + running_device *screen; + + UINT8 reg[16]; + + bitmap_t *bitmap; + + int rasterline, lastline; + double lightpenreadtime; + + int charheight, matrix8x16, inverted; + int chars_x, chars_y; + int xsize, ysize, xpos, ypos; + int chargenaddr, videoaddr; + + /* values in videoformat */ + UINT16 backgroundcolor, framecolor, helpercolor; + + /* arrays for bit to color conversion without condition checking */ + UINT16 mono[2], monoinverted[2], multi[4], multiinverted[4]; + + /* video chip settings */ + int total_xsize, total_ysize, total_lines, total_vretracerate; + + /* DMA */ + mos6560_dma_read dma_read; + mos6560_dma_read_color dma_read_color; + + /* lightpen */ + mos6560_lightpen_button_callback lightpen_button_cb; + mos6560_lightpen_x_callback lightpen_x_cb; + mos6560_lightpen_y_callback lightpen_y_cb; + + /* paddles */ + mos6560_paddle_callback paddle_cb[2]; + + /* sound part */ + int tone1pos, tone2pos, tone3pos, + tonesize, tone1samples, tone2samples, tone3samples, + noisesize, /* number of samples */ + noisepos, /* pos of tone */ + noisesamples; /* count of samples to give out per tone */ + + sound_stream *channel; + INT16 *tone; + INT8 *noise; +}; + +/***************************************************************************** + INLINE FUNCTIONS +*****************************************************************************/ + +INLINE mos6560_state *get_safe_token( running_device *device ) +{ + assert(device != NULL); + assert(device->token != NULL); + assert(device->type == MOS6560); + + return (mos6560_state *)device->token; +} + +INLINE const mos6560_interface *get_interface( running_device *device ) +{ + assert(device != NULL); + assert((device->type == MOS6560)); + return (const mos6560_interface *) device->baseconfig().static_config; +} + +/***************************************************************************** + PARAMETERS +*****************************************************************************/ + +#define VERBOSE_LEVEL 0 +#define DBG_LOG(N,M,A) \ + do { \ + if(VERBOSE_LEVEL >= N) \ + { \ + if( M ) \ + logerror("%11.6f: %-24s", attotime_to_double(timer_get_time(device->machine)), (char*) M ); \ + logerror A; \ + } \ + } while (0) + + +/* 2008-05 FP: lightpen code needs to read input port from vc20.c */ + +#define LIGHTPEN_BUTTON (mos6560->lightpen_button_cb(device->machine)) +#define LIGHTPEN_X_VALUE (mos6560->lightpen_x_cb(device->machine)) +#define LIGHTPEN_Y_VALUE (mos6560->lightpen_y_cb(device->machine)) + +/* lightpen delivers values from internal counters + * they do not start with the visual area or frame area */ +#define MOS6560_X_BEGIN 38 +#define MOS6560_Y_BEGIN -6 /* first 6 lines after retrace not for lightpen! */ +#define MOS6561_X_BEGIN 38 +#define MOS6561_Y_BEGIN -6 +#define MOS656X_X_BEGIN ((mos6560->type == MOS6561) ? MOS6561_X_BEGIN : MOS6560_X_BEGIN) +#define MOS656X_Y_BEGIN ((mos6560->type == MOS6561) ? MOS6561_Y_BEGIN : MOS6560_Y_BEGIN) + +#define MOS656X_MAME_XPOS ((mos6560->type == MOS6561) ? MOS6561_MAME_XPOS : MOS6560_MAME_XPOS) +#define MOS656X_MAME_YPOS ((mos6560->type == MOS6561) ? MOS6561_MAME_YPOS : MOS6560_MAME_YPOS) + +/* lightpen behaviour in pal or mono multicolor not tested */ +#define MOS656X_X_VALUE ((LIGHTPEN_X_VALUE + MOS656X_X_BEGIN + MOS656X_MAME_XPOS)/2) +#define MOS656X_Y_VALUE ((LIGHTPEN_Y_VALUE + MOS656X_Y_BEGIN + MOS656X_MAME_YPOS)/2) + +#define MOS656X_VRETRACERATE ((mos6560->type == MOS6561) ? MOS6561_VRETRACERATE : MOS6560_VRETRACERATE) + +/* ntsc 1 - 8 */ +/* pal 5 - 19 */ +#define XPOS (((int)mos6560->reg[0] & 0x7f) * 4) +#define YPOS ((int)mos6560->reg[1] * 2) + +/* ntsc values >= 31 behave like 31 */ +/* pal value >= 32 behave like 32 */ +#define CHARS_X ((int)mos6560->reg[2] & 0x7f) +#define CHARS_Y (((int)mos6560->reg[3] & 0x7e) >> 1) + +/* colorram and backgroundcolor are changed */ +#define INVERTED (!(mos6560->reg[0x0f] & 8)) + +#define CHARGENADDR (((int)mos6560->reg[5] & 0x0f) << 10) +#define VIDEOADDR ((((int)mos6560->reg[5] & 0xf0) << (10 - 4)) | (((int)mos6560->reg[2] & 0x80) << (9-7))) +#define VIDEORAMSIZE (YSIZE * XSIZE) +#define CHARGENSIZE (256 * HEIGHTPIXEL) + +#define HELPERCOLOR (mos6560->reg[0x0e] >> 4) +#define BACKGROUNDCOLOR (mos6560->reg[0x0f] >> 4) +#define FRAMECOLOR (mos6560->reg[0x0f] & 0x07) + +/***************************************************************************** + IMPLEMENTATION +*****************************************************************************/ + +static void mos6560_soundport_w( running_device *device, int offset, int data ); + +/*------------------------------------------------- + mos6560_draw_character +-------------------------------------------------*/ + +static void mos6560_draw_character( running_device *device, int ybegin, int yend, int ch, int yoff, int xoff, UINT16 *color ) +{ + mos6560_state *mos6560 = get_safe_token(device); + int y, code; + + for (y = ybegin; y <= yend; y++) + { + code = mos6560->dma_read(device->machine, (mos6560->chargenaddr + ch * mos6560->charheight + y) & 0x3fff); + *BITMAP_ADDR16(mos6560->bitmap, y + yoff, xoff + 0) = color[code >> 7]; + *BITMAP_ADDR16(mos6560->bitmap, y + yoff, xoff + 1) = color[(code >> 6) & 1]; + *BITMAP_ADDR16(mos6560->bitmap, y + yoff, xoff + 2) = color[(code >> 5) & 1]; + *BITMAP_ADDR16(mos6560->bitmap, y + yoff, xoff + 3) = color[(code >> 4) & 1]; + *BITMAP_ADDR16(mos6560->bitmap, y + yoff, xoff + 4) = color[(code >> 3) & 1]; + *BITMAP_ADDR16(mos6560->bitmap, y + yoff, xoff + 5) = color[(code >> 2) & 1]; + *BITMAP_ADDR16(mos6560->bitmap, y + yoff, xoff + 6) = color[(code >> 1) & 1]; + *BITMAP_ADDR16(mos6560->bitmap, y + yoff, xoff + 7) = color[code & 1]; + } +} + + +/*------------------------------------------------- + mos6560_draw_character_multi +-------------------------------------------------*/ + +static void mos6560_draw_character_multi( running_device *device, int ybegin, int yend, int ch, int yoff, int xoff, UINT16 *color ) +{ + mos6560_state *mos6560 = get_safe_token(device); + int y, code; + + for (y = ybegin; y <= yend; y++) + { + code = mos6560->dma_read(device->machine, (mos6560->chargenaddr + ch * mos6560->charheight + y) & 0x3fff); + *BITMAP_ADDR16(mos6560->bitmap, y + yoff, xoff + 0) = + *BITMAP_ADDR16(mos6560->bitmap, y + yoff, xoff + 1) = color[code >> 6]; + *BITMAP_ADDR16(mos6560->bitmap, y + yoff, xoff + 2) = + *BITMAP_ADDR16(mos6560->bitmap, y + yoff, xoff + 3) = color[(code >> 4) & 3]; + *BITMAP_ADDR16(mos6560->bitmap, y + yoff, xoff + 4) = + *BITMAP_ADDR16(mos6560->bitmap, y + yoff, xoff + 5) = color[(code >> 2) & 3]; + *BITMAP_ADDR16(mos6560->bitmap, y + yoff, xoff + 6) = + *BITMAP_ADDR16(mos6560->bitmap, y + yoff, xoff + 7) = color[code & 3]; + } +} + + +/*------------------------------------------------- + mos6560_drawlines - draw a certain numer of lines +-------------------------------------------------*/ + +static void mos6560_drawlines( running_device *device, int first, int last ) +{ + mos6560_state *mos6560 = get_safe_token(device); + int line, vline; + int offs, yoff, xoff, ybegin, yend, i, j; + int attr, ch; + + mos6560->lastline = last; + if (first >= last) + return; + + for (line = first; (line < mos6560->ypos) && (line < last); line++) + { + for (j = 0; j < mos6560->total_xsize; j++) + *BITMAP_ADDR16(mos6560->bitmap, line, j) = mos6560->framecolor; + } + + for (vline = line - mos6560->ypos; (line < last) && (line < mos6560->ypos + mos6560->ysize);) + { + if (mos6560->matrix8x16) + { + offs = (vline >> 4) * mos6560->chars_x; + yoff = (vline & ~0xf) + mos6560->ypos; + ybegin = vline & 0xf; + yend = (vline + 0xf < last - mos6560->ypos) ? 0xf : ((last - line) & 0xf) + ybegin; + } + else + { + offs = (vline >> 3) * mos6560->chars_x; + yoff = (vline & ~7) + mos6560->ypos; + ybegin = vline & 7; + yend = (vline + 7 < last - mos6560->ypos) ? 7 : ((last - line) & 7) + ybegin; + } + + if (mos6560->xpos > 0) + { + for (i = ybegin; i <= yend; i++) + for (j = 0; j < mos6560->xpos; j++) + *BITMAP_ADDR16(mos6560->bitmap, yoff + i, j) = mos6560->framecolor; + } + + for (xoff = mos6560->xpos; (xoff < mos6560->xpos + mos6560->xsize) && (xoff < mos6560->total_xsize); xoff += 8, offs++) + { + ch = mos6560->dma_read(device->machine, (mos6560->videoaddr + offs) & 0x3fff); + attr = (mos6560->dma_read_color(device->machine, (mos6560->videoaddr + offs) & 0x3fff)) & 0xf; + + if (mos6560->type == MOS6560_ATTACKUFO) + { + /* the mos6560 variant used in attckufo only has only one draw mode */ + mos6560->mono[1] = attr; + mos6560_draw_character(device, ybegin, yend, ch, yoff, xoff, mos6560->mono); + } + else if (mos6560->inverted) + { + if (attr & 8) + { + mos6560->multiinverted[0] = attr & 7; + mos6560_draw_character_multi(device, ybegin, yend, ch, yoff, xoff, mos6560->multiinverted); + } + else + { + mos6560->monoinverted[0] = attr; + mos6560_draw_character(device, ybegin, yend, ch, yoff, xoff, mos6560->monoinverted); + } + } + else + { + if (attr & 8) + { + mos6560->multi[2] = attr & 7; + mos6560_draw_character_multi(device, ybegin, yend, ch, yoff, xoff, mos6560->multi); + } + else + { + mos6560->mono[1] = attr; + mos6560_draw_character(device, ybegin, yend, ch, yoff, xoff, mos6560->mono); + } + } + } + + if (xoff < mos6560->total_xsize) + { + for (i = ybegin; i <= yend; i++) + for (j = xoff; j < mos6560->total_xsize; j++) + *BITMAP_ADDR16(mos6560->bitmap, yoff + i, j) = mos6560->framecolor; + } + + if (mos6560->matrix8x16) + { + vline = (vline + 16) & ~0xf; + line = vline + mos6560->ypos; + } + else + { + vline = (vline + 8) & ~7; + line = vline + mos6560->ypos; + } + } + + for (; line < last; line++) + for (j = 0; j < mos6560->total_xsize; j++) + *BITMAP_ADDR16(mos6560->bitmap, line, j) = mos6560->framecolor; +} + + +/*------------------------------------------------- + mos6560_port_w - write to regs +-------------------------------------------------*/ + +WRITE8_DEVICE_HANDLER( mos6560_port_w ) +{ + mos6560_state *mos6560 = get_safe_token(device); + + DBG_LOG(1, "mos6560_port_w", ("%.4x:%.2x\n", offset, data)); + + switch (offset) + { + case 0xa: + case 0xb: + case 0xc: + case 0xd: + case 0xe: + mos6560_soundport_w(device, offset, data); + break; + } + + if (mos6560->reg[offset] != data) + { + switch (offset) + { + case 0: + case 1: + case 2: + case 3: + case 5: + case 0xe: + case 0xf: + mos6560_drawlines(device, mos6560->lastline, mos6560->rasterline); + break; + } + mos6560->reg[offset] = data; + + switch (offset) + { + case 0: + if ((mos6560->type != MOS6560_ATTACKUFO)) + mos6560->xpos = XPOS; + break; + case 1: + if ((mos6560->type != MOS6560_ATTACKUFO)) + mos6560->ypos = YPOS; + break; + case 2: + /* ntsc values >= 31 behave like 31 */ + /* pal value >= 32 behave like 32 */ + mos6560->chars_x = CHARS_X; + mos6560->videoaddr = VIDEOADDR; + mos6560->xsize = CHARS_X * 8; + break; + case 3: + if ((mos6560->type != MOS6560_ATTACKUFO)) + { + mos6560->matrix8x16 = data & 0x01; + mos6560->charheight = mos6560->matrix8x16 ? 16 : 8; + } + mos6560->chars_y = CHARS_Y; + mos6560->ysize = CHARS_Y * mos6560->charheight; + break; + case 5: + mos6560->chargenaddr = CHARGENADDR; + mos6560->videoaddr = VIDEOADDR; + break; + case 0xe: + mos6560->multi[3] = mos6560->multiinverted[3] = mos6560->helpercolor = HELPERCOLOR; + break; + case 0xf: + if ((mos6560->type != MOS6560_ATTACKUFO)) + mos6560->inverted = INVERTED; + mos6560->multi[1] = mos6560->multiinverted[1] = mos6560->framecolor = FRAMECOLOR; + mos6560->mono[0] = mos6560->monoinverted[1] = mos6560->multi[0] = mos6560->multiinverted[2] = mos6560->backgroundcolor = BACKGROUNDCOLOR; + break; + } + } +} + +/*------------------------------------------------- + mos6560_port_r - read from regs +-------------------------------------------------*/ + +READ8_DEVICE_HANDLER( mos6560_port_r ) +{ + mos6560_state *mos6560 = get_safe_token(device); + int val; + + switch (offset) + { + case 3: + val = ((mos6560->rasterline & 1) << 7) | (mos6560->reg[offset] & 0x7f); + break; + case 4: /*rasterline */ + mos6560_drawlines(device, mos6560->lastline, mos6560->rasterline); + val = (mos6560->rasterline / 2) & 0xff; + break; + case 6: /*lightpen horizontal */ + case 7: /*lightpen vertical */ + if (LIGHTPEN_BUTTON && ((attotime_to_double(timer_get_time(device->machine)) - mos6560->lightpenreadtime) * MOS656X_VRETRACERATE >= 1)) + { + /* only 1 update each frame */ + /* and diode must recognize light */ + if (1) + { + mos6560->reg[6] = MOS656X_X_VALUE; + mos6560->reg[7] = MOS656X_Y_VALUE; + } + mos6560->lightpenreadtime = attotime_to_double(timer_get_time(device->machine)); + } + val = mos6560->reg[offset]; + break; + case 8: /* poti 1 */ + case 9: /* poti 2 */ + val = mos6560->paddle_cb[offset - 8](device->machine); + break; + default: + val = mos6560->reg[offset]; + break; + } + DBG_LOG(3, "mos6560_port_r", ("%.4x:%.2x\n", offset, val)); + return val; +} + + +/*------------------------------------------------- + mos6560_raster_interrupt_gen +-------------------------------------------------*/ + +void mos6560_raster_interrupt_gen( running_device *device ) +{ + mos6560_state *mos6560 = get_safe_token(device); + + mos6560->rasterline++; + if (mos6560->rasterline >= mos6560->total_lines) + { + mos6560->rasterline = 0; + mos6560_drawlines(device, mos6560->lastline, mos6560->total_lines); + mos6560->lastline = 0; + } +} + + +/*------------------------------------------------- + mos6560_video_update - copy the VIC bitmap to + main screen bitmap +-------------------------------------------------*/ + +UINT32 mos6560_video_update( running_device *device, bitmap_t *bitmap, const rectangle *cliprect ) +{ + mos6560_state *mos6560 = get_safe_token(device); + + copybitmap(bitmap, mos6560->bitmap, 0, 0, 0, 0, cliprect); + return 0; +} + +/***************************************************************************** + SOUND IMPLEMENTATION +*****************************************************************************/ + +/* + * assumed model: + * each write to a ton/noise generated starts it new + * each generator behaves like an timer + * when it reaches 0, the next samplevalue is given out + */ + +/* + * noise channel + * based on a document by diku0748@diku.dk (Asger Alstrup Nielsen) + * + * 23 bit shift register + * initial value (0x7ffff8) + * after shift bit 0 is set to bit 22 xor bit 17 + * dac sample bit22 bit20 bit16 bit13 bit11 bit7 bit4 bit2(lsb) + * + * emulation: + * allocate buffer for 5 sec sampledata (fastest played frequency) + * and fill this buffer in init with the required sample + * fast turning off channel, immediate change of frequency + */ + +#define NOISE_BUFFER_SIZE_SEC 5 + +#define TONE1_ON (mos6560->reg[0x0a] & 0x80) +#define TONE2_ON (mos6560->reg[0x0b] & 0x80) +#define TONE3_ON (mos6560->reg[0x0c] & 0x80) +#define NOISE_ON (mos6560->reg[0x0d] & 0x80) +#define VOLUME (mos6560->reg[0x0e] & 0x0f) + +#define MOS656X_CLOCK ((mos6560->type == MOS6561) ? MOS6561_CLOCK : MOS6560_CLOCK) + +#define TONE_FREQUENCY_MIN (MOS656X_CLOCK/256/128) + +#define TONE1_VALUE (8 * (128 - ((mos6560->reg[0x0a] + 1) & 0x7f))) +#define TONE1_FREQUENCY (MOS656X_CLOCK/32/TONE1_VALUE) + +#define TONE2_VALUE (4 * (128 - ((mos6560->reg[0x0b] + 1) & 0x7f))) +#define TONE2_FREQUENCY (MOS656X_CLOCK/32/TONE2_VALUE) + +#define TONE3_VALUE (2 * (128 - ((mos6560->reg[0x0c] + 1) & 0x7f))) +#define TONE3_FREQUENCY (MOS656X_CLOCK/32/TONE3_VALUE) + +#define NOISE_VALUE (32 * (128 - ((mos6560->reg[0x0d] + 1) & 0x7f))) +#define NOISE_FREQUENCY (MOS656X_CLOCK/NOISE_VALUE) + +#define NOISE_FREQUENCY_MAX (MOS656X_CLOCK/32/1) + + +/*------------------------------------------------- + mos6560_soundport_w - write to regs +-------------------------------------------------*/ + +static void mos6560_soundport_w( running_device *device, int offset, int data ) +{ + mos6560_state *mos6560 = get_safe_token(device); + int old = mos6560->reg[offset]; + stream_update(mos6560->channel); + + switch (offset) + { + case 0x0a: + mos6560->reg[offset] = data; + if (!(old & 0x80) && TONE1_ON) + { + mos6560->tone1pos = 0; + mos6560->tone1samples = device->machine->sample_rate / TONE1_FREQUENCY; + if (!mos6560->tone1samples == 0) + mos6560->tone1samples = 1; + } + DBG_LOG(1, "mos6560", ("tone1 %.2x %d\n", data, TONE1_FREQUENCY)); + break; + case 0x0b: + mos6560->reg[offset] = data; + if (!(old & 0x80) && TONE2_ON) + { + mos6560->tone2pos = 0; + mos6560->tone2samples = device->machine->sample_rate / TONE2_FREQUENCY; + if (mos6560->tone2samples == 0) + mos6560->tone2samples = 1; + } + DBG_LOG(1, "mos6560", ("tone2 %.2x %d\n", data, TONE2_FREQUENCY)); + break; + case 0x0c: + mos6560->reg[offset] = data; + if (!(old & 0x80) && TONE3_ON) + { + mos6560->tone3pos = 0; + mos6560->tone3samples = device->machine->sample_rate / TONE3_FREQUENCY; + if (mos6560->tone3samples == 0) + mos6560->tone3samples = 1; + } + DBG_LOG(1, "mos6560", ("tone3 %.2x %d\n", data, TONE3_FREQUENCY)); + break; + case 0x0d: + mos6560->reg[offset] = data; + if (NOISE_ON) + { + mos6560->noisesamples = (int) ((double) NOISE_FREQUENCY_MAX * device->machine->sample_rate + * NOISE_BUFFER_SIZE_SEC / NOISE_FREQUENCY); + DBG_LOG (1, "mos6560", ("noise %.2x %d sample:%d\n", + data, NOISE_FREQUENCY, mos6560->noisesamples)); + if ((double) mos6560->noisepos / mos6560->noisesamples >= 1.0) + { + mos6560->noisepos = 0; + } + } + else + { + mos6560->noisepos = 0; + } + break; + case 0x0e: + mos6560->reg[offset] = (old & ~0x0f) | (data & 0x0f); + DBG_LOG (3, "mos6560", ("volume %d\n", data & 0x0f)); + break; + } +} + + +/*------------------------------------------------- + mos6560_update - update audio stream +-------------------------------------------------*/ + +static STREAM_UPDATE( mos6560_update ) +{ + mos6560_state *mos6560 = get_safe_token(device); + int i, v; + stream_sample_t *buffer = outputs[0]; + + for (i = 0; i < samples; i++) + { + v = 0; + if (TONE1_ON /*||(mos6560->tone1pos != 0) */ ) + { + v += mos6560->tone[mos6560->tone1pos * mos6560->tonesize / mos6560->tone1samples]; + mos6560->tone1pos++; +#if 0 + mos6560->tone1pos %= mos6560->tone1samples; +#else + if (mos6560->tone1pos >= mos6560->tone1samples) + { + mos6560->tone1pos = 0; + mos6560->tone1samples = device->machine->sample_rate / TONE1_FREQUENCY; + if (mos6560->tone1samples == 0) + mos6560->tone1samples = 1; + } +#endif + } + if (TONE2_ON /*||(mos6560->tone2pos != 0) */ ) + { + v += mos6560->tone[mos6560->tone2pos * mos6560->tonesize / mos6560->tone2samples]; + mos6560->tone2pos++; +#if 0 + mos6560->tone2pos %= mos6560->tone2samples; +#else + if (mos6560->tone2pos >= mos6560->tone2samples) + { + mos6560->tone2pos = 0; + mos6560->tone2samples = device->machine->sample_rate / TONE2_FREQUENCY; + if (mos6560->tone2samples == 0) + mos6560->tone2samples = 1; + } +#endif + } + if (TONE3_ON /*||(mos6560->tone3pos != 0) */ ) + { + v += mos6560->tone[mos6560->tone3pos * mos6560->tonesize / mos6560->tone3samples]; + mos6560->tone3pos++; +#if 0 + mos6560->tone3pos %= mos6560->tone3samples; +#else + if (mos6560->tone3pos >= mos6560->tone3samples) + { + mos6560->tone3pos = 0; + mos6560->tone3samples = device->machine->sample_rate / TONE3_FREQUENCY; + if (mos6560->tone3samples == 0) + mos6560->tone3samples = 1; + } +#endif + } + if (NOISE_ON) + { + v += mos6560->noise[(int) ((double) mos6560->noisepos * mos6560->noisesize / mos6560->noisesamples)]; + mos6560->noisepos++; + if ((double) mos6560->noisepos / mos6560->noisesamples >= 1.0) + { + mos6560->noisepos = 0; + } + } + v = (v * VOLUME) << 2; + if (v > 32767) + buffer[i] = 32767; + else if (v < -32767) + buffer[i] = -32767; + else + buffer[i] = v; + + + + } +} + + +/***************************************************************************** + DEVICE INTERFACE +*****************************************************************************/ + +/*------------------------------------------------- + mos6560_sound_start - start audio emulation + (to be called at device start) +-------------------------------------------------*/ + +static void mos6560_sound_start( running_device *device ) +{ + mos6560_state *mos6560 = get_safe_token(device); + int i; + + mos6560->channel = stream_create(device, 0, 1, device->machine->sample_rate, 0, mos6560_update); + + /* buffer for fastest played sample for 5 second so we have enough data for min 5 second */ + mos6560->noisesize = NOISE_FREQUENCY_MAX * NOISE_BUFFER_SIZE_SEC; + mos6560->noise = auto_alloc_array(device->machine, INT8, mos6560->noisesize); + { + int noiseshift = 0x7ffff8; + char data; + + for (i = 0; i < mos6560->noisesize; i++) + { + data = 0; + if (noiseshift & 0x400000) + data |= 0x80; + if (noiseshift & 0x100000) + data |= 0x40; + if (noiseshift & 0x010000) + data |= 0x20; + if (noiseshift & 0x002000) + data |= 0x10; + if (noiseshift & 0x000800) + data |= 0x08; + if (noiseshift & 0x000080) + data |= 0x04; + if (noiseshift & 0x000010) + data |= 0x02; + if (noiseshift & 0x000004) + data |= 0x01; + mos6560->noise[i] = data; + if (((noiseshift & 0x400000) == 0) != ((noiseshift & 0x002000) == 0)) + noiseshift = (noiseshift << 1) | 1; + else + noiseshift <<= 1; + } + } + mos6560->tonesize = device->machine->sample_rate / TONE_FREQUENCY_MIN; + + if (mos6560->tonesize > 0) + { + mos6560->tone = auto_alloc_array(device->machine, INT16, mos6560->tonesize); + + for (i = 0; i < mos6560->tonesize; i++) + { + mos6560->tone[i] = (INT16)(sin (2 * M_PI * i / mos6560->tonesize) * 127 + 0.5); + } + } + else + { + mos6560->tone = NULL; + } +} + + +/*------------------------------------------------- + DEVICE_START( mos6560 ) +-------------------------------------------------*/ + +static DEVICE_START( mos6560 ) +{ + mos6560_state *mos6560 = get_safe_token(device); + const mos6560_interface *intf = (mos6560_interface *)device->baseconfig().static_config; + int width, height; + + mos6560->screen = devtag_get_device(device->machine, intf->screen); + width = video_screen_get_width(mos6560->screen); + height = video_screen_get_height(mos6560->screen); + + mos6560->type = intf->type; + + mos6560->bitmap = auto_bitmap_alloc(device->machine, width, height, BITMAP_FORMAT_INDEXED16); + + mos6560->dma_read = intf->dma_read; + mos6560->dma_read_color = intf->dma_read_color; + + mos6560->lightpen_button_cb = intf->button_cb; + mos6560->lightpen_x_cb = intf->x_cb; + mos6560->lightpen_y_cb = intf->y_cb; + + mos6560->paddle_cb[0] = intf->paddle0_cb; + mos6560->paddle_cb[1] = intf->paddle1_cb; + + switch (mos6560->type) + { + case MOS6560: + mos6560->total_xsize = MOS6560_XSIZE; + mos6560->total_ysize = MOS6560_YSIZE; + mos6560->total_lines = MOS6560_LINES; + mos6560->total_vretracerate = MOS6560_VRETRACERATE; + break; + case MOS6560_ATTACKUFO: + mos6560->total_xsize = 23 * 8; + mos6560->total_ysize = 22 * 8; + mos6560->total_lines = MOS6560_LINES; + mos6560->total_vretracerate = MOS6560_VRETRACERATE; + break; + case MOS6561: + mos6560->total_xsize = MOS6561_XSIZE; + mos6560->total_ysize = MOS6561_YSIZE; + mos6560->total_lines = MOS6561_LINES; + mos6560->total_vretracerate = MOS6561_VRETRACERATE; + break; + } + + mos6560_sound_start(device); + + state_save_register_device_item(device, 0, mos6560->lightpenreadtime); + state_save_register_device_item(device, 0, mos6560->rasterline); + state_save_register_device_item(device, 0, mos6560->lastline); + + state_save_register_device_item(device, 0, mos6560->charheight); + state_save_register_device_item(device, 0, mos6560->matrix8x16); + state_save_register_device_item(device, 0, mos6560->inverted); + state_save_register_device_item(device, 0, mos6560->chars_x); + state_save_register_device_item(device, 0, mos6560->chars_y); + state_save_register_device_item(device, 0, mos6560->xsize); + state_save_register_device_item(device, 0, mos6560->ysize); + state_save_register_device_item(device, 0, mos6560->xpos); + state_save_register_device_item(device, 0, mos6560->ypos); + state_save_register_device_item(device, 0, mos6560->chargenaddr); + state_save_register_device_item(device, 0, mos6560->videoaddr); + + state_save_register_device_item(device, 0, mos6560->backgroundcolor); + state_save_register_device_item(device, 0, mos6560->framecolor); + state_save_register_device_item(device, 0, mos6560->helpercolor); + + state_save_register_device_item_array(device, 0, mos6560->reg); + + state_save_register_device_item_array(device, 0, mos6560->mono); + state_save_register_device_item_array(device, 0, mos6560->monoinverted); + state_save_register_device_item_array(device, 0, mos6560->multi); + state_save_register_device_item_array(device, 0, mos6560->multiinverted); + + state_save_register_device_item_bitmap(device, 0, mos6560->bitmap); + + state_save_register_device_item(device, 0, mos6560->tone1pos); + state_save_register_device_item(device, 0, mos6560->tone2pos); + state_save_register_device_item(device, 0, mos6560->tone3pos); + state_save_register_device_item(device, 0, mos6560->tone1samples); + state_save_register_device_item(device, 0, mos6560->tone2samples); + state_save_register_device_item(device, 0, mos6560->tone3samples); + state_save_register_device_item(device, 0, mos6560->noisepos); + state_save_register_device_item(device, 0, mos6560->noisesamples); +} + +/*------------------------------------------------- + DEVICE_RESET( mos6560 ) +-------------------------------------------------*/ + +static DEVICE_RESET( mos6560 ) +{ + mos6560_state *mos6560 = get_safe_token(device); + + mos6560->lightpenreadtime = 0.0; + mos6560->rasterline = 0; + mos6560->lastline = 0; + + memset(mos6560->reg, 0, 16); + + mos6560->charheight = 8; + mos6560->matrix8x16 = 0; + mos6560->inverted = 0; + mos6560->chars_x = 0; + mos6560->chars_y = 0; + mos6560->xsize = 0; + mos6560->ysize = 0; + mos6560->xpos = 0; + mos6560->ypos = 0; + mos6560->chargenaddr = 0; + mos6560->videoaddr = 0; + + mos6560->backgroundcolor = 0; + mos6560->framecolor = 0; + mos6560->helpercolor = 0; + + mos6560->mono[0] = 0; + mos6560->mono[1] = 0; + mos6560->monoinverted[0] = 0; + mos6560->monoinverted[1] = 0; + mos6560->multi[0] = 0; + mos6560->multi[1] = 0; + mos6560->multi[2] = 0; + mos6560->multi[3] = 0; + mos6560->multiinverted[0] = 0; + mos6560->multiinverted[1] = 0; + mos6560->multiinverted[2] = 0; + mos6560->multiinverted[3] = 0; + + mos6560->tone1pos = 0; + mos6560->tone2pos = 0; + mos6560->tone3pos = 0; + mos6560->tone1samples = 1; + mos6560->tone2samples = 1; + mos6560->tone3samples = 1; + mos6560->noisepos = 0; + mos6560->noisesamples = 1; +} + + +/*------------------------------------------------- + Device definition +-------------------------------------------------*/ + +static const char DEVTEMPLATE_SOURCE[] = __FILE__; + +#define DEVTEMPLATE_ID(p,s) p##mos6560##s +#define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_RESET +#define DEVTEMPLATE_NAME "MOS 6560 / 6561 VIC" +#define DEVTEMPLATE_FAMILY "MOS Video Interface Chip" +#include "devtempl.h" diff --git a/src/emu/sound/mos6560.h b/src/emu/sound/mos6560.h new file mode 100644 index 00000000000..3892bfc6b88 --- /dev/null +++ b/src/emu/sound/mos6560.h @@ -0,0 +1,116 @@ +/***************************************************************************** + * + * audio/vic6560.h + * + ****************************************************************************/ + +#ifndef __MOS6560_H__ +#define __MOS6560_H__ + +#include "devcb.h" + + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +typedef UINT8 (*mos6560_lightpen_x_callback)(running_machine *machine); +typedef UINT8 (*mos6560_lightpen_y_callback)(running_machine *machine); +typedef UINT8 (*mos6560_lightpen_button_callback)(running_machine *machine); +typedef UINT8 (*mos6560_paddle_callback)(running_machine *machine); + +typedef int (*mos6560_dma_read)(running_machine *machine, int); +typedef int (*mos6560_dma_read_color)(running_machine *machine, int); + + +typedef enum +{ + MOS6560_ATTACKUFO, // this is a 6560VIC derivative, missing some of the features + MOS6560, // this is the NTSC version + MOS6561 // this is the PAL version +} mos6560_type; + +typedef struct _mos6560_interface mos6560_interface; +struct _mos6560_interface +{ + const char *screen; + + mos6560_type type; + + mos6560_lightpen_x_callback x_cb; + mos6560_lightpen_y_callback y_cb; + mos6560_lightpen_button_callback button_cb; + + mos6560_paddle_callback paddle0_cb, paddle1_cb; + + mos6560_dma_read dma_read; + mos6560_dma_read_color dma_read_color; +}; + +/*************************************************************************** + CONSTANTS +***************************************************************************/ + +#define MOS6560_VRETRACERATE 60 +#define MOS6561_VRETRACERATE 50 +#define MOS656X_HRETRACERATE 15625 + +#define MOS6560_MAME_XPOS 4 /* xleft not displayed */ +#define MOS6560_MAME_YPOS 10 /* y up not displayed */ +#define MOS6561_MAME_XPOS 20 +#define MOS6561_MAME_YPOS 10 +#define MOS6560_MAME_XSIZE 200 +#define MOS6560_MAME_YSIZE 248 +#define MOS6561_MAME_XSIZE 224 +#define MOS6561_MAME_YSIZE 296 +/* real values */ + +#define MOS6560_LINES 261 +#define MOS6561_LINES 312 + +#define MOS6560_XSIZE (4+201) /* 4 left not visible */ +#define MOS6560_YSIZE (10+251) /* 10 not visible */ +/* cycles 65 */ + +#define MOS6561_XSIZE (20+229) /* 20 left not visible */ +#define MOS6561_YSIZE (10+302) /* 10 not visible */ +/* cycles 71 */ + + +/* the following values depend on the VIC clock, + * but to achieve TV-frequency the clock must have a fix frequency */ +#define MOS6560_CLOCK (14318181/14) +#define MOS6561_CLOCK (4433618/4) + + +/*************************************************************************** + INFO PROTOTYPES +***************************************************************************/ + +DEVICE_GET_INFO( mos6560 ); + +/*************************************************************************** + DEVICE CONFIGURATION MACROS +***************************************************************************/ + +#define MOS656X DEVICE_GET_INFO_NAME( mos6560 ) +#define SOUND_MOS656X MOS656X + +#define MDRV_MOS656X_ADD(_tag, _interface) \ + MDRV_DEVICE_ADD(_tag, SOUND, 0) \ + MDRV_DEVICE_CONFIG_DATAPTR(sound_config, type, SOUND_MOS656X) \ + MDRV_DEVICE_CONFIG(_interface) + + +/*************************************************************************** + I/O PROTOTYPES +***************************************************************************/ + +WRITE8_DEVICE_HANDLER( mos6560_port_w ); +READ8_DEVICE_HANDLER( mos6560_port_r ); + +void mos6560_raster_interrupt_gen( running_device *device ); +UINT32 mos6560_video_update( running_device *device, bitmap_t *bitmap, const rectangle *cliprect ); + + +#endif /* __MOS6560_H__ */ diff --git a/src/emu/sound/sound.mak b/src/emu/sound/sound.mak index 5128659471f..999e798a061 100644 --- a/src/emu/sound/sound.mak +++ b/src/emu/sound/sound.mak @@ -270,6 +270,17 @@ SOUNDOBJS += $(SOUNDOBJ)/k056800.o endif + +#------------------------------------------------- +# MOS 6560VIC +#------------------------------------------------- + +ifneq ($(filter MOS656X,$(SOUNDS)),) +SOUNDOBJS += $(SOUNDOBJ)/mos6560.o +endif + + + #------------------------------------------------- # Namco custom sound chips #------------------------------------------------- diff --git a/src/mame/drivers/attckufo.c b/src/mame/drivers/attckufo.c index 7dc2a6c8736..0aa5be82a4f 100644 --- a/src/mame/drivers/attckufo.c +++ b/src/mame/drivers/attckufo.c @@ -43,12 +43,36 @@ LOIPOIO-B #include "emu.h" #include "cpu/m6502/m6502.h" -#include "includes/attckufo.h" +#include "sound/mos6560.h" static UINT8 *mainram; static UINT8 *tileram; +static const rgb_t attckufo_palette[] = +{ +/* ripped from vice, a very excellent emulator */ + MAKE_RGB(0x00, 0x00, 0x00), + MAKE_RGB(0xff, 0xff, 0xff), + MAKE_RGB(0xf0, 0x00, 0x00), + MAKE_RGB(0x00, 0xf0, 0xf0), + + MAKE_RGB(0x60, 0x00, 0x60), + MAKE_RGB(0x00, 0xa0, 0x00), + MAKE_RGB(0x00, 0x00, 0xf0), + MAKE_RGB(0xd0, 0xd0, 0x00), + + MAKE_RGB(0xc0, 0xa0, 0x00), + MAKE_RGB(0xff, 0xa0, 0x00), + MAKE_RGB(0xf0, 0x80, 0x80), + MAKE_RGB(0x00, 0xff, 0xff), + + MAKE_RGB(0xff, 0x00, 0xff), + MAKE_RGB(0x00, 0xff, 0x00), + MAKE_RGB(0x00, 0xa0, 0xff), + MAKE_RGB(0xff, 0xff, 0x00) +}; + static PALETTE_INIT( attckufo ) { palette_set_colors(machine, 0, attckufo_palette, ARRAY_LENGTH(attckufo_palette)); @@ -80,7 +104,7 @@ static WRITE8_HANDLER(attckufo_io_w) static ADDRESS_MAP_START( cpu_map, ADDRESS_SPACE_PROGRAM, 8 ) ADDRESS_MAP_GLOBAL_MASK(0x3fff) AM_RANGE(0x0000, 0x0fff) AM_RAM AM_BASE(&mainram) - AM_RANGE(0x1000, 0x100f) AM_READWRITE(attckufo_port_r, attckufo_port_w) + AM_RANGE(0x1000, 0x100f) AM_DEVREADWRITE("mos6560", mos6560_port_r, mos6560_port_w) AM_RANGE(0x1400, 0x1403) AM_READWRITE(attckufo_io_r, attckufo_io_w) AM_RANGE(0x1c00, 0x1fff) AM_RAM AM_BASE(&tileram) AM_RANGE(0x2000, 0x3fff) AM_ROM @@ -114,28 +138,61 @@ static INPUT_PORTS_START( attckufo ) INPUT_PORTS_END +INTERRUPT_GEN( attckufo_raster_interrupt ) +{ + running_device *mos6560 = devtag_get_device(device->machine, "mos6560"); + mos6560_raster_interrupt_gen(mos6560); +} + +VIDEO_UPDATE( attckufo ) +{ + running_device *mos6560 = devtag_get_device(screen->machine, "mos6560"); + mos6560_video_update(mos6560, bitmap, cliprect); + return 0; +} + +static int attckufo_dma_read( running_machine *machine, int offset ) +{ + const address_space *program = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM); + return memory_read_byte(program, offset); +} + +static int attckufo_dma_read_color( running_machine *machine, int offset ) +{ + const address_space *program = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM); + return memory_read_byte(program, offset + 0x400); +} + +static const mos6560_interface attckufo_6560_intf = +{ + "screen", /* screen */ + MOS6560_ATTACKUFO, + NULL, NULL, NULL, /* lightgun cb */ + NULL, NULL, /* paddle cb */ + attckufo_dma_read, attckufo_dma_read_color /* DMA */ +}; + static MACHINE_DRIVER_START( attckufo ) MDRV_CPU_ADD("maincpu", M6502, 14318181/14) MDRV_CPU_PROGRAM_MAP(cpu_map) - MDRV_CPU_PERIODIC_INT(attckufo_raster_interrupt, 15625) - - /* video hardware */ + MDRV_CPU_PERIODIC_INT(attckufo_raster_interrupt, MOS656X_HRETRACERATE) + /* video hardware */ MDRV_SCREEN_ADD("screen", RASTER) - MDRV_SCREEN_REFRESH_RATE(60) - MDRV_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500) /* not accurate */) + MDRV_SCREEN_REFRESH_RATE(MOS6560_VRETRACERATE) + MDRV_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */ MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) - MDRV_SCREEN_SIZE(256, 256) - MDRV_SCREEN_VISIBLE_AREA(0, 23*8-1, 0, 22*8-1) + MDRV_SCREEN_SIZE((MOS6560_XSIZE + 7) & ~7, MOS6560_YSIZE) + MDRV_SCREEN_VISIBLE_AREA(0, 23*8 - 1, 0, 22*8 - 1) MDRV_PALETTE_LENGTH(ARRAY_LENGTH(attckufo_palette)) - MDRV_PALETTE_INIT( attckufo ) + MDRV_PALETTE_INIT(attckufo) - MDRV_VIDEO_UPDATE( attckufo ) + MDRV_VIDEO_UPDATE(attckufo) /* sound hardware */ MDRV_SPEAKER_STANDARD_MONO("mono") - MDRV_SOUND_ADD("attckufo", ATTCKUFO, 0) + MDRV_MOS656X_ADD("mos6560", attckufo_6560_intf) MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0) MACHINE_DRIVER_END @@ -154,4 +211,4 @@ ROM_START( attckufo ) ROM_COPY( "maincpu", 0x02000, 0x00000, 0x400) ROM_END -GAME( 1980, attckufo, 0, attckufo, attckufo, 0, ROT270, "Ryoto Electric Co.", "Attack Ufo", 0) +GAME( 1980, attckufo, 0, attckufo, attckufo, 0, ROT270, "Ryoto Electric Co.", "Attack Ufo", 0 ) diff --git a/src/mame/includes/attckufo.h b/src/mame/includes/attckufo.h deleted file mode 100644 index ea279a4a16d..00000000000 --- a/src/mame/includes/attckufo.h +++ /dev/null @@ -1,20 +0,0 @@ -/*----------- defined in audio/attckufo.c -----------*/ - -void attckufo_soundport_w (int offset, int data); - -DEVICE_GET_INFO( attckufo_sound ); -#define SOUND_ATTCKUFO DEVICE_GET_INFO_NAME(attckufo_sound) - - -/*----------- defined in video/attckufo.c -----------*/ - -extern const rgb_t attckufo_palette[16]; -extern UINT8 attckufo_regs[16]; - -VIDEO_UPDATE( attckufo ); - -WRITE8_HANDLER ( attckufo_port_w ); -READ8_HANDLER ( attckufo_port_r ); - -INTERRUPT_GEN( attckufo_raster_interrupt ); - diff --git a/src/mame/mame.mak b/src/mame/mame.mak index 6e7ddaf7a2a..8bf584cef0c 100644 --- a/src/mame/mame.mak +++ b/src/mame/mame.mak @@ -221,6 +221,7 @@ SOUNDS += DIGITALKER SOUNDS += CDP1863 SOUNDS += CDP1864 SOUNDS += ZSG2 +SOUNDS += MOS656X #------------------------------------------------- # this is the list of driver libraries that @@ -1485,7 +1486,7 @@ $(MAMEOBJ)/misc.a: \ $(DRIVERS)/amspdwy.o $(VIDEO)/amspdwy.o \ $(DRIVERS)/artmagic.o $(VIDEO)/artmagic.o \ $(DRIVERS)/astrocorp.o \ - $(DRIVERS)/attckufo.o $(AUDIO)/attckufo.o $(VIDEO)/attckufo.o \ + $(DRIVERS)/attckufo.o \ $(DRIVERS)/aztarac.o $(AUDIO)/aztarac.o $(VIDEO)/aztarac.o \ $(DRIVERS)/beaminv.o \ $(DRIVERS)/big10.o \ diff --git a/src/mame/video/attckufo.c b/src/mame/video/attckufo.c deleted file mode 100644 index b2882c21c43..00000000000 --- a/src/mame/video/attckufo.c +++ /dev/null @@ -1,171 +0,0 @@ -/*************************************************************************** - - Attack ufo video emulation - based on MOS 6560 emulator by - PeT mess@utanet.at - - Differences between 6560 and Attack Ufo chip: - - no invert mode - - no multicolor - - 16 col chars - -***************************************************************************/ - -#include "emu.h" -#include "includes/attckufo.h" - -#define MAX_LINES 261 - -const rgb_t attckufo_palette[] = -{ -/* ripped from vice, a very excellent emulator */ - MAKE_RGB(0x00, 0x00, 0x00), - MAKE_RGB(0xff, 0xff, 0xff), - MAKE_RGB(0xf0, 0x00, 0x00), - MAKE_RGB(0x00, 0xf0, 0xf0), - - MAKE_RGB(0x60, 0x00, 0x60), - MAKE_RGB(0x00, 0xa0, 0x00), - MAKE_RGB(0x00, 0x00, 0xf0), - MAKE_RGB(0xd0, 0xd0, 0x00), - - MAKE_RGB(0xc0, 0xa0, 0x00), - MAKE_RGB(0xff, 0xa0, 0x00), - MAKE_RGB(0xf0, 0x80, 0x80), - MAKE_RGB(0x00, 0xff, 0xff), - - MAKE_RGB(0xff, 0x00, 0xff), - MAKE_RGB(0x00, 0xff, 0x00), - MAKE_RGB(0x00, 0xa0, 0xff), - MAKE_RGB(0xff, 0xff, 0x00) -}; - - - -UINT8 attckufo_regs[16]; - -#define CHARS_X ((int)attckufo_regs[2]&0x7f) -#define CHARS_Y (((int)attckufo_regs[3]&0x7e)>>1) - - -#define XSIZE (CHARS_X*8) -#define YSIZE (CHARS_Y*8) - -#define CHARGENADDR (((int)attckufo_regs[5]&0xf)<<10) -#define VIDEOADDR ( ( ((int)attckufo_regs[5]&0xf0)<<(10-4))\ - | ( ((int)attckufo_regs[2]&0x80)<<(9-7)) ) - -static int rasterline = 0; - -static int chars_x, chars_y; -static int xsize, ysize ; -static int chargenaddr, videoaddr; - -WRITE8_HANDLER ( attckufo_port_w ) -{ - switch (offset) - { - case 0xa: - case 0xb: - case 0xc: - case 0xd: - case 0xe: - attckufo_soundport_w (offset, data); - break; - } - if (attckufo_regs[offset] != data) - { - switch (offset) - { - case 0: - case 1: - case 2: - case 3: - case 5: - case 0xe: - case 0xf: - video_screen_update_partial(space->machine->primary_screen, rasterline); - break; - } - attckufo_regs[offset] = data; - switch (offset) - { - case 2: - /* ntsc values >= 31 behave like 31 */ - chars_x = CHARS_X; - videoaddr = VIDEOADDR; - xsize = XSIZE; - break; - case 3: - chars_y = CHARS_Y; - ysize = YSIZE; - break; - case 5: - chargenaddr = CHARGENADDR; - videoaddr = VIDEOADDR; - break; - } - } -} - - READ8_HANDLER ( attckufo_port_r ) -{ - int val; - - switch (offset) - { - case 3: - val = ((rasterline & 1) << 7) | (attckufo_regs[offset] & 0x7f); - break; - case 4: /*rasterline */ - val = (rasterline / 2) & 0xff; - break; - default: - val = attckufo_regs[offset]; - break; - } - return val; -} - -INTERRUPT_GEN( attckufo_raster_interrupt ) -{ - rasterline++; - if (rasterline >= MAX_LINES) - rasterline = 0; -} - -VIDEO_UPDATE( attckufo ) -{ - const address_space *space = cputag_get_address_space(screen->machine, "maincpu", ADDRESS_SPACE_PROGRAM); - int x, y, yy; - - for (y = cliprect->min_y & ~7; y <= cliprect->max_y; y += 8) - { - UINT16 *destrow = BITMAP_ADDR16(bitmap, y, 0); - int offs = videoaddr + (y / 8) * chars_x; - int ymin = MAX(y, cliprect->min_y) & 7; - int ymax = MIN(y + 7, cliprect->max_y) & 7; - - for (x = cliprect->min_x & ~7; x <= cliprect->max_x; x += 8) - { - UINT8 ch = memory_read_byte(space, offs + x/8); - UINT8 attr = memory_read_byte(space, offs + x/8 + 0x400) & 0xf; - UINT16 *dest = destrow; - - for (yy = ymin; yy <= ymax; yy++) - { - UINT8 code = memory_read_byte(space, chargenaddr + ch * 8 + yy); - dest[x + 0] = (code & 0x80) ? attr : 0; - dest[x + 1] = (code & 0x40) ? attr : 0; - dest[x + 2] = (code & 0x20) ? attr : 0; - dest[x + 3] = (code & 0x10) ? attr : 0; - dest[x + 4] = (code & 0x08) ? attr : 0; - dest[x + 5] = (code & 0x04) ? attr : 0; - dest[x + 6] = (code & 0x02) ? attr : 0; - dest[x + 7] = (code & 0x01) ? attr : 0; - dest += bitmap->rowpixels; - } - } - } - return 0; -}