~ubuntu-branches/ubuntu/raring/mame/raring-proposed

« back to all changes in this revision

Viewing changes to mess/src/mess/video/spectrum.c

  • Committer: Package Import Robot
  • Author(s): Jordi Mallach, Jordi Mallach, Emmanuel Kasper
  • Date: 2011-12-19 22:56:27 UTC
  • mfrom: (0.1.2)
  • Revision ID: package-import@ubuntu.com-20111219225627-ub5oga1oys4ogqzm
Tags: 0.144-1
[ Jordi Mallach ]
* Fix syntax errors in DEP5 copyright file (lintian).
* Use a versioned copyright Format specification field.
* Update Vcs-* URLs.
* Move transitional packages to the new metapackages section, and make
  them priority extra.
* Remove references to GNU/Linux and MESS sources from copyright.
* Add build variables for s390x.
* Use .xz tarballs as it cuts 4MB for the upstream sources.
* Add nplayers.ini as a patch. Update copyright file to add CC-BY-SA-3.0.

[ Emmanuel Kasper ]
* New upstream release. Closes: #651538.
* Add Free Desktop compliant png icons of various sizes taken from
  the hydroxygen iconset
* Mess is now built from a new source package, to avoid possible source
  incompatibilities between mame and the mess overlay.
* Mame-tools are not built from the mame source package anymore, but
  from the mess source package

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/***************************************************************************
2
 
 
3
 
  spectrum.c
4
 
 
5
 
  Functions to emulate the video hardware of the ZX Spectrum.
6
 
 
7
 
  Changes:
8
 
 
9
 
  DJR 08/02/00 - Added support for FLASH 1.
10
 
  DJR 16/05/00 - Support for TS2068/TC2048 hires and 64 column modes.
11
 
  DJR 19/05/00 - Speeded up Spectrum 128 screen refresh.
12
 
  DJR 23/05/00 - Preliminary support for border colour emulation.
13
 
 
14
 
***************************************************************************/
15
 
 
16
 
#include "emu.h"
17
 
#include "includes/spectrum.h"
18
 
 
19
 
/***************************************************************************
20
 
  Start the video hardware emulation.
21
 
***************************************************************************/
22
 
VIDEO_START( spectrum )
23
 
{
24
 
        spectrum_state *state = machine.driver_data<spectrum_state>();
25
 
        state->m_LastDisplayedBorderColor = -1;
26
 
        state->m_frame_invert_count = 25;
27
 
        state->m_frame_number = 0;
28
 
        state->m_flash_invert = 0;
29
 
 
30
 
        spectrum_EventList_Initialise(machine, 30000);
31
 
 
32
 
        state->m_retrace_cycles = SPEC_RETRACE_CYCLES;
33
 
 
34
 
        state->m_screen_location = state->m_video_ram;
35
 
}
36
 
 
37
 
VIDEO_START( spectrum_128 )
38
 
{
39
 
        spectrum_state *state = machine.driver_data<spectrum_state>();
40
 
        state->m_LastDisplayedBorderColor = -1;
41
 
        state->m_frame_invert_count = 25;
42
 
        state->m_frame_number = 0;
43
 
        state->m_flash_invert = 0;
44
 
 
45
 
        spectrum_EventList_Initialise(machine, 30000);
46
 
 
47
 
        state->m_retrace_cycles = SPEC128_RETRACE_CYCLES;
48
 
}
49
 
 
50
 
 
51
 
/* return the color to be used inverting FLASHing colors if necessary */
52
 
INLINE unsigned char get_display_color (unsigned char color, int invert)
53
 
{
54
 
        if (invert && (color & 0x80))
55
 
                return (color & 0xc0) + ((color & 0x38) >> 3) + ((color & 0x07) << 3);
56
 
        else
57
 
                return color;
58
 
}
59
 
 
60
 
/* Code to change the FLASH status every 25 frames. Note this must be
61
 
   independent of frame skip etc. */
62
 
SCREEN_EOF( spectrum )
63
 
{
64
 
        spectrum_state *state = machine.driver_data<spectrum_state>();
65
 
        EVENT_LIST_ITEM *pItem;
66
 
        int NumItems;
67
 
 
68
 
        state->m_frame_number++;
69
 
        if (state->m_frame_number >= state->m_frame_invert_count)
70
 
        {
71
 
                state->m_frame_number = 0;
72
 
                state->m_flash_invert = !state->m_flash_invert;
73
 
        }
74
 
 
75
 
        /* Empty event buffer for undisplayed frames noting the last border
76
 
       colour (in case colours are not changed in the next frame). */
77
 
        NumItems = spectrum_EventList_NumEvents(machine);
78
 
        if (NumItems)
79
 
        {
80
 
                pItem = spectrum_EventList_GetFirstItem(machine);
81
 
                spectrum_border_set_last_color ( machine, pItem[NumItems-1].Event_Data );
82
 
                spectrum_EventList_Reset(machine);
83
 
                spectrum_EventList_SetOffsetStartTime ( machine, machine.firstcpu->attotime_to_cycles(machine.primary_screen->scan_period() * machine.primary_screen->vpos()) );
84
 
                logerror ("Event log reset in callback fn.\n");
85
 
        }
86
 
}
87
 
 
88
 
 
89
 
 
90
 
/***************************************************************************
91
 
  Update the spectrum screen display.
92
 
 
93
 
  The screen consists of 312 scanlines as follows:
94
 
  64  border lines (the last 48 are actual border lines; the others may be
95
 
                    border lines or vertical retrace)
96
 
  192 screen lines
97
 
  56  border lines
98
 
 
99
 
  Each screen line has 48 left border pixels, 256 screen pixels and 48 right
100
 
  border pixels.
101
 
 
102
 
  Each scanline takes 224 T-states divided as follows:
103
 
  128 Screen (reads a screen and ATTR byte [8 pixels] every 4 T states)
104
 
  24  Right border
105
 
  48  Horizontal retrace
106
 
  24  Left border
107
 
 
108
 
  The 128K Spectrums have only 63 scanlines before the TV picture (311 total)
109
 
  and take 228 T-states per scanline.
110
 
 
111
 
***************************************************************************/
112
 
 
113
 
INLINE void spectrum_plot_pixel(bitmap_t *bitmap, int x, int y, UINT32 color)
114
 
{
115
 
        *BITMAP_ADDR16(bitmap, y, x) = (UINT16)color;
116
 
}
117
 
 
118
 
SCREEN_UPDATE( spectrum )
119
 
{
120
 
        /* for now do a full-refresh */
121
 
        spectrum_state *state = screen->machine().driver_data<spectrum_state>();
122
 
        int x, y, b, scrx, scry;
123
 
        unsigned short ink, pap;
124
 
        unsigned char *attr, *scr;
125
 
                int full_refresh = 1;
126
 
 
127
 
        scr=state->m_screen_location;
128
 
 
129
 
        for (y=0; y<192; y++)
130
 
        {
131
 
                scrx=SPEC_LEFT_BORDER;
132
 
                scry=((y&7) * 8) + ((y&0x38)>>3) + (y&0xC0);
133
 
                attr=state->m_screen_location + ((scry>>3)*32) + 0x1800;
134
 
 
135
 
                for (x=0;x<32;x++)
136
 
                {
137
 
                        /* Get ink and paper colour with bright */
138
 
                        if (state->m_flash_invert && (*attr & 0x80))
139
 
                        {
140
 
                                ink=((*attr)>>3) & 0x0f;
141
 
                                pap=((*attr) & 0x07) + (((*attr)>>3) & 0x08);
142
 
                        }
143
 
                        else
144
 
                        {
145
 
                                ink=((*attr) & 0x07) + (((*attr)>>3) & 0x08);
146
 
                                pap=((*attr)>>3) & 0x0f;
147
 
                        }
148
 
 
149
 
                        for (b=0x80;b!=0;b>>=1)
150
 
                        {
151
 
                                if (*scr&b)
152
 
                                        spectrum_plot_pixel(bitmap,scrx++,SPEC_TOP_BORDER+scry,ink);
153
 
                                else
154
 
                                        spectrum_plot_pixel(bitmap,scrx++,SPEC_TOP_BORDER+scry,pap);
155
 
                        }
156
 
 
157
 
                        scr++;
158
 
                        attr++;
159
 
                }
160
 
        }
161
 
 
162
 
        spectrum_border_draw(screen->machine(), bitmap, full_refresh,
163
 
                SPEC_TOP_BORDER, SPEC_DISPLAY_YSIZE, SPEC_BOTTOM_BORDER,
164
 
                SPEC_LEFT_BORDER, SPEC_DISPLAY_XSIZE, SPEC_RIGHT_BORDER,
165
 
                SPEC_LEFT_BORDER_CYCLES, SPEC_DISPLAY_XSIZE_CYCLES,
166
 
                SPEC_RIGHT_BORDER_CYCLES, state->m_retrace_cycles, 200, 0xfe);
167
 
        return 0;
168
 
}
169
 
 
170
 
 
171
 
static const rgb_t spectrum_palette[16] = {
172
 
        MAKE_RGB(0x00, 0x00, 0x00),
173
 
        MAKE_RGB(0x00, 0x00, 0xbf),
174
 
        MAKE_RGB(0xbf, 0x00, 0x00),
175
 
        MAKE_RGB(0xbf, 0x00, 0xbf),
176
 
        MAKE_RGB(0x00, 0xbf, 0x00),
177
 
        MAKE_RGB(0x00, 0xbf, 0xbf),
178
 
        MAKE_RGB(0xbf, 0xbf, 0x00),
179
 
        MAKE_RGB(0xbf, 0xbf, 0xbf),
180
 
        MAKE_RGB(0x00, 0x00, 0x00),
181
 
        MAKE_RGB(0x00, 0x00, 0xff),
182
 
        MAKE_RGB(0xff, 0x00, 0x00),
183
 
        MAKE_RGB(0xff, 0x00, 0xff),
184
 
        MAKE_RGB(0x00, 0xff, 0x00),
185
 
        MAKE_RGB(0x00, 0xff, 0xff),
186
 
        MAKE_RGB(0xff, 0xff, 0x00),
187
 
        MAKE_RGB(0xff, 0xff, 0xff)
188
 
};
189
 
/* Initialise the palette */
190
 
PALETTE_INIT( spectrum )
191
 
{
192
 
        palette_set_colors(machine, 0, spectrum_palette, ARRAY_LENGTH(spectrum_palette));
193
 
}
194
 
 
195
 
/***************************************************************************
196
 
        Border engine:
197
 
 
198
 
        Functions for drawing multi-coloured screen borders using the
199
 
        Event List processing.
200
 
 
201
 
Changes:
202
 
 
203
 
28/05/2000 DJR - Initial implementation.
204
 
08/06/2000 DJR - Now only uses events with the correct ID value.
205
 
28/06/2000 DJR - draw_border now uses full_refresh flag.
206
 
 
207
 
***************************************************************************/
208
 
 
209
 
/* Force the border to be redrawn on the next frame */
210
 
void spectrum_border_force_redraw (running_machine &machine)
211
 
{
212
 
        spectrum_state *state = machine.driver_data<spectrum_state>();
213
 
        state->m_LastDisplayedBorderColor = -1;
214
 
}
215
 
 
216
 
/* Set the last border colour to have been displayed. Used when loading snap
217
 
   shots and to record the last colour change in a frame that was skipped. */
218
 
void spectrum_border_set_last_color(running_machine &machine, int NewColor)
219
 
{
220
 
        spectrum_state *state = machine.driver_data<spectrum_state>();
221
 
        state->m_CurrBorderColor = NewColor;
222
 
}
223
 
 
224
 
void spectrum_border_draw(running_machine &machine, bitmap_t *bitmap,
225
 
        int full_refresh,               /* Full refresh flag */
226
 
        int TopBorderLines,             /* Border lines before actual screen */
227
 
        int ScreenLines,                /* Screen height in pixels */
228
 
        int BottomBorderLines,          /* Border lines below screen */
229
 
        int LeftBorderPixels,           /* Border pixels to the left of each screen line */
230
 
        int ScreenPixels,               /* Width of actual screen in pixels */
231
 
        int RightBorderPixels,          /* Border pixels to the right of each screen line */
232
 
        int LeftBorderCycles,           /* Cycles taken to draw left border of each scan line */
233
 
        int ScreenCycles,               /* Cycles taken to draw screen data part of each scan line */
234
 
        int RightBorderCycles,          /* Cycles taken to draw right border of each scan line */
235
 
        int HorizontalRetraceCycles,    /* Cycles taken to return to LHS of CRT after each scan line */
236
 
        int VRetraceTime,               /* Cycles taken before start of first border line */
237
 
        int EventID)                    /* Event ID of border messages */
238
 
{
239
 
        spectrum_state *state = machine.driver_data<spectrum_state>();
240
 
        EVENT_LIST_ITEM *pItem;
241
 
        int TotalScreenHeight = TopBorderLines+ScreenLines+BottomBorderLines;
242
 
        int TotalScreenWidth = LeftBorderPixels+ScreenPixels+RightBorderPixels;
243
 
        int DisplayCyclesPerLine = LeftBorderCycles+ScreenCycles+RightBorderCycles;
244
 
        int CyclesPerLine = DisplayCyclesPerLine+HorizontalRetraceCycles;
245
 
        int CyclesSoFar = 0;
246
 
        int NumItems, CurrItem = 0, NextItem;
247
 
        int Count, ScrX, NextScrX, ScrY;
248
 
        rectangle r;
249
 
 
250
 
        pItem = spectrum_EventList_GetFirstItem(machine);
251
 
        NumItems = spectrum_EventList_NumEvents(machine);
252
 
 
253
 
        for (Count = 0; Count < NumItems; Count++)
254
 
        {
255
 
//      logerror ("Event no %05d, ID = %04x, data = %04x, time = %ld\n", Count, pItem[Count].Event_ID, pItem[Count].Event_Data, (long) pItem[Count].Event_Time);
256
 
        }
257
 
 
258
 
        /* Find the first and second events with the correct ID */
259
 
        while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID))
260
 
                CurrItem++;
261
 
        NextItem = CurrItem + 1;
262
 
        while ((NextItem < NumItems) && (pItem[NextItem].Event_ID != EventID))
263
 
                NextItem++;
264
 
 
265
 
        /* Single border colour */
266
 
        if ((CurrItem < NumItems) && (NextItem >= NumItems))
267
 
                state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
268
 
 
269
 
        if ((NextItem >= NumItems) && (state->m_CurrBorderColor==state->m_LastDisplayedBorderColor) && !full_refresh)
270
 
        {
271
 
                /* Do nothing if border colour has not changed */
272
 
        }
273
 
        else if (NextItem >= NumItems)
274
 
        {
275
 
                        /* Single border colour - this is not strictly correct as the
276
 
                colour change may have occurred midway through the frame
277
 
                or after the last visible border line however the whole
278
 
                border would be redrawn in the correct colour during the
279
 
                next frame anyway! */
280
 
                r.min_x = 0;
281
 
                r.max_x = TotalScreenWidth-1;
282
 
                r.min_y = 0;
283
 
                r.max_y = TopBorderLines-1;
284
 
                bitmap_fill(bitmap, &r, machine.pens[state->m_CurrBorderColor]);
285
 
 
286
 
                r.min_x = 0;
287
 
                r.max_x = LeftBorderPixels-1;
288
 
                r.min_y = TopBorderLines;
289
 
                r.max_y = TopBorderLines+ScreenLines-1;
290
 
                bitmap_fill(bitmap, &r, machine.pens[state->m_CurrBorderColor]);
291
 
 
292
 
                r.min_x = LeftBorderPixels+ScreenPixels;
293
 
                r.max_x = TotalScreenWidth-1;
294
 
                bitmap_fill(bitmap, &r, machine.pens[state->m_CurrBorderColor]);
295
 
 
296
 
                r.min_x = 0;
297
 
                r.max_x = TotalScreenWidth-1;
298
 
                r.min_y = TopBorderLines+ScreenLines;
299
 
                r.max_y = TotalScreenHeight-1;
300
 
                bitmap_fill(bitmap, &r, machine.pens[state->m_CurrBorderColor]);
301
 
 
302
 
//          logerror ("Setting border colour to %d (Last = %d, Full Refresh = %d)\n", state->m_CurrBorderColor, state->m_LastDisplayedBorderColor, full_refresh);
303
 
                state->m_LastDisplayedBorderColor = state->m_CurrBorderColor;
304
 
        }
305
 
        else
306
 
        {
307
 
                /* Multiple border colours */
308
 
 
309
 
                /* Process entries before first displayed line */
310
 
                while ((CurrItem < NumItems) && (pItem[CurrItem].Event_Time <= VRetraceTime))
311
 
                {
312
 
                        state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
313
 
                        do {
314
 
                                CurrItem++;
315
 
                        } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
316
 
                }
317
 
 
318
 
                /* Draw top border */
319
 
                CyclesSoFar = VRetraceTime;
320
 
                for (ScrY = 0; ScrY < TopBorderLines; ScrY++)
321
 
                {
322
 
                        r.min_x = 0;
323
 
                        r.min_y = r.max_y = ScrY;
324
 
                        if ((CurrItem >= NumItems) || (pItem[CurrItem].Event_Time >= (CyclesSoFar+DisplayCyclesPerLine)))
325
 
                        {
326
 
                                /* Single colour on line */
327
 
                                r.max_x = TotalScreenWidth-1;
328
 
                                bitmap_fill(bitmap, &r, machine.pens[state->m_CurrBorderColor]);
329
 
                        }
330
 
                        else
331
 
                        {
332
 
                                /* Multiple colours on a line */
333
 
                                ScrX = (int)(pItem[CurrItem].Event_Time - CyclesSoFar) * (float)TotalScreenWidth / (float)DisplayCyclesPerLine;
334
 
                                r.max_x = ScrX-1;
335
 
                                bitmap_fill(bitmap, &r, machine.pens[state->m_CurrBorderColor]);
336
 
                                state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
337
 
                                do {
338
 
                                        CurrItem++;
339
 
                                } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
340
 
 
341
 
                                while ((CurrItem < NumItems) && (pItem[CurrItem].Event_Time < (CyclesSoFar+DisplayCyclesPerLine)))
342
 
                                {
343
 
                                        NextScrX = (int)(pItem[CurrItem].Event_Time - CyclesSoFar) * (float)TotalScreenWidth / (float)DisplayCyclesPerLine;
344
 
                                        r.min_x = ScrX;
345
 
                                        r.max_x = NextScrX-1;
346
 
                                        bitmap_fill(bitmap, &r, machine.pens[state->m_CurrBorderColor]);
347
 
                                        ScrX = NextScrX;
348
 
                                        state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
349
 
                                        do {
350
 
                                                CurrItem++;
351
 
                                        } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
352
 
                                }
353
 
                                r.min_x = ScrX;
354
 
                                r.max_x = TotalScreenWidth-1;
355
 
                                bitmap_fill(bitmap, &r, machine.pens[state->m_CurrBorderColor]);
356
 
                        }
357
 
 
358
 
                        /* Process colour changes during horizontal retrace */
359
 
                        CyclesSoFar+= CyclesPerLine;
360
 
                        while ((CurrItem < NumItems) && (pItem[CurrItem].Event_Time <= CyclesSoFar))
361
 
                        {
362
 
                                state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
363
 
                                do {
364
 
                                        CurrItem++;
365
 
                                } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
366
 
                        }
367
 
                }
368
 
 
369
 
                /* Draw left and right borders next to screen lines */
370
 
                for (ScrY = TopBorderLines; ScrY < (TopBorderLines+ScreenLines); ScrY++)
371
 
                {
372
 
                        /* Draw left hand border */
373
 
                        r.min_x = 0;
374
 
                        r.min_y = r.max_y = ScrY;
375
 
 
376
 
                        if ((CurrItem >= NumItems) || (pItem[CurrItem].Event_Time >= (CyclesSoFar+LeftBorderCycles)))
377
 
                        {
378
 
                                /* Single colour */
379
 
                                r.max_x = LeftBorderPixels-1;
380
 
                                bitmap_fill(bitmap, &r, machine.pens[state->m_CurrBorderColor]);
381
 
                        }
382
 
                        else
383
 
                        {
384
 
                                /* Multiple colours */
385
 
                                ScrX = (int)(pItem[CurrItem].Event_Time - CyclesSoFar) * (float)LeftBorderPixels / (float)LeftBorderCycles;
386
 
                                r.max_x = ScrX-1;
387
 
                                bitmap_fill(bitmap, &r, machine.pens[state->m_CurrBorderColor]);
388
 
                                state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
389
 
                                do {
390
 
                                        CurrItem++;
391
 
                                } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
392
 
 
393
 
                                while ((CurrItem < NumItems) && (pItem[CurrItem].Event_Time < (CyclesSoFar+LeftBorderCycles)))
394
 
                                {
395
 
                                        NextScrX = (int)(pItem[CurrItem].Event_Time - CyclesSoFar) * (float)LeftBorderPixels / (float)LeftBorderCycles;
396
 
                                        r.min_x = ScrX;
397
 
                                        r.max_x = NextScrX-1;
398
 
                                        bitmap_fill(bitmap, &r, machine.pens[state->m_CurrBorderColor]);
399
 
                                        ScrX = NextScrX;
400
 
                                        state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
401
 
                                        do {
402
 
                                                CurrItem++;
403
 
                                        } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
404
 
                                }
405
 
                                r.min_x = ScrX;
406
 
                                r.max_x = LeftBorderPixels-1;
407
 
                                bitmap_fill(bitmap, &r, machine.pens[state->m_CurrBorderColor]);
408
 
                        }
409
 
 
410
 
                        /* Process colour changes during screen draw */
411
 
                        while ((CurrItem < NumItems) && (pItem[CurrItem].Event_Time <= (CyclesSoFar+LeftBorderCycles+ScreenCycles)))
412
 
                        {
413
 
                                state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
414
 
                                do {
415
 
                                        CurrItem++;
416
 
                                } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
417
 
                        }
418
 
 
419
 
                        /* Draw right hand border */
420
 
                        r.min_x = LeftBorderPixels+ScreenPixels;
421
 
                        if ((CurrItem >= NumItems) || (pItem[CurrItem].Event_Time >= (CyclesSoFar+DisplayCyclesPerLine)))
422
 
                        {
423
 
                                /* Single colour */
424
 
                                r.max_x = TotalScreenWidth-1;
425
 
                                bitmap_fill(bitmap, &r, machine.pens[state->m_CurrBorderColor]);
426
 
                        }
427
 
                        else
428
 
                        {
429
 
                                /* Multiple colours */
430
 
                                ScrX = LeftBorderPixels + ScreenPixels + (int)(pItem[CurrItem].Event_Time - CyclesSoFar) * (float)RightBorderPixels / (float)RightBorderCycles;
431
 
                                r.max_x = ScrX-1;
432
 
                                bitmap_fill(bitmap, &r, machine.pens[state->m_CurrBorderColor]);
433
 
                                state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
434
 
                                do {
435
 
                                        CurrItem++;
436
 
                                } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
437
 
 
438
 
                                while ((CurrItem < NumItems) && (pItem[CurrItem].Event_Time < (CyclesSoFar+DisplayCyclesPerLine)))
439
 
                                {
440
 
                                        NextScrX = LeftBorderPixels + ScreenPixels + (int)(pItem[CurrItem].Event_Time - CyclesSoFar) * (float)RightBorderPixels / (float)RightBorderCycles;
441
 
                                        r.min_x = ScrX;
442
 
                                        r.max_x = NextScrX-1;
443
 
                                        bitmap_fill(bitmap, &r, machine.pens[state->m_CurrBorderColor]);
444
 
                                        ScrX = NextScrX;
445
 
                                        state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
446
 
                                        do {
447
 
                                                CurrItem++;
448
 
                                        } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
449
 
                                }
450
 
                                r.min_x = ScrX;
451
 
                                r.max_x = TotalScreenWidth-1;
452
 
                                bitmap_fill(bitmap, &r, machine.pens[state->m_CurrBorderColor]);
453
 
                        }
454
 
 
455
 
                        /* Process colour changes during horizontal retrace */
456
 
                        CyclesSoFar+= CyclesPerLine;
457
 
                        while ((CurrItem < NumItems) && (pItem[CurrItem].Event_Time <= CyclesSoFar))
458
 
                        {
459
 
                                state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
460
 
                                do {
461
 
                                        CurrItem++;
462
 
                                } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
463
 
                        }
464
 
                }
465
 
 
466
 
                /* Draw bottom border */
467
 
                for (ScrY = TopBorderLines+ScreenLines; ScrY < TotalScreenHeight; ScrY++)
468
 
                {
469
 
                        r.min_x = 0;
470
 
                        r.min_y = r.max_y = ScrY;
471
 
                        if ((CurrItem >= NumItems) || (pItem[CurrItem].Event_Time >= (CyclesSoFar+DisplayCyclesPerLine)))
472
 
                        {
473
 
                                /* Single colour on line */
474
 
                                r.max_x = TotalScreenWidth-1;
475
 
                                bitmap_fill(bitmap, &r, machine.pens[state->m_CurrBorderColor]);
476
 
                        }
477
 
                        else
478
 
                        {
479
 
                                /* Multiple colours on a line */
480
 
                                ScrX = (int)(pItem[CurrItem].Event_Time - CyclesSoFar) * (float)TotalScreenWidth / (float)DisplayCyclesPerLine;
481
 
                                r.max_x = ScrX-1;
482
 
                                bitmap_fill(bitmap, &r, machine.pens[state->m_CurrBorderColor]);
483
 
                                state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
484
 
                                do {
485
 
                                        CurrItem++;
486
 
                                } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
487
 
 
488
 
                                while ((CurrItem < NumItems) && (pItem[CurrItem].Event_Time < (CyclesSoFar+DisplayCyclesPerLine)))
489
 
                                {
490
 
                                        NextScrX = (int)(pItem[CurrItem].Event_Time - CyclesSoFar) * (float)TotalScreenWidth / (float)DisplayCyclesPerLine;
491
 
                                        r.min_x = ScrX;
492
 
                                        r.max_x = NextScrX-1;
493
 
                                        bitmap_fill(bitmap, &r, machine.pens[state->m_CurrBorderColor]);
494
 
                                        ScrX = NextScrX;
495
 
                                        state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
496
 
                                        do {
497
 
                                                CurrItem++;
498
 
                                        } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
499
 
                                }
500
 
                                r.min_x = ScrX;
501
 
                                r.max_x = TotalScreenWidth-1;
502
 
                                bitmap_fill(bitmap, &r, machine.pens[state->m_CurrBorderColor]);
503
 
                        }
504
 
 
505
 
                        /* Process colour changes during horizontal retrace */
506
 
                        CyclesSoFar+= CyclesPerLine;
507
 
                        while ((CurrItem < NumItems) && (pItem[CurrItem].Event_Time <= CyclesSoFar))
508
 
                        {
509
 
                                state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
510
 
                                do {
511
 
                                        CurrItem++;
512
 
                                } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
513
 
                        }
514
 
                }
515
 
 
516
 
                /* Process colour changes after last displayed line */
517
 
                while (CurrItem < NumItems)
518
 
                {
519
 
                        if (pItem[CurrItem].Event_ID == EventID)
520
 
                                state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
521
 
                        CurrItem++;
522
 
                }
523
 
 
524
 
                /* Set value to ensure redraw on next frame */
525
 
                state->m_LastDisplayedBorderColor = -1;
526
 
 
527
 
//          logerror ("Multi coloured border drawn (last colour = %d)\n", CurrBorderColor);
528
 
        }
529
 
 
530
 
        /* Assume all other routines have processed their data from the list */
531
 
        spectrum_EventList_Reset(machine);
532
 
        spectrum_EventList_SetOffsetStartTime ( machine, machine.firstcpu->attotime_to_cycles(machine.primary_screen->scan_period() * machine.primary_screen->vpos()));
533
 
}
534
 
 
535
 
 
536
 
/* initialise */
537
 
 
538
 
/* if the CPU is the controlling factor, the size of the buffer
539
 
can be setup as:
540
 
 
541
 
Number_of_CPU_Cycles_In_A_Frame/Minimum_Number_Of_Cycles_Per_Instruction */
542
 
void spectrum_EventList_Initialise(running_machine &machine, int NumEntries)
543
 
{
544
 
        spectrum_state *state = machine.driver_data<spectrum_state>();
545
 
        state->m_pEventListBuffer = auto_alloc_array(machine, char, NumEntries);
546
 
        state->m_TotalEvents = NumEntries;
547
 
        state->m_CyclesPerFrame = 0;
548
 
        spectrum_EventList_Reset(machine);
549
 
}
550
 
 
551
 
/* reset the change list */
552
 
void spectrum_EventList_Reset(running_machine &machine)
553
 
{
554
 
        spectrum_state *state = machine.driver_data<spectrum_state>();
555
 
        state->m_NumEvents = 0;
556
 
        state->m_pCurrentItem = (EVENT_LIST_ITEM *)state->m_pEventListBuffer;
557
 
}
558
 
 
559
 
 
560
 
#ifdef UNUSED_FUNCTION
561
 
/* add an event to the buffer */
562
 
void EventList_AddItem(running_machine &machine, int ID, int Data, int Time)
563
 
{
564
 
        spectrum_state *state = machine.driver_data<spectrum_state>();
565
 
        if (state->m_NumEvents < state->m_TotalEvents)
566
 
        {
567
 
                /* setup item only if there is space in the buffer */
568
 
                state->m_pCurrentItem->Event_ID = ID;
569
 
                state->m_pCurrentItem->Event_Data = Data;
570
 
                state->m_pCurrentItem->Event_Time = Time;
571
 
 
572
 
                state->m_pCurrentItem++;
573
 
                state->m_NumEvents++;
574
 
        }
575
 
}
576
 
#endif
577
 
 
578
 
/* set the start time for use with EventList_AddItemOffset usually this will
579
 
   be cpu_getcurrentcycles() at the time that the screen is being refreshed */
580
 
void spectrum_EventList_SetOffsetStartTime(running_machine &machine, int StartTime)
581
 
{
582
 
        spectrum_state *state = machine.driver_data<spectrum_state>();
583
 
        state->m_LastFrameStartTime = StartTime;
584
 
}
585
 
 
586
 
/* add an event to the buffer with a time index offset from a specified time */
587
 
void spectrum_EventList_AddItemOffset(running_machine &machine, int ID, int Data, int Time)
588
 
{
589
 
        spectrum_state *state = machine.driver_data<spectrum_state>();
590
 
 
591
 
        if (!state->m_CyclesPerFrame)
592
 
                state->m_CyclesPerFrame = (int)(machine.firstcpu->unscaled_clock() / machine.primary_screen->frame_period().attoseconds);       //totalcycles();    //_(int)(cpunum_get_clock(0) / machine.config()->frames_per_second);
593
 
 
594
 
        if (state->m_NumEvents < state->m_TotalEvents)
595
 
        {
596
 
                /* setup item only if there is space in the buffer */
597
 
                state->m_pCurrentItem->Event_ID = ID;
598
 
                state->m_pCurrentItem->Event_Data = Data;
599
 
 
600
 
                Time -= state->m_LastFrameStartTime;
601
 
                if ((Time < 0) || ((Time == 0) && state->m_NumEvents))
602
 
                        Time += state->m_CyclesPerFrame;
603
 
                state->m_pCurrentItem->Event_Time = Time;
604
 
 
605
 
                state->m_pCurrentItem++;
606
 
                state->m_NumEvents++;
607
 
        }
608
 
}
609
 
 
610
 
/* get number of events */
611
 
int spectrum_EventList_NumEvents(running_machine &machine)
612
 
{
613
 
        spectrum_state *state = machine.driver_data<spectrum_state>();
614
 
        return state->m_NumEvents;
615
 
}
616
 
 
617
 
/* get first item in buffer */
618
 
EVENT_LIST_ITEM *spectrum_EventList_GetFirstItem(running_machine &machine)
619
 
{
620
 
        spectrum_state *state = machine.driver_data<spectrum_state>();
621
 
        return (EVENT_LIST_ITEM *)state->m_pEventListBuffer;
622
 
}