Previous 199869 Revisions Next

r18716 Friday 26th October, 2012 at 06:39:23 UTC by Miodrag Milanović
-spectrum: cleanup and simplification of video output [David Haywood]
[src/mess/drivers]spec128.c spectrum.c
[src/mess/formats]spec_snqk.c
[src/mess/includes]spectrum.h
[src/mess/video]spectrum.c timex.c

trunk/src/mess/formats/spec_snqk.c
r18715r18716
308308 *******************************************************************/
309309static void spectrum_border_update(running_machine &machine, int data)
310310{
311#if 0
311312    spectrum_EventList_Reset(machine);
312313    spectrum_border_set_last_color(machine, data);
313314    spectrum_border_force_redraw(machine);
315#endif
314316}
315317
316318void spectrum_setup_sp(running_machine &machine, UINT8 *snapdata, UINT32 snapsize)
trunk/src/mess/drivers/spectrum.c
r18715r18716
11411408/03/2002  KS -    #FF port emulation added.
115115                Arkanoid works now, but is not playable due to
116116                completly messed timings.
11725/10/2012  DH - simplified border emulation to be a (manual) partial
118                 update with bitmap
119             Removed legacy fff4 interrupt hack, modern version of
120             MAME can handle this just fine
117121
118122Initialisation values used when determining which model is being emulated:
119123 48K        Spectrum doesn't use either port.
r18715r18716
302306   /* border colour changed? */
303307   if ((Changed & 0x07)!=0)
304308   {
305      /* yes - send event */
306      spectrum_EventList_AddItemOffset(machine(), 0x0fe, data & 0x07, machine().device<cpu_device>("maincpu")->attotime_to_cycles(machine().primary_screen->scan_period() * machine().primary_screen->vpos()));
309      spectrum_UpdateBorderBitmap(machine());
307310   }
308311
309312   if ((Changed & (1<<4))!=0)
r18715r18716
321324   m_port_fe_data = data;
322325}
323326
324DIRECT_UPDATE_MEMBER(spectrum_state::spectrum_direct)
325{
326    /* Hack for correct handling 0xffff interrupt vector */
327    if (address == 0x0001)
328        if (machine().device("maincpu")->safe_pcbase()==0xffff)
329        {
330            machine().device("maincpu")->state().set_state_int(Z80_PC, 0xfff4);
331            return 0xfff4;
332        }
333    return address;
334}
335327
328
336329/* KT: more accurate keyboard reading */
337330/* DJR: Spectrum+ keys added */
338331READ8_MEMBER(spectrum_state::spectrum_port_fe_r)
r18715r18716
633626
634627MACHINE_RESET_MEMBER(spectrum_state,spectrum)
635628{
636   address_space &space = machine().device("maincpu")->memory().space(AS_PROGRAM);
637
638   space.set_direct_update_handler(direct_update_delegate(FUNC(spectrum_state::spectrum_direct), this));
639
640629   m_port_7ffd_data = -1;
641630   m_port_1ffd_data = -1;
642631}
r18715r18716
715704
716705    /* video hardware */
717706   MCFG_SCREEN_ADD("screen", RASTER)
718   MCFG_SCREEN_REFRESH_RATE(50.08)
719   MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */
720   MCFG_SCREEN_SIZE(SPEC_SCREEN_WIDTH, SPEC_SCREEN_HEIGHT)
721   MCFG_SCREEN_VISIBLE_AREA(0, SPEC_SCREEN_WIDTH-1, 0, SPEC_SCREEN_HEIGHT-1)
707
708   MCFG_SCREEN_RAW_PARAMS(X1 / 2, 448, 0, 352,  312, 0, 296)
709
722710   MCFG_SCREEN_UPDATE_DRIVER(spectrum_state, screen_update_spectrum)
723711   MCFG_SCREEN_VBLANK_DRIVER(spectrum_state, screen_eof_spectrum)
724712
trunk/src/mess/drivers/spec128.c
r18715r18716
246246ADDRESS_MAP_END
247247
248248static ADDRESS_MAP_START (spectrum_128_mem, AS_PROGRAM, 8, spectrum_state )
249   AM_RANGE( 0x0000, 0x3fff) AM_RAMBANK("bank1")
249   AM_RANGE( 0x0000, 0x3fff) AM_ROMBANK("bank1") // don't use RAMBANK here otherwise programs can erase the ROM(!)
250250   AM_RANGE( 0x4000, 0x7fff) AM_RAMBANK("bank2")
251251   AM_RANGE( 0x8000, 0xbfff) AM_RAMBANK("bank3")
252252   AM_RANGE( 0xc000, 0xffff) AM_RAMBANK("bank4")
r18715r18716
294294
295295MACHINE_CONFIG_DERIVED( spectrum_128, spectrum )
296296
297   MCFG_CPU_MODIFY("maincpu")
297   MCFG_DEVICE_REMOVE("maincpu")
298
299   MCFG_CPU_ADD("maincpu", Z80, X1_128_SINCLAIR / 5)
298300   MCFG_CPU_PROGRAM_MAP(spectrum_128_mem)
299301   MCFG_CPU_IO_MAP(spectrum_128_io)
302   MCFG_CPU_VBLANK_INT_DRIVER("screen", spectrum_state,  spec_interrupt)
303   MCFG_QUANTUM_TIME(attotime::from_hz(60))
300304
305
301306   MCFG_MACHINE_RESET_OVERRIDE(spectrum_state, spectrum_128 )
302307
303308   /* video hardware */
304309   MCFG_SCREEN_MODIFY("screen")
305310   MCFG_PALETTE_LENGTH(16)
306311   MCFG_PALETTE_INIT_OVERRIDE(spectrum_state, spectrum )
307   MCFG_SCREEN_REFRESH_RATE(50.021)
312   MCFG_SCREEN_RAW_PARAMS(X1_128_SINCLAIR / 2.5f, 456, 0, 352,  311, 0, 296)
313
308314   MCFG_VIDEO_START_OVERRIDE(spectrum_state, spectrum_128 )
309315   MCFG_GFXDECODE(spec128)
310316
trunk/src/mess/includes/spectrum.h
r18715r18716
1212
1313/* Spectrum crystals */
1414
15#define X1 XTAL_14MHz      // Main clock
15#define X1 XTAL_14MHz      // Main clock (48k Spectrum)
16#define X1_128_AMSTRAD  35469000 // Main clock (Amstrad 128K model, +2A?)
17#define X1_128_SINCLAIR 17734475 // Main clock (Sinclair 128K model)
18
1619#define X2 XTAL_4_433619MHz // PAL color subcarrier
1720
1821/* Spectrum screen size in pixels */
r18715r18716
8184   int m_frame_invert_count;
8285   int m_frame_number;    /* Used for handling FLASH 1 */
8386   int m_flash_invert;
84   UINT8 m_retrace_cycles;
8587   optional_shared_ptr<UINT8> m_video_ram;
8688   UINT8 *m_screen_location;
8789
8890   int m_ROMSelection;
8991
90   /* Last border colour output in the previous frame */
91   int m_CurrBorderColor;
92   int m_LastDisplayedBorderColor; /* Negative value indicates redraw */
9392
9493   EVENT_LIST_ITEM *m_pCurrentItem;
9594   int m_NumEvents;
r18715r18716
106105   DECLARE_READ8_MEMBER(spectrum_port_7f_r);
107106   DECLARE_READ8_MEMBER(spectrum_port_df_r);
108107   DECLARE_READ8_MEMBER(spectrum_port_ula_r);
109   DECLARE_DIRECT_UPDATE_MEMBER(spectrum_direct);
110108   DECLARE_DRIVER_INIT(spectrum);
111109   DECLARE_DRIVER_INIT(plus2);
112110   DECLARE_DRIVER_INIT(plus3);
r18715r18716
124122   UINT32 screen_update_ts2068(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
125123   void screen_eof_spectrum(screen_device &screen, bool state);
126124   INTERRUPT_GEN_MEMBER(spec_interrupt);
125
126   unsigned int m_previous_border_x, m_previous_border_y;
127   bitmap_ind16 m_border_bitmap;
127128};
128129
129130
r18715r18716
152153
153154/*----------- defined in video/spectrum.c -----------*/
154155
156void spectrum_UpdateBorderBitmap(running_machine &machine);
155157
156void spectrum_border_force_redraw (running_machine &machine);
157void spectrum_border_set_last_color (running_machine &machine, int NewColor);
158void spectrum_border_draw(running_machine &machine, bitmap_ind16 &bitmap, int full_refresh,
159                int TopBorderLines, int ScreenLines, int BottomBorderLines,
160                int LeftBorderPixels, int ScreenPixels, int RightBorderPixels,
161                int LeftBorderCycles, int ScreenCycles, int RightBorderCycles,
162                int HorizontalRetraceCycles, int VRetraceTime, int EventID);
163158
164void spectrum_EventList_Initialise(running_machine &machine, int NumEntries);
165void spectrum_EventList_Reset(running_machine &machine);
166void spectrum_EventList_SetOffsetStartTime(running_machine &machine, int StartTime);
167void spectrum_EventList_AddItemOffset(running_machine &machine, int ID, int Data,int Time);
168int spectrum_EventList_NumEvents(running_machine &machine);
169EVENT_LIST_ITEM *spectrum_EventList_GetFirstItem(running_machine &machine);
170159
171160#endif /* __SPECTRUM_H__ */
trunk/src/mess/video/timex.c
r18715r18716
182182{
183183   /* for now TS2068 will do a full-refresh */
184184   int count;
185   int full_refresh = 1;
185   
186   if (m_border_bitmap.valid())
187      copyscrollbitmap(bitmap, m_border_bitmap, 0, 0, 0, 0, cliprect);
186188
187189   if ((m_port_ff_data & 7) == 6)
188190   {
r18715r18716
210212         ts2068_lores_scanline(machine(),bitmap, count, TS2068_TOP_BORDER, 0);
211213   }
212214
213   spectrum_border_draw(machine(), bitmap, full_refresh,
214      TS2068_TOP_BORDER, SPEC_DISPLAY_YSIZE, TS2068_BOTTOM_BORDER,
215      TS2068_LEFT_BORDER, TS2068_DISPLAY_XSIZE, TS2068_RIGHT_BORDER,
216      SPEC_LEFT_BORDER_CYCLES, SPEC_DISPLAY_XSIZE_CYCLES,
217      SPEC_RIGHT_BORDER_CYCLES, SPEC_RETRACE_CYCLES, 200, 0xfe);
218215   return 0;
219216}
220217
r18715r18716
222219{
223220   /* for now TS2068 will do a full-refresh */
224221   int count;
225   int full_refresh = 1;
226222
223   if (m_border_bitmap.valid())
224      copyscrollbitmap(bitmap, m_border_bitmap, 0, 0, 0, 0, cliprect);
225
227226   if ((m_port_ff_data & 7) == 6)
228227   {
229228      /* 64 Column mode */
r18715r18716
250249         ts2068_lores_scanline(machine(),bitmap, count, SPEC_TOP_BORDER, 0);
251250   }
252251
253   spectrum_border_draw(machine(), bitmap, full_refresh,
254      SPEC_TOP_BORDER, SPEC_DISPLAY_YSIZE, SPEC_BOTTOM_BORDER,
255      TS2068_LEFT_BORDER, TS2068_DISPLAY_XSIZE, TS2068_RIGHT_BORDER,
256      SPEC_LEFT_BORDER_CYCLES, SPEC_DISPLAY_XSIZE_CYCLES,
257      SPEC_RIGHT_BORDER_CYCLES, SPEC_RETRACE_CYCLES, 200, 0xfe);
258252   return 0;
259253}
trunk/src/mess/video/spectrum.c
r18715r18716
2121***************************************************************************/
2222VIDEO_START_MEMBER(spectrum_state,spectrum)
2323{
24   m_LastDisplayedBorderColor = -1;
2524   m_frame_invert_count = 25;
2625   m_frame_number = 0;
2726   m_flash_invert = 0;
2827
29   spectrum_EventList_Initialise(machine(), 30000);
28   m_previous_border_x = 0; m_previous_border_y = 0;
29   machine().primary_screen->register_screen_bitmap(m_border_bitmap);
3030
31   m_retrace_cycles = SPEC_RETRACE_CYCLES;
32
3331   m_screen_location = m_video_ram;
3432}
3533
3634VIDEO_START_MEMBER(spectrum_state,spectrum_128)
3735{
38   m_LastDisplayedBorderColor = -1;
3936   m_frame_invert_count = 25;
4037   m_frame_number = 0;
4138   m_flash_invert = 0;
4239
43   spectrum_EventList_Initialise(machine(), 30000);
44
45   m_retrace_cycles = SPEC128_RETRACE_CYCLES;
40   m_previous_border_x = 0; m_previous_border_y = 0;
41   machine().primary_screen->register_screen_bitmap(m_border_bitmap);
4642}
4743
4844
r18715r18716
6258   // rising edge
6359   if (state)
6460   {
65      EVENT_LIST_ITEM *pItem;
66      int NumItems;
67
68      m_frame_number++;
69      if (m_frame_number >= m_frame_invert_count)
70      {
71         m_frame_number = 0;
72         m_flash_invert = !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(screen.scan_period() * screen.vpos()) );
84         logerror ("Event log reset in callback fn.\n");
85      }
61      spectrum_UpdateBorderBitmap(machine());
8662   }
8763}
8864
r18715r18716
11894
11995UINT32 spectrum_state::screen_update_spectrum(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
12096{
97   // note, don't update borders in here, this can time travel w/regards to other timers and may end up giving you
98   // screen positions earlier than the last write handler gave you
99
121100   /* for now do a full-refresh */
122101   int x, y, b, scrx, scry;
123102   unsigned short ink, pap;
124103   unsigned char *attr, *scr;
125      int full_refresh = 1;
104   //   int full_refresh = 1;
126105
106   if (m_border_bitmap.valid())
107      copyscrollbitmap(bitmap, m_border_bitmap, 0, 0, 0, 0, cliprect);
108
127109   scr=m_screen_location;
128110
129111   for (y=0; y<192; y++)
r18715r18716
159141      }
160142   }
161143
162   spectrum_border_draw(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, m_retrace_cycles, 200, 0xfe);
167144   return 0;
168145}
169146
r18715r18716
192169   palette_set_colors(machine(), 0, spectrum_palette, ARRAY_LENGTH(spectrum_palette));
193170}
194171
195/***************************************************************************
196        Border engine:
197172
198        Functions for drawing multi-coloured screen borders using the
199        Event List processing.
173/* The code below is just a per-pixel 'partial update' for the border */
200174
201Changes:
202
20328/05/2000 DJR - Initial implementation.
20408/06/2000 DJR - Now only uses events with the correct ID value.
20528/06/2000 DJR - draw_border now uses full_refresh flag.
206
207***************************************************************************/
208
209/* Force the border to be redrawn on the next frame */
210void spectrum_border_force_redraw (running_machine &machine)
175INLINE void spectrum_GetNextPos(running_machine &machine, unsigned int &x, unsigned int &y)
211176{
212177   spectrum_state *state = machine.driver_data<spectrum_state>();
213   state->m_LastDisplayedBorderColor = -1;
214}
178   int width = state->m_border_bitmap.width();
179   int height = state->m_border_bitmap.height();
215180
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. */
218void 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}
181   x += 1;
223182
224void spectrum_border_draw(running_machine &machine, bitmap_ind16 &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++)
183   if (x>width)
254184   {
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   }
185      x = 0;
186      y += 1;
257187
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 */
188      if (y>height)
189      {
190         y = 0;
191      }
272192   }
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.set(0, TotalScreenWidth-1, 0, TopBorderLines-1);
281      bitmap.fill(machine.pens[state->m_CurrBorderColor], r);
193}
282194
283      r.set(0, LeftBorderPixels-1, TopBorderLines, TopBorderLines+ScreenLines-1);
284      bitmap.fill(machine.pens[state->m_CurrBorderColor], r);
285195
286      r.setx(LeftBorderPixels+ScreenPixels, TotalScreenWidth-1);
287      bitmap.fill(machine.pens[state->m_CurrBorderColor], r);
196void spectrum_UpdateBorderBitmap(running_machine &machine)
197{
198   spectrum_state *state = machine.driver_data<spectrum_state>();
199   unsigned int x = machine.primary_screen->hpos();
200   unsigned int y = machine.primary_screen->vpos();
201   int width = state->m_border_bitmap.width();
202   int height = state->m_border_bitmap.height();
288203
289      r.set(0, TotalScreenWidth-1, TopBorderLines+ScreenLines, TotalScreenHeight-1);
290      bitmap.fill(machine.pens[state->m_CurrBorderColor], r);
291204
292//          logerror ("Setting border colour to %d (Last = %d, Full Refresh = %d)\n", state->m_CurrBorderColor, state->m_LastDisplayedBorderColor, full_refresh);
293      state->m_LastDisplayedBorderColor = state->m_CurrBorderColor;
294   }
295   else
205   if (state->m_border_bitmap.valid())
296206   {
297      /* Multiple border colours */
207      int colour = state->m_port_fe_data & 0x07;
298208
299      /* Process entries before first displayed line */
300      while ((CurrItem < NumItems) && (pItem[CurrItem].Event_Time <= VRetraceTime))
301      {
302         state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
303         do {
304            CurrItem++;
305         } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
306      }
209      //printf("update border from %d,%d to %d,%d\n", state->m_previous_border_x, state->m_previous_border_y, x, y);
307210
308      /* Draw top border */
309      CyclesSoFar = VRetraceTime;
310      for (ScrY = 0; ScrY < TopBorderLines; ScrY++)
211      do
311212      {
312         r.min_x = 0;
313         r.min_y = r.max_y = ScrY;
314         if ((CurrItem >= NumItems) || (pItem[CurrItem].Event_Time >= (CyclesSoFar+DisplayCyclesPerLine)))
213         if (state->m_previous_border_y < height)
315214         {
316            /* Single colour on line */
317            r.max_x = TotalScreenWidth-1;
318            bitmap.fill(machine.pens[state->m_CurrBorderColor], r);
319         }
320         else
321         {
322            /* Multiple colours on a line */
323            ScrX = (int)(pItem[CurrItem].Event_Time - CyclesSoFar) * (float)TotalScreenWidth / (float)DisplayCyclesPerLine;
324            r.max_x = ScrX-1;
325            bitmap.fill(machine.pens[state->m_CurrBorderColor], r);
326            state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
327            do {
328               CurrItem++;
329            } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
215            UINT16* bm = &state->m_border_bitmap.pix16(state->m_previous_border_y);
330216
331            while ((CurrItem < NumItems) && (pItem[CurrItem].Event_Time < (CyclesSoFar+DisplayCyclesPerLine)))
332            {
333               NextScrX = (int)(pItem[CurrItem].Event_Time - CyclesSoFar) * (float)TotalScreenWidth / (float)DisplayCyclesPerLine;
334               r.setx(ScrX, NextScrX-1);
335               bitmap.fill(machine.pens[state->m_CurrBorderColor], r);
336               ScrX = NextScrX;
337               state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
338               do {
339                  CurrItem++;
340               } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
341            }
342            r.setx(ScrX, TotalScreenWidth-1);
343            bitmap.fill(machine.pens[state->m_CurrBorderColor], r);
217            if (state->m_previous_border_x < width)
218               bm[state->m_previous_border_x] = colour;   
344219         }
345220
346         /* Process colour changes during horizontal retrace */
347         CyclesSoFar+= CyclesPerLine;
348         while ((CurrItem < NumItems) && (pItem[CurrItem].Event_Time <= CyclesSoFar))
349         {
350            state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
351            do {
352               CurrItem++;
353            } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
354         }
221         spectrum_GetNextPos(machine, state->m_previous_border_x, state->m_previous_border_y);
355222      }
223      while (!((state->m_previous_border_x == x) && (state->m_previous_border_y == y)));
356224
357      /* Draw left and right borders next to screen lines */
358      for (ScrY = TopBorderLines; ScrY < (TopBorderLines+ScreenLines); ScrY++)
359      {
360         /* Draw left hand border */
361         r.min_x = 0;
362         r.min_y = r.max_y = ScrY;
363
364         if ((CurrItem >= NumItems) || (pItem[CurrItem].Event_Time >= (CyclesSoFar+LeftBorderCycles)))
365         {
366            /* Single colour */
367            r.max_x = LeftBorderPixels-1;
368            bitmap.fill(machine.pens[state->m_CurrBorderColor], r);
369         }
370         else
371         {
372            /* Multiple colours */
373            ScrX = (int)(pItem[CurrItem].Event_Time - CyclesSoFar) * (float)LeftBorderPixels / (float)LeftBorderCycles;
374            r.max_x = ScrX-1;
375            bitmap.fill(machine.pens[state->m_CurrBorderColor], r);
376            state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
377            do {
378               CurrItem++;
379            } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
380
381            while ((CurrItem < NumItems) && (pItem[CurrItem].Event_Time < (CyclesSoFar+LeftBorderCycles)))
382            {
383               NextScrX = (int)(pItem[CurrItem].Event_Time - CyclesSoFar) * (float)LeftBorderPixels / (float)LeftBorderCycles;
384               r.setx(ScrX, NextScrX-1);
385               bitmap.fill(machine.pens[state->m_CurrBorderColor], r);
386               ScrX = NextScrX;
387               state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
388               do {
389                  CurrItem++;
390               } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
391            }
392            r.setx(ScrX, LeftBorderPixels-1);
393            bitmap.fill(machine.pens[state->m_CurrBorderColor], r);
394         }
395
396         /* Process colour changes during screen draw */
397         while ((CurrItem < NumItems) && (pItem[CurrItem].Event_Time <= (CyclesSoFar+LeftBorderCycles+ScreenCycles)))
398         {
399            state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
400            do {
401               CurrItem++;
402            } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
403         }
404
405         /* Draw right hand border */
406         r.min_x = LeftBorderPixels+ScreenPixels;
407         if ((CurrItem >= NumItems) || (pItem[CurrItem].Event_Time >= (CyclesSoFar+DisplayCyclesPerLine)))
408         {
409            /* Single colour */
410            r.max_x = TotalScreenWidth-1;
411            bitmap.fill(machine.pens[state->m_CurrBorderColor], r);
412         }
413         else
414         {
415            /* Multiple colours */
416            ScrX = LeftBorderPixels + ScreenPixels + (int)(pItem[CurrItem].Event_Time - CyclesSoFar) * (float)RightBorderPixels / (float)RightBorderCycles;
417            r.max_x = ScrX-1;
418            bitmap.fill(machine.pens[state->m_CurrBorderColor], r);
419            state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
420            do {
421               CurrItem++;
422            } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
423
424            while ((CurrItem < NumItems) && (pItem[CurrItem].Event_Time < (CyclesSoFar+DisplayCyclesPerLine)))
425            {
426               NextScrX = LeftBorderPixels + ScreenPixels + (int)(pItem[CurrItem].Event_Time - CyclesSoFar) * (float)RightBorderPixels / (float)RightBorderCycles;
427               r.setx(ScrX, NextScrX-1);
428               bitmap.fill(machine.pens[state->m_CurrBorderColor], r);
429               ScrX = NextScrX;
430               state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
431               do {
432                  CurrItem++;
433               } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
434            }
435            r.setx(ScrX, TotalScreenWidth-1);
436            bitmap.fill(machine.pens[state->m_CurrBorderColor], r);
437         }
438
439         /* Process colour changes during horizontal retrace */
440         CyclesSoFar+= CyclesPerLine;
441         while ((CurrItem < NumItems) && (pItem[CurrItem].Event_Time <= CyclesSoFar))
442         {
443            state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
444            do {
445               CurrItem++;
446            } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
447         }
448      }
449
450      /* Draw bottom border */
451      for (ScrY = TopBorderLines+ScreenLines; ScrY < TotalScreenHeight; ScrY++)
452      {
453         r.min_x = 0;
454         r.min_y = r.max_y = ScrY;
455         if ((CurrItem >= NumItems) || (pItem[CurrItem].Event_Time >= (CyclesSoFar+DisplayCyclesPerLine)))
456         {
457            /* Single colour on line */
458            r.max_x = TotalScreenWidth-1;
459            bitmap.fill(machine.pens[state->m_CurrBorderColor], r);
460         }
461         else
462         {
463            /* Multiple colours on a line */
464            ScrX = (int)(pItem[CurrItem].Event_Time - CyclesSoFar) * (float)TotalScreenWidth / (float)DisplayCyclesPerLine;
465            r.max_x = ScrX-1;
466            bitmap.fill(machine.pens[state->m_CurrBorderColor], r);
467            state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
468            do {
469               CurrItem++;
470            } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
471
472            while ((CurrItem < NumItems) && (pItem[CurrItem].Event_Time < (CyclesSoFar+DisplayCyclesPerLine)))
473            {
474               NextScrX = (int)(pItem[CurrItem].Event_Time - CyclesSoFar) * (float)TotalScreenWidth / (float)DisplayCyclesPerLine;
475               r.setx(ScrX, NextScrX-1);
476               bitmap.fill(machine.pens[state->m_CurrBorderColor], r);
477               ScrX = NextScrX;
478               state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
479               do {
480                  CurrItem++;
481               } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
482            }
483            r.setx(ScrX, TotalScreenWidth-1);
484            bitmap.fill(machine.pens[state->m_CurrBorderColor], r);
485         }
486
487         /* Process colour changes during horizontal retrace */
488         CyclesSoFar+= CyclesPerLine;
489         while ((CurrItem < NumItems) && (pItem[CurrItem].Event_Time <= CyclesSoFar))
490         {
491            state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
492            do {
493               CurrItem++;
494            } while ((CurrItem < NumItems) && (pItem[CurrItem].Event_ID != EventID));
495         }
496      }
497
498      /* Process colour changes after last displayed line */
499      while (CurrItem < NumItems)
500      {
501         if (pItem[CurrItem].Event_ID == EventID)
502            state->m_CurrBorderColor = pItem[CurrItem].Event_Data;
503         CurrItem++;
504      }
505
506      /* Set value to ensure redraw on next frame */
507      state->m_LastDisplayedBorderColor = -1;
508
509//          logerror ("Multi coloured border drawn (last colour = %d)\n", CurrBorderColor);
510225   }
511
512   /* Assume all other routines have processed their data from the list */
513   spectrum_EventList_Reset(machine);
514   spectrum_EventList_SetOffsetStartTime ( machine, machine.firstcpu->attotime_to_cycles(machine.primary_screen->scan_period() * machine.primary_screen->vpos()));
515}
516
517
518/* initialise */
519
520/* if the CPU is the controlling factor, the size of the buffer
521can be setup as:
522
523Number_of_CPU_Cycles_In_A_Frame/Minimum_Number_Of_Cycles_Per_Instruction */
524void spectrum_EventList_Initialise(running_machine &machine, int NumEntries)
525{
526   spectrum_state *state = machine.driver_data<spectrum_state>();
527   state->m_pEventListBuffer = auto_alloc_array(machine, char, NumEntries);
528   state->m_TotalEvents = NumEntries;
529   state->m_CyclesPerFrame = 0;
530   spectrum_EventList_Reset(machine);
531}
532
533/* reset the change list */
534void spectrum_EventList_Reset(running_machine &machine)
535{
536   spectrum_state *state = machine.driver_data<spectrum_state>();
537   state->m_NumEvents = 0;
538   state->m_pCurrentItem = (EVENT_LIST_ITEM *)state->m_pEventListBuffer;
539}
540
541
542#ifdef UNUSED_FUNCTION
543/* add an event to the buffer */
544void EventList_AddItem(running_machine &machine, int ID, int Data, int Time)
545{
546   spectrum_state *state = machine.driver_data<spectrum_state>();
547   if (state->m_NumEvents < state->m_TotalEvents)
226   else
548227   {
549      /* setup item only if there is space in the buffer */
550      state->m_pCurrentItem->Event_ID = ID;
551      state->m_pCurrentItem->Event_Data = Data;
552      state->m_pCurrentItem->Event_Time = Time;
553
554      state->m_pCurrentItem++;
555      state->m_NumEvents++;
228      // no border bitmap allocated? fatalerror?
556229   }
557}
558#endif
559230
560/* set the start time for use with EventList_AddItemOffset usually this will
561   be cpu_getcurrentcycles() at the time that the screen is being refreshed */
562void spectrum_EventList_SetOffsetStartTime(running_machine &machine, int StartTime)
563{
564   spectrum_state *state = machine.driver_data<spectrum_state>();
565   state->m_LastFrameStartTime = StartTime;
566}
567231
568/* add an event to the buffer with a time index offset from a specified time */
569void spectrum_EventList_AddItemOffset(running_machine &machine, int ID, int Data, int Time)
570{
571   spectrum_state *state = machine.driver_data<spectrum_state>();
572
573   if (!state->m_CyclesPerFrame)
574      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);
575
576   if (state->m_NumEvents < state->m_TotalEvents)
577   {
578      /* setup item only if there is space in the buffer */
579      state->m_pCurrentItem->Event_ID = ID;
580      state->m_pCurrentItem->Event_Data = Data;
581
582      Time -= state->m_LastFrameStartTime;
583      if ((Time < 0) || ((Time == 0) && state->m_NumEvents))
584         Time += state->m_CyclesPerFrame;
585      state->m_pCurrentItem->Event_Time = Time;
586
587      state->m_pCurrentItem++;
588      state->m_NumEvents++;
589   }
590}
591
592/* get number of events */
593int spectrum_EventList_NumEvents(running_machine &machine)
594{
595   spectrum_state *state = machine.driver_data<spectrum_state>();
596   return state->m_NumEvents;
597}
598
599/* get first item in buffer */
600EVENT_LIST_ITEM *spectrum_EventList_GetFirstItem(running_machine &machine)
601{
602   spectrum_state *state = machine.driver_data<spectrum_state>();
603   return (EVENT_LIST_ITEM *)state->m_pEventListBuffer;
604}
232}
No newline at end of file

Previous 199869 Revisions Next


© 1997-2024 The MAME Team