1 /*
2  * viciitypes.h - A cycle-exact event-driven MOS6569 (VIC-II) emulation.
3  *
4  * Written by
5  *  Ettore Perazzoli <ettore@comm2000.it>
6  *  Andreas Boose <viceteam@t-online.de>
7  *
8  * This file is part of VICE, the Versatile Commodore Emulator.
9  * See README for copyright notice.
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24  *  02111-1307  USA.
25  *
26  */
27 
28 #ifndef VICE_VICIITYPES_H
29 #define VICE_VICIITYPES_H
30 
31 #include "raster.h"
32 #include "types.h"
33 
34 /* Screen constants.  */
35 #define VICII_SCREEN_XPIX                  320
36 #define VICII_SCREEN_YPIX                  200
37 #define VICII_SCREEN_TEXTCOLS              40
38 #define VICII_SCREEN_TEXTLINES             25
39 #define VICII_SCREEN_CHARHEIGHT            8
40 
41 #define VICII_40COL_START_PIXEL vicii.screen_leftborderwidth
42 #define VICII_40COL_STOP_PIXEL  (vicii.screen_leftborderwidth + VICII_SCREEN_XPIX)
43 /* these are one pixel 'off' on the DTV */
44 #define VICII_38COL_START_PIXEL (vicii.screen_leftborderwidth + 7)
45 #define VICII_38COL_STOP_PIXEL  (vicii.screen_leftborderwidth + 311)
46 
47 #define VICII_NUM_SPRITES      8
48 #define VICII_MAX_SPRITE_WIDTH 56  /* expanded sprite in bug area */
49 #define VICII_NUM_COLORS       16
50 
51 /* Available video modes.  The number is given by
52    ((vicii.regs[0x11] & 0x60) | (vicii.regs[0x16] & 0x10)) >> 4.  */
53 /* Also for DTV:
54    | (vicii.regs[0x3c] & 0x04)<<1 | (vicii.regs[0x3c] & 0x01)<<3
55    + FRED/FRED2, CHUNKY/PIXEL/ILLEGAL_LINEAR separation */
56 enum vicii_video_mode_s {
57     VICII_NORMAL_TEXT_MODE,
58     VICII_MULTICOLOR_TEXT_MODE,
59     VICII_HIRES_BITMAP_MODE,
60     VICII_MULTICOLOR_BITMAP_MODE,
61     VICII_EXTENDED_TEXT_MODE,
62     VICII_ILLEGAL_TEXT_MODE,
63     VICII_ILLEGAL_BITMAP_MODE_1,
64     VICII_ILLEGAL_BITMAP_MODE_2,
65     VICII_IDLE_MODE,           /* Special mode for idle state.  */
66     VICII_NUM_VMODES  /* valid for DTV only */
67 };
68 typedef enum vicii_video_mode_s vicii_video_mode_t;
69 
70 #define VICII_IS_ILLEGAL_MODE(x) ((x) >= VICII_ILLEGAL_TEXT_MODE \
71                                   && (x) <= VICII_ILLEGAL_BITMAP_MODE_2)
72 
73 #define VICII_IS_BITMAP_MODE(x)  ((x) & 0x02)
74 
75 #define VICII_IS_TEXT_MODE(x)    ((x) == VICII_NORMAL_TEXT_MODE \
76                                   || (x) == VICII_MULTICOLOR_TEXT_MODE \
77                                   || (x) == VICII_EXTENDED_TEXT_MODE)
78 
79 /* Temporary list to keep all demos running correctly */
80 #define VICII_MODULO_BUG(x)      ((x) == VICII_ILLEGAL_TEXT_MODE)
81 
82 /* These timings are taken from the ``VIC Article'' by Christian Bauer
83    <bauec002@goofy.zdv.uni-mainz.de>.  Thanks Christian!
84    Note: we measure cycles from 0 to 62, not from 1 to 63 as he does.  */
85 
86 /* Cycle # at which the VIC takes the bus in a bad line (BA goes low).  */
87 #define VICII_FETCH_CYCLE          11
88 
89 /* Delay for the raster line interrupt.  This is not due to the VIC-II, since
90    it triggers the IRQ line at the beginning of the line, but to the 6510
91    that needs at least 2 cycles to detect it.  */
92 #define VICII_RASTER_IRQ_DELAY     2
93 
94 /* Current char being drawn by the raster.  < 0 or >= VICII_SCREEN_TEXTCOLS
95    if outside the visible range.  */
96 #define VICII_RASTER_CHAR(cycle)   ((int)(cycle) - 15)
97 
98 /* Current horizontal position (in pixels) of the raster.  < 0 or >=
99    SCREEN_WIDTH if outside the visible range.  */
100 #define VICII_RASTER_X(cycle)      (((int)(cycle) - 17) * 8 + vicii.screen_leftborderwidth)
101 
102 /* Current vertical position of the raster.  Unlike `rasterline', which is
103    only accurate if a pending drawing event has been served, this is
104    guarranteed to be always correct.  It is a bit slow, though.  */
105 #define VICII_RASTER_Y(clk)        ((unsigned int)((clk) \
106                                                    / vicii.cycles_per_line) \
107                                     % vicii.screen_height)
108 
109 /* Cycle # within the current line.  */
110 #define VICII_RASTER_CYCLE(clk)    ((unsigned int)((clk) \
111                                                    % vicii.cycles_per_line))
112 /* `clk' value for the beginning of the current line.  */
113 #define VICII_LINE_START_CLK(clk)  (((clk) / vicii.cycles_per_line) \
114                                     * vicii.cycles_per_line)
115 
116 /* # of the previous and next raster line.  Handles wrap over.  */
117 #define VICII_PREVIOUS_LINE(line)  (((line) > 0) \
118                                     ? (line) - 1 : vicii.screen_height - 1)
119 #define VICII_NEXT_LINE(line)      (((line) + 1) % vicii.screen_height)
120 
121 /* VIC-II structures.  This is meant to be used by VIC-II modules
122    *exclusively*!  */
123 
124 struct vicii_light_pen_s {
125     int state;
126     int triggered;
127     int x, y, x_extra_bits;
128 };
129 typedef struct vicii_light_pen_s vicii_light_pen_t;
130 
131 enum vicii_fetch_idx_s {
132     VICII_FETCH_MATRIX,
133     VICII_CHECK_SPRITE_DMA,
134     VICII_FETCH_SPRITE
135 };
136 typedef enum vicii_fetch_idx_s vicii_fetch_idx_t;
137 
138 enum vicii_idle_data_location_s {
139     IDLE_NONE,
140     IDLE_3FFF,
141     IDLE_39FF
142 };
143 typedef enum vicii_idle_data_location_s vicii_idle_data_location_t;
144 
145 struct idle_3fff_s {
146     CLOCK cycle;
147     uint8_t value;
148 };
149 typedef struct idle_3fff_s idle_3fff_t;
150 
151 struct alarm_s;
152 struct video_chip_cap_s;
153 
154 struct vicii_s {
155     /* Flag: Are we initialized?  */
156     int initialized;            /* = 0; */
157 
158     /* VIC-II raster.  */
159     raster_t raster;
160 
161     /* VIC-II registers.  */
162     uint8_t regs[0x40];
163 
164     /* Interrupt register.  */
165     int irq_status;             /* = 0; */
166 
167     /* Line for raster compare IRQ.  */
168     unsigned int raster_irq_line;
169 
170     /* Pointer to the base of RAM seen by the VIC-II.  */
171     /* address is base of 64k bank. vbank adds 0/16k/32k/48k to get actual
172        video address */
173     uint8_t *ram_base_phi1;                /* = VIC-II address during Phi1; */
174     uint8_t *ram_base_phi2;                /* = VIC-II address during Phi2; */
175 
176     /* valid VIC-II address bits for Phi1 and Phi2. After masking
177        the address, it is or'd with the offset value to set always-1 bits */
178     uint16_t vaddr_mask_phi1;            /* mask of valid address bits */
179     uint16_t vaddr_mask_phi2;            /* mask of valid address bits */
180     uint16_t vaddr_offset_phi1;          /* mask of address bits always set */
181     uint16_t vaddr_offset_phi2;          /* mask of address bits always set */
182 
183     /* Those two values determine where in the address space the chargen
184        ROM is mapped. Use mask=0x7000, value=0x1000 for the C64. */
185     uint16_t vaddr_chargen_mask_phi1;    /* address bits to comp. for chargen */
186     uint16_t vaddr_chargen_mask_phi2;    /* address bits to comp. for chargen */
187     uint16_t vaddr_chargen_value_phi1;   /* compare value for chargen */
188     uint16_t vaddr_chargen_value_phi2;   /* compare value for chargen */
189 
190     /* Video memory pointers.  Changed for drawing.  */
191     uint8_t *screen_ptr;
192     uint8_t *chargen_ptr;
193 
194     /* Pointer to the bitmap (lower part)  */
195     uint8_t *bitmap_low_ptr;
196 
197     /* Pointer to the bitmap (higher part)  */
198     uint8_t *bitmap_high_ptr;
199 
200     /* Video memory pointers.  Changed immediately.  */
201     uint8_t *screen_base_phi1;
202     uint8_t *screen_base_phi2;
203 
204     /* Offset to the vbuf/cbuf buffer */
205     int buf_offset;
206 
207     /* Screen memory buffers (chars and color).  */
208     uint8_t vbuf[VICII_SCREEN_TEXTCOLS];
209     uint8_t cbuf[VICII_SCREEN_TEXTCOLS];
210 
211     /* If this flag is set, bad lines (DMA's) can happen.  */
212     int allow_bad_lines;
213 
214     /* Sprite-sprite and sprite-background collision registers.  */
215     uint8_t sprite_sprite_collisions;
216     uint8_t sprite_background_collisions;
217 
218     /* Extended background colors (1, 2 and 3).  */
219     int ext_background_color[3];
220 
221     /* Current video mode.  */
222     int video_mode;
223 
224     /* Flag: are we in idle state? */
225     int idle_state;
226 
227     /* Flag: should we force display (i.e. non-idle) state for the following
228        line? */
229     int force_display_state;
230 
231     /* This flag is set if a memory fetch has already happened on the current
232        line.  FIXME: Value of 2?...  */
233     int memory_fetch_done;
234 
235     /* Internal memory pointer (VCBASE).  */
236     int memptr;
237 
238     /* Internal memory counter (VC).  */
239     int mem_counter;
240 
241     /* Value to add to `mem_counter' after the graphics has been painted.  */
242     int mem_counter_inc;
243 
244     /* Flag: is the current line a `bad' line? */
245     int bad_line;
246 
247     /* Flag: Check for raster.ycounter reset already done on this line?
248        (cycle 13) */
249     int ycounter_reset_checked;
250 
251     /* Flag: Does the currently selected video mode force the overscan
252        background color to be black?  (This happens with the hires bitmap and
253        illegal modes.)  */
254     int force_black_overscan_background_color;
255 
256     /* Background color source */
257     int background_color_source;
258 
259     /* Light pen.  */
260     vicii_light_pen_t light_pen;
261 
262     /* Start of the memory bank seen by the VIC-II.  */
263     int vbank_phi1;                     /* = 0; */
264     int vbank_phi2;                     /* = 0; */
265 
266     /* Pointer to the start of the video bank.  */
267     /* BYTE *vbank_ptr; - never used, only set */
268 
269     /* Data to display in idle state.  */
270     int idle_data;
271 
272     /* left border idle data */
273     int idle_data_l[4];
274     /* middle idle data */
275     int idle_data_m[4];
276     /* right border idle data */
277     int idle_data_r[4];
278 
279     /* Where do we currently fetch idle state from?  If `IDLE_NONE', we are
280        not in idle state and thus do not need to update `idle_data'.  */
281     vicii_idle_data_location_t idle_data_location;
282 
283     /* All the VIC-II logging goes here.  */
284     signed int log;
285 
286     /* VIC-II alarms.  */
287     struct alarm_s *raster_fetch_alarm;
288     struct alarm_s *raster_draw_alarm;
289     struct alarm_s *raster_irq_alarm;
290 
291     /* What do we do when the `A_RASTERFETCH' event happens?  */
292     vicii_fetch_idx_t fetch_idx;
293 
294     /* Number of sprite being DMA fetched.  */
295     unsigned int sprite_fetch_idx;
296 
297     /* Mask for sprites being fetched at DMA.  */
298     unsigned int sprite_fetch_msk;
299 
300     /* Clock cycle for the next "raster fetch" alarm.  */
301     CLOCK fetch_clk;
302 
303     /* Clock cycle for the next "raster draw" alarm.  */
304     CLOCK draw_clk;
305 
306     /* Clock value for raster compare IRQ.  */
307     CLOCK raster_irq_clk;
308 
309     /* FIXME: Bad name.  FIXME: Has to be initialized.  */
310     CLOCK last_emulate_line_clk;
311 
312     /* Clock cycle for the next sprite fetch.  */
313     CLOCK sprite_fetch_clk;
314 
315     /* Geometry and timing parameters of the selected VIC-II emulation.  */
316     unsigned int screen_height;
317     int first_displayed_line;
318     int last_displayed_line;
319 
320     unsigned int row_25_start_line;
321     unsigned int row_25_stop_line;
322     unsigned int row_24_start_line;
323     unsigned int row_24_stop_line;
324 
325     int screen_leftborderwidth;
326     int screen_rightborderwidth;
327     int cycles_per_line;
328     int draw_cycle;
329     int sprite_fetch_cycle;
330     int sprite_wrap_x;
331 
332     unsigned int first_dma_line;
333     unsigned int last_dma_line;
334 
335     /* Flag backgroundcolor in hires mode or extended text mode.  */
336     int get_background_from_vbuf;
337 
338     /* Value to store before DMA.  */
339     CLOCK store_clk;
340     uint16_t store_addr;
341     uint8_t store_value;
342 
343     /* Stores to 0x3fff idle location (used for idle sprite fetch).  */
344     unsigned int num_idle_3fff;
345     idle_3fff_t *idle_3fff;
346     unsigned int num_idle_3fff_old;
347     idle_3fff_t *idle_3fff_old;
348 
349     /* Last value read from VICII (used for RMW access).  */
350     uint8_t last_read;
351 
352     /* Video chip capabilities.  */
353     struct video_chip_cap_s *video_chip_cap;
354 
355     unsigned int int_num;
356 
357     /* Pointer to color ram */
358     uint8_t *color_ram_ptr;
359 };
360 typedef struct vicii_s vicii_t;
361 
362 extern vicii_t vicii;
363 
364 /* Private function calls, used by the other VIC-II modules.  */
365 extern void vicii_update_memory_ptrs(unsigned int cycle);
366 extern void vicii_update_video_mode(unsigned int cycle);
367 extern void vicii_raster_draw_alarm_handler(CLOCK offset, void *data);
368 extern void vicii_handle_pending_alarms(int num_write_cycles);
369 extern void vicii_delay_clk(void);
370 extern void vicii_delay_oldclk(CLOCK num);
371 
372 /* Debugging options.  */
373 
374 /* #define VICII_VMODE_DEBUG */
375 /* #define VICII_RASTER_DEBUG */
376 /* #define VICII_REGISTERS_DEBUG */
377 
378 #ifdef VICII_VMODE_DEBUG
379 #define VICII_DEBUG_VMODE(x) log_debug x
380 #else
381 #define VICII_DEBUG_VMODE(x)
382 #endif
383 
384 #ifdef VICII_RASTER_DEBUG
385 #define VICII_DEBUG_RASTER(x) log_debug x
386 #else
387 #define VICII_DEBUG_RASTER(x)
388 #endif
389 
390 #ifdef VICII_REGISTERS_DEBUG
391 #define VICII_DEBUG_REGISTER(x) log_debug x
392 #else
393 #define VICII_DEBUG_REGISTER(x)
394 #endif
395 
396 #endif
397