attckufo: Imported MOS6560 device emulation from MESS and removed the existent custom audio/video emulation [Fabio Priuli]

This commit is contained in:
Fabio Priuli 2010-02-17 17:07:06 +00:00
parent 9d7196b0fe
commit f26c5bf115
8 changed files with 1111 additions and 207 deletions

4
.gitattributes vendored
View File

@ -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

910
src/emu/sound/mos6560.c Normal file
View File

@ -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"

116
src/emu/sound/mos6560.h Normal file
View File

@ -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__ */

View File

@ -270,6 +270,17 @@ SOUNDOBJS += $(SOUNDOBJ)/k056800.o
endif
#-------------------------------------------------
# MOS 6560VIC
#-------------------------------------------------
ifneq ($(filter MOS656X,$(SOUNDS)),)
SOUNDOBJS += $(SOUNDOBJ)/mos6560.o
endif
#-------------------------------------------------
# Namco custom sound chips
#-------------------------------------------------

View File

@ -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 )

View File

@ -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 );

View File

@ -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 \

View File

@ -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;
}