trunk/src/emu/sound/mos6560.c
r17678 | r17679 | |
59 | 59 | #include "emu.h" |
60 | 60 | #include "sound/mos6560.h" |
61 | 61 | |
62 | | /*************************************************************************** |
63 | | TYPE DEFINITIONS |
64 | | ***************************************************************************/ |
65 | 62 | |
66 | | typedef struct _mos6560_state mos6560_state; |
67 | | struct _mos6560_state |
68 | | { |
69 | | mos6560_type type; |
70 | | |
71 | | screen_device *screen; |
72 | | |
73 | | UINT8 reg[16]; |
74 | | |
75 | | bitmap_ind16 *bitmap; |
76 | | |
77 | | int rasterline, lastline; |
78 | | double lightpenreadtime; |
79 | | |
80 | | int charheight, matrix8x16, inverted; |
81 | | int chars_x, chars_y; |
82 | | int xsize, ysize, xpos, ypos; |
83 | | int chargenaddr, videoaddr; |
84 | | |
85 | | /* values in videoformat */ |
86 | | UINT16 backgroundcolor, framecolor, helpercolor; |
87 | | |
88 | | /* arrays for bit to color conversion without condition checking */ |
89 | | UINT16 mono[2], monoinverted[2], multi[4], multiinverted[4]; |
90 | | |
91 | | /* video chip settings */ |
92 | | int total_xsize, total_ysize, total_lines, total_vretracerate; |
93 | | |
94 | | /* DMA */ |
95 | | devcb_resolved_read8 dma_read; |
96 | | devcb_resolved_read8 dma_read_color; |
97 | | UINT8 last_data; |
98 | | |
99 | | /* lightpen */ |
100 | | devcb_resolved_read8 lightpen_button_cb; |
101 | | devcb_resolved_read8 lightpen_x_cb; |
102 | | devcb_resolved_read8 lightpen_y_cb; |
103 | | |
104 | | /* paddles */ |
105 | | devcb_resolved_read8 paddle_cb[2]; |
106 | | |
107 | | /* sound part */ |
108 | | int tone1pos, tone2pos, tone3pos, |
109 | | tonesize, tone1samples, tone2samples, tone3samples, |
110 | | noisesize, /* number of samples */ |
111 | | noisepos, /* pos of tone */ |
112 | | noisesamples; /* count of samples to give out per tone */ |
113 | | |
114 | | sound_stream *channel; |
115 | | INT16 *tone; |
116 | | INT8 *noise; |
117 | | }; |
118 | | |
119 | 63 | /***************************************************************************** |
120 | | INLINE FUNCTIONS |
121 | | *****************************************************************************/ |
122 | | |
123 | | INLINE mos6560_state *get_safe_token( device_t *device ) |
124 | | { |
125 | | assert(device != NULL); |
126 | | assert(device->type() == MOS656X); |
127 | | |
128 | | return (mos6560_state *)downcast<mos6560_device *>(device)->token(); |
129 | | } |
130 | | |
131 | | INLINE const mos6560_interface *get_interface( device_t *device ) |
132 | | { |
133 | | assert(device != NULL); |
134 | | assert((device->type() == MOS656X)); |
135 | | |
136 | | return (const mos6560_interface *) device->static_config(); |
137 | | } |
138 | | |
139 | | /***************************************************************************** |
140 | 64 | PARAMETERS |
141 | 65 | *****************************************************************************/ |
142 | 66 | |
r17678 | r17679 | |
146 | 70 | if(VERBOSE_LEVEL >= N) \ |
147 | 71 | { \ |
148 | 72 | if( M ) \ |
149 | | logerror("%11.6f: %-24s", device->machine().time().as_double(), (char*) M ); \ |
| 73 | logerror("%11.6f: %-24s", machine().time().as_double(), (char*) M ); \ |
150 | 74 | logerror A; \ |
151 | 75 | } \ |
152 | 76 | } while (0) |
r17678 | r17679 | |
154 | 78 | |
155 | 79 | /* 2008-05 FP: lightpen code needs to read input port from vc20.c */ |
156 | 80 | |
157 | | #define LIGHTPEN_BUTTON ((!mos6560->lightpen_button_cb.isnull()) ? mos6560->lightpen_button_cb(0) : 0) |
158 | | #define LIGHTPEN_X_VALUE ((!mos6560->lightpen_x_cb.isnull()) ? mos6560->lightpen_x_cb(0) : 0) |
159 | | #define LIGHTPEN_Y_VALUE ((!mos6560->lightpen_y_cb.isnull()) ? mos6560->lightpen_y_cb(0) : 0) |
| 81 | #define LIGHTPEN_BUTTON ((!m_lightpen_button_cb.isnull()) ? m_lightpen_button_cb(0) : 0) |
| 82 | #define LIGHTPEN_X_VALUE ((!m_lightpen_x_cb.isnull()) ? m_lightpen_x_cb(0) : 0) |
| 83 | #define LIGHTPEN_Y_VALUE ((!m_lightpen_y_cb.isnull()) ? m_lightpen_y_cb(0) : 0) |
160 | 84 | |
161 | 85 | /* lightpen delivers values from internal counters |
162 | 86 | * they do not start with the visual area or frame area */ |
r17678 | r17679 | |
164 | 88 | #define MOS6560_Y_BEGIN -6 /* first 6 lines after retrace not for lightpen! */ |
165 | 89 | #define MOS6561_X_BEGIN 38 |
166 | 90 | #define MOS6561_Y_BEGIN -6 |
167 | | #define MOS656X_X_BEGIN ((mos6560->type == MOS6561) ? MOS6561_X_BEGIN : MOS6560_X_BEGIN) |
168 | | #define MOS656X_Y_BEGIN ((mos6560->type == MOS6561) ? MOS6561_Y_BEGIN : MOS6560_Y_BEGIN) |
| 91 | #define MOS656X_X_BEGIN ((m_variant == TYPE_6561) ? MOS6561_X_BEGIN : MOS6560_X_BEGIN) |
| 92 | #define MOS656X_Y_BEGIN ((m_variant == TYPE_6561) ? MOS6561_Y_BEGIN : MOS6560_Y_BEGIN) |
169 | 93 | |
170 | | #define MOS656X_MAME_XPOS ((mos6560->type == MOS6561) ? MOS6561_MAME_XPOS : MOS6560_MAME_XPOS) |
171 | | #define MOS656X_MAME_YPOS ((mos6560->type == MOS6561) ? MOS6561_MAME_YPOS : MOS6560_MAME_YPOS) |
| 94 | #define MOS656X_MAME_XPOS ((m_variant == TYPE_6561) ? MOS6561_MAME_XPOS : MOS6560_MAME_XPOS) |
| 95 | #define MOS656X_MAME_YPOS ((m_variant == TYPE_6561) ? MOS6561_MAME_YPOS : MOS6560_MAME_YPOS) |
172 | 96 | |
173 | 97 | /* lightpen behaviour in pal or mono multicolor not tested */ |
174 | 98 | #define MOS656X_X_VALUE ((LIGHTPEN_X_VALUE + MOS656X_X_BEGIN + MOS656X_MAME_XPOS)/2) |
175 | 99 | #define MOS656X_Y_VALUE ((LIGHTPEN_Y_VALUE + MOS656X_Y_BEGIN + MOS656X_MAME_YPOS)/2) |
176 | 100 | |
177 | | #define MOS656X_VRETRACERATE ((mos6560->type == MOS6561) ? MOS6561_VRETRACERATE : MOS6560_VRETRACERATE) |
| 101 | #define MOS656X_VRETRACERATE ((m_variant == TYPE_6561) ? MOS6561_VRETRACERATE : MOS6560_VRETRACERATE) |
178 | 102 | |
179 | 103 | /* ntsc 1 - 8 */ |
180 | 104 | /* pal 5 - 19 */ |
181 | | #define XPOS (((int)mos6560->reg[0] & 0x7f) * 4) |
182 | | #define YPOS ((int)mos6560->reg[1] * 2) |
| 105 | #define XPOS (((int)m_reg[0] & 0x7f) * 4) |
| 106 | #define YPOS ((int)m_reg[1] * 2) |
183 | 107 | |
184 | 108 | /* ntsc values >= 31 behave like 31 */ |
185 | 109 | /* pal value >= 32 behave like 32 */ |
186 | | #define CHARS_X ((int)mos6560->reg[2] & 0x7f) |
187 | | #define CHARS_Y (((int)mos6560->reg[3] & 0x7e) >> 1) |
| 110 | #define CHARS_X ((int)m_reg[2] & 0x7f) |
| 111 | #define CHARS_Y (((int)m_reg[3] & 0x7e) >> 1) |
188 | 112 | |
189 | 113 | /* colorram and backgroundcolor are changed */ |
190 | | #define INVERTED (!(mos6560->reg[0x0f] & 8)) |
| 114 | #define INVERTED (!(m_reg[0x0f] & 8)) |
191 | 115 | |
192 | | #define CHARGENADDR (((int)mos6560->reg[5] & 0x0f) << 10) |
193 | | #define VIDEOADDR ((((int)mos6560->reg[5] & 0xf0) << (10 - 4)) | (((int)mos6560->reg[2] & 0x80) << (9-7))) |
| 116 | #define CHARGENADDR (((int)m_reg[5] & 0x0f) << 10) |
| 117 | #define VIDEOADDR ((((int)m_reg[5] & 0xf0) << (10 - 4)) | (((int)m_reg[2] & 0x80) << (9-7))) |
194 | 118 | #define VIDEORAMSIZE (YSIZE * XSIZE) |
195 | 119 | #define CHARGENSIZE (256 * HEIGHTPIXEL) |
196 | 120 | |
197 | | #define HELPERCOLOR (mos6560->reg[0x0e] >> 4) |
198 | | #define BACKGROUNDCOLOR (mos6560->reg[0x0f] >> 4) |
199 | | #define FRAMECOLOR (mos6560->reg[0x0f] & 0x07) |
| 121 | #define HELPERCOLOR (m_reg[0x0e] >> 4) |
| 122 | #define BACKGROUNDCOLOR (m_reg[0x0f] >> 4) |
| 123 | #define FRAMECOLOR (m_reg[0x0f] & 0x07) |
200 | 124 | |
201 | 125 | |
202 | 126 | static const rgb_t PALETTE[] = |
r17678 | r17679 | |
223 | 147 | MAKE_RGB(0xff, 0xff, 0x00) |
224 | 148 | }; |
225 | 149 | |
226 | | PALETTE_INIT( mos6560 ) |
| 150 | |
| 151 | //************************************************************************** |
| 152 | // INLINE HELPERS |
| 153 | //************************************************************************** |
| 154 | |
| 155 | //------------------------------------------------- |
| 156 | // initialize_palette - |
| 157 | //------------------------------------------------- |
| 158 | |
| 159 | inline void mos6560_device::initialize_palette() |
227 | 160 | { |
228 | | palette_set_colors(machine, 0, PALETTE, ARRAY_LENGTH(PALETTE)); |
| 161 | palette_set_colors(machine(), 0, PALETTE, ARRAY_LENGTH(PALETTE)); |
229 | 162 | } |
230 | 163 | |
231 | | |
232 | 164 | /***************************************************************************** |
233 | 165 | IMPLEMENTATION |
234 | 166 | *****************************************************************************/ |
235 | 167 | |
236 | | static void mos6560_soundport_w( device_t *device, int offset, int data ); |
| 168 | inline UINT8 mos6560_device::read_videoram(offs_t offset) |
| 169 | { |
| 170 | m_last_data = space(AS_0)->read_byte(offset & 0x3fff); |
| 171 | |
| 172 | return m_last_data; |
| 173 | } |
237 | 174 | |
| 175 | inline UINT8 mos6560_device::read_colorram(offs_t offset) |
| 176 | { |
| 177 | return space(AS_1)->read_byte(offset & 0x3ff); |
| 178 | } |
| 179 | |
238 | 180 | /*------------------------------------------------- |
239 | | mos6560_draw_character |
| 181 | draw_character |
240 | 182 | -------------------------------------------------*/ |
241 | 183 | |
242 | | static void mos6560_draw_character( device_t *device, int ybegin, int yend, int ch, int yoff, int xoff, UINT16 *color ) |
| 184 | void mos6560_device::draw_character( int ybegin, int yend, int ch, int yoff, int xoff, UINT16 *color ) |
243 | 185 | { |
244 | | mos6560_state *mos6560 = get_safe_token(device); |
245 | 186 | int y, code; |
246 | 187 | |
247 | 188 | for (y = ybegin; y <= yend; y++) |
248 | 189 | { |
249 | | code = mos6560->dma_read((mos6560->chargenaddr + ch * mos6560->charheight + y) & 0x3fff); |
250 | | mos6560->last_data = code; |
251 | | mos6560->bitmap->pix16(y + yoff, xoff + 0) = color[code >> 7]; |
252 | | mos6560->bitmap->pix16(y + yoff, xoff + 1) = color[(code >> 6) & 1]; |
253 | | mos6560->bitmap->pix16(y + yoff, xoff + 2) = color[(code >> 5) & 1]; |
254 | | mos6560->bitmap->pix16(y + yoff, xoff + 3) = color[(code >> 4) & 1]; |
255 | | mos6560->bitmap->pix16(y + yoff, xoff + 4) = color[(code >> 3) & 1]; |
256 | | mos6560->bitmap->pix16(y + yoff, xoff + 5) = color[(code >> 2) & 1]; |
257 | | mos6560->bitmap->pix16(y + yoff, xoff + 6) = color[(code >> 1) & 1]; |
258 | | mos6560->bitmap->pix16(y + yoff, xoff + 7) = color[code & 1]; |
| 190 | code = read_videoram((m_chargenaddr + ch * m_charheight + y) & 0x3fff); |
| 191 | |
| 192 | m_bitmap.pix16(y + yoff, xoff + 0) = color[code >> 7]; |
| 193 | m_bitmap.pix16(y + yoff, xoff + 1) = color[(code >> 6) & 1]; |
| 194 | m_bitmap.pix16(y + yoff, xoff + 2) = color[(code >> 5) & 1]; |
| 195 | m_bitmap.pix16(y + yoff, xoff + 3) = color[(code >> 4) & 1]; |
| 196 | m_bitmap.pix16(y + yoff, xoff + 4) = color[(code >> 3) & 1]; |
| 197 | m_bitmap.pix16(y + yoff, xoff + 5) = color[(code >> 2) & 1]; |
| 198 | m_bitmap.pix16(y + yoff, xoff + 6) = color[(code >> 1) & 1]; |
| 199 | m_bitmap.pix16(y + yoff, xoff + 7) = color[code & 1]; |
259 | 200 | } |
260 | 201 | } |
261 | 202 | |
262 | 203 | |
263 | 204 | /*------------------------------------------------- |
264 | | mos6560_draw_character_multi |
| 205 | draw_character_multi |
265 | 206 | -------------------------------------------------*/ |
266 | 207 | |
267 | | static void mos6560_draw_character_multi( device_t *device, int ybegin, int yend, int ch, int yoff, int xoff, UINT16 *color ) |
| 208 | void mos6560_device::draw_character_multi( int ybegin, int yend, int ch, int yoff, int xoff, UINT16 *color ) |
268 | 209 | { |
269 | | mos6560_state *mos6560 = get_safe_token(device); |
270 | 210 | int y, code; |
271 | 211 | |
272 | 212 | for (y = ybegin; y <= yend; y++) |
273 | 213 | { |
274 | | code = mos6560->dma_read((mos6560->chargenaddr + ch * mos6560->charheight + y) & 0x3fff); |
275 | | mos6560->last_data = code; |
276 | | mos6560->bitmap->pix16(y + yoff, xoff + 0) = |
277 | | mos6560->bitmap->pix16(y + yoff, xoff + 1) = color[code >> 6]; |
278 | | mos6560->bitmap->pix16(y + yoff, xoff + 2) = |
279 | | mos6560->bitmap->pix16(y + yoff, xoff + 3) = color[(code >> 4) & 3]; |
280 | | mos6560->bitmap->pix16(y + yoff, xoff + 4) = |
281 | | mos6560->bitmap->pix16(y + yoff, xoff + 5) = color[(code >> 2) & 3]; |
282 | | mos6560->bitmap->pix16(y + yoff, xoff + 6) = |
283 | | mos6560->bitmap->pix16(y + yoff, xoff + 7) = color[code & 3]; |
| 214 | code = read_videoram((m_chargenaddr + ch * m_charheight + y) & 0x3fff); |
| 215 | |
| 216 | m_bitmap.pix16(y + yoff, xoff + 0) = |
| 217 | m_bitmap.pix16(y + yoff, xoff + 1) = color[code >> 6]; |
| 218 | m_bitmap.pix16(y + yoff, xoff + 2) = |
| 219 | m_bitmap.pix16(y + yoff, xoff + 3) = color[(code >> 4) & 3]; |
| 220 | m_bitmap.pix16(y + yoff, xoff + 4) = |
| 221 | m_bitmap.pix16(y + yoff, xoff + 5) = color[(code >> 2) & 3]; |
| 222 | m_bitmap.pix16(y + yoff, xoff + 6) = |
| 223 | m_bitmap.pix16(y + yoff, xoff + 7) = color[code & 3]; |
284 | 224 | } |
285 | 225 | } |
286 | 226 | |
287 | 227 | |
288 | 228 | /*------------------------------------------------- |
289 | | mos6560_drawlines - draw a certain numer of lines |
| 229 | drawlines - draw a certain numer of lines |
290 | 230 | -------------------------------------------------*/ |
291 | 231 | |
292 | | static void mos6560_drawlines( device_t *device, int first, int last ) |
| 232 | void mos6560_device::drawlines( int first, int last ) |
293 | 233 | { |
294 | | mos6560_state *mos6560 = get_safe_token(device); |
295 | 234 | int line, vline; |
296 | 235 | int offs, yoff, xoff, ybegin, yend, i, j; |
297 | 236 | int attr, ch; |
298 | 237 | |
299 | | mos6560->lastline = last; |
| 238 | m_lastline = last; |
300 | 239 | if (first >= last) |
301 | 240 | return; |
302 | 241 | |
303 | | for (line = first; (line < mos6560->ypos) && (line < last); line++) |
| 242 | for (line = first; (line < m_ypos) && (line < last); line++) |
304 | 243 | { |
305 | | for (j = 0; j < mos6560->total_xsize; j++) |
306 | | mos6560->bitmap->pix16(line, j) = mos6560->framecolor; |
| 244 | for (j = 0; j < m_total_xsize; j++) |
| 245 | m_bitmap.pix16(line, j) = m_framecolor; |
307 | 246 | } |
308 | 247 | |
309 | | for (vline = line - mos6560->ypos; (line < last) && (line < mos6560->ypos + mos6560->ysize);) |
| 248 | for (vline = line - m_ypos; (line < last) && (line < m_ypos + m_ysize);) |
310 | 249 | { |
311 | | if (mos6560->matrix8x16) |
| 250 | if (m_matrix8x16) |
312 | 251 | { |
313 | | offs = (vline >> 4) * mos6560->chars_x; |
314 | | yoff = (vline & ~0xf) + mos6560->ypos; |
| 252 | offs = (vline >> 4) * m_chars_x; |
| 253 | yoff = (vline & ~0xf) + m_ypos; |
315 | 254 | ybegin = vline & 0xf; |
316 | | yend = (vline + 0xf < last - mos6560->ypos) ? 0xf : ((last - line) & 0xf) + ybegin; |
| 255 | yend = (vline + 0xf < last - m_ypos) ? 0xf : ((last - line) & 0xf) + ybegin; |
317 | 256 | } |
318 | 257 | else |
319 | 258 | { |
320 | | offs = (vline >> 3) * mos6560->chars_x; |
321 | | yoff = (vline & ~7) + mos6560->ypos; |
| 259 | offs = (vline >> 3) * m_chars_x; |
| 260 | yoff = (vline & ~7) + m_ypos; |
322 | 261 | ybegin = vline & 7; |
323 | | yend = (vline + 7 < last - mos6560->ypos) ? 7 : ((last - line) & 7) + ybegin; |
| 262 | yend = (vline + 7 < last - m_ypos) ? 7 : ((last - line) & 7) + ybegin; |
324 | 263 | } |
325 | 264 | |
326 | | if (mos6560->xpos > 0) |
| 265 | if (m_xpos > 0) |
327 | 266 | { |
328 | 267 | for (i = ybegin; i <= yend; i++) |
329 | | for (j = 0; j < mos6560->xpos; j++) |
330 | | mos6560->bitmap->pix16(yoff + i, j) = mos6560->framecolor; |
| 268 | for (j = 0; j < m_xpos; j++) |
| 269 | m_bitmap.pix16(yoff + i, j) = m_framecolor; |
331 | 270 | } |
332 | 271 | |
333 | | for (xoff = mos6560->xpos; (xoff < mos6560->xpos + mos6560->xsize) && (xoff < mos6560->total_xsize); xoff += 8, offs++) |
| 272 | for (xoff = m_xpos; (xoff < m_xpos + m_xsize) && (xoff < m_total_xsize); xoff += 8, offs++) |
334 | 273 | { |
335 | | ch = mos6560->dma_read((mos6560->videoaddr + offs) & 0x3fff); |
336 | | mos6560->last_data = ch; |
337 | | attr = (mos6560->dma_read_color((mos6560->videoaddr + offs) & 0x3fff)) & 0xf; |
| 274 | ch = read_videoram((m_videoaddr + offs) & 0x3fff); |
338 | 275 | |
339 | | if (mos6560->type == MOS6560_ATTACKUFO) |
| 276 | attr = (read_colorram((m_videoaddr + offs) & 0x3fff)) & 0xf; |
| 277 | |
| 278 | if (m_variant == TYPE_ATTACK_UFO) |
340 | 279 | { |
341 | 280 | /* the mos6560 variant used in attckufo only has only one draw mode */ |
342 | | mos6560->mono[1] = attr; |
343 | | mos6560_draw_character(device, ybegin, yend, ch, yoff, xoff, mos6560->mono); |
| 281 | m_mono[1] = attr; |
| 282 | draw_character(ybegin, yend, ch, yoff, xoff, m_mono); |
344 | 283 | } |
345 | | else if (mos6560->inverted) |
| 284 | else if (m_inverted) |
346 | 285 | { |
347 | 286 | if (attr & 8) |
348 | 287 | { |
349 | | mos6560->multiinverted[0] = attr & 7; |
350 | | mos6560_draw_character_multi(device, ybegin, yend, ch, yoff, xoff, mos6560->multiinverted); |
| 288 | m_multiinverted[0] = attr & 7; |
| 289 | draw_character_multi(ybegin, yend, ch, yoff, xoff, m_multiinverted); |
351 | 290 | } |
352 | 291 | else |
353 | 292 | { |
354 | | mos6560->monoinverted[0] = attr; |
355 | | mos6560_draw_character(device, ybegin, yend, ch, yoff, xoff, mos6560->monoinverted); |
| 293 | m_monoinverted[0] = attr; |
| 294 | draw_character(ybegin, yend, ch, yoff, xoff, m_monoinverted); |
356 | 295 | } |
357 | 296 | } |
358 | 297 | else |
359 | 298 | { |
360 | 299 | if (attr & 8) |
361 | 300 | { |
362 | | mos6560->multi[2] = attr & 7; |
363 | | mos6560_draw_character_multi(device, ybegin, yend, ch, yoff, xoff, mos6560->multi); |
| 301 | m_multi[2] = attr & 7; |
| 302 | draw_character_multi(ybegin, yend, ch, yoff, xoff, m_multi); |
364 | 303 | } |
365 | 304 | else |
366 | 305 | { |
367 | | mos6560->mono[1] = attr; |
368 | | mos6560_draw_character(device, ybegin, yend, ch, yoff, xoff, mos6560->mono); |
| 306 | m_mono[1] = attr; |
| 307 | draw_character(ybegin, yend, ch, yoff, xoff, m_mono); |
369 | 308 | } |
370 | 309 | } |
371 | 310 | } |
372 | 311 | |
373 | | if (xoff < mos6560->total_xsize) |
| 312 | if (xoff < m_total_xsize) |
374 | 313 | { |
375 | 314 | for (i = ybegin; i <= yend; i++) |
376 | | for (j = xoff; j < mos6560->total_xsize; j++) |
377 | | mos6560->bitmap->pix16(yoff + i, j) = mos6560->framecolor; |
| 315 | for (j = xoff; j < m_total_xsize; j++) |
| 316 | m_bitmap.pix16(yoff + i, j) = m_framecolor; |
378 | 317 | } |
379 | 318 | |
380 | | if (mos6560->matrix8x16) |
| 319 | if (m_matrix8x16) |
381 | 320 | { |
382 | 321 | vline = (vline + 16) & ~0xf; |
383 | | line = vline + mos6560->ypos; |
| 322 | line = vline + m_ypos; |
384 | 323 | } |
385 | 324 | else |
386 | 325 | { |
387 | 326 | vline = (vline + 8) & ~7; |
388 | | line = vline + mos6560->ypos; |
| 327 | line = vline + m_ypos; |
389 | 328 | } |
390 | 329 | } |
391 | 330 | |
392 | 331 | for (; line < last; line++) |
393 | | for (j = 0; j < mos6560->total_xsize; j++) |
394 | | mos6560->bitmap->pix16(line, j) = mos6560->framecolor; |
| 332 | for (j = 0; j < m_total_xsize; j++) |
| 333 | m_bitmap.pix16(line, j) = m_framecolor; |
395 | 334 | } |
396 | 335 | |
397 | 336 | |
r17678 | r17679 | |
399 | 338 | mos6560_port_w - write to regs |
400 | 339 | -------------------------------------------------*/ |
401 | 340 | |
402 | | WRITE8_DEVICE_HANDLER( mos6560_port_w ) |
| 341 | WRITE8_MEMBER( mos6560_device::write ) |
403 | 342 | { |
404 | | mos6560_state *mos6560 = get_safe_token(device); |
405 | | |
406 | 343 | DBG_LOG(1, "mos6560_port_w", ("%.4x:%.2x\n", offset, data)); |
407 | 344 | |
408 | 345 | switch (offset) |
r17678 | r17679 | |
412 | 349 | case 0xc: |
413 | 350 | case 0xd: |
414 | 351 | case 0xe: |
415 | | mos6560_soundport_w(device, offset, data); |
| 352 | soundport_w(offset, data); |
416 | 353 | break; |
417 | 354 | } |
418 | 355 | |
419 | | if (mos6560->reg[offset] != data) |
| 356 | if (m_reg[offset] != data) |
420 | 357 | { |
421 | 358 | switch (offset) |
422 | 359 | { |
r17678 | r17679 | |
427 | 364 | case 5: |
428 | 365 | case 0xe: |
429 | 366 | case 0xf: |
430 | | mos6560_drawlines(device, mos6560->lastline, mos6560->rasterline); |
| 367 | drawlines(m_lastline, m_rasterline); |
431 | 368 | break; |
432 | 369 | } |
433 | | mos6560->reg[offset] = data; |
| 370 | m_reg[offset] = data; |
434 | 371 | |
435 | 372 | switch (offset) |
436 | 373 | { |
437 | 374 | case 0: |
438 | | if ((mos6560->type != MOS6560_ATTACKUFO)) |
439 | | mos6560->xpos = XPOS; |
| 375 | if ((m_variant != TYPE_ATTACK_UFO)) |
| 376 | m_xpos = XPOS; |
440 | 377 | break; |
441 | 378 | case 1: |
442 | | if ((mos6560->type != MOS6560_ATTACKUFO)) |
443 | | mos6560->ypos = YPOS; |
| 379 | if ((m_variant != TYPE_ATTACK_UFO)) |
| 380 | m_ypos = YPOS; |
444 | 381 | break; |
445 | 382 | case 2: |
446 | 383 | /* ntsc values >= 31 behave like 31 */ |
447 | 384 | /* pal value >= 32 behave like 32 */ |
448 | | mos6560->chars_x = CHARS_X; |
449 | | mos6560->videoaddr = VIDEOADDR; |
450 | | mos6560->xsize = CHARS_X * 8; |
| 385 | m_chars_x = CHARS_X; |
| 386 | m_videoaddr = VIDEOADDR; |
| 387 | m_xsize = CHARS_X * 8; |
451 | 388 | break; |
452 | 389 | case 3: |
453 | | if ((mos6560->type != MOS6560_ATTACKUFO)) |
| 390 | if ((m_variant != TYPE_ATTACK_UFO)) |
454 | 391 | { |
455 | | mos6560->matrix8x16 = data & 0x01; |
456 | | mos6560->charheight = mos6560->matrix8x16 ? 16 : 8; |
| 392 | m_matrix8x16 = data & 0x01; |
| 393 | m_charheight = m_matrix8x16 ? 16 : 8; |
457 | 394 | } |
458 | | mos6560->chars_y = CHARS_Y; |
459 | | mos6560->ysize = CHARS_Y * mos6560->charheight; |
| 395 | m_chars_y = CHARS_Y; |
| 396 | m_ysize = CHARS_Y * m_charheight; |
460 | 397 | break; |
461 | 398 | case 5: |
462 | | mos6560->chargenaddr = CHARGENADDR; |
463 | | mos6560->videoaddr = VIDEOADDR; |
| 399 | m_chargenaddr = CHARGENADDR; |
| 400 | m_videoaddr = VIDEOADDR; |
464 | 401 | break; |
465 | 402 | case 0xe: |
466 | | mos6560->multi[3] = mos6560->multiinverted[3] = mos6560->helpercolor = HELPERCOLOR; |
| 403 | m_multi[3] = m_multiinverted[3] = m_helpercolor = HELPERCOLOR; |
467 | 404 | break; |
468 | 405 | case 0xf: |
469 | | if ((mos6560->type != MOS6560_ATTACKUFO)) |
470 | | mos6560->inverted = INVERTED; |
471 | | mos6560->multi[1] = mos6560->multiinverted[1] = mos6560->framecolor = FRAMECOLOR; |
472 | | mos6560->mono[0] = mos6560->monoinverted[1] = mos6560->multi[0] = mos6560->multiinverted[2] = mos6560->backgroundcolor = BACKGROUNDCOLOR; |
| 406 | if ((m_variant != TYPE_ATTACK_UFO)) |
| 407 | m_inverted = INVERTED; |
| 408 | m_multi[1] = m_multiinverted[1] = m_framecolor = FRAMECOLOR; |
| 409 | m_mono[0] = m_monoinverted[1] = m_multi[0] = m_multiinverted[2] = m_backgroundcolor = BACKGROUNDCOLOR; |
473 | 410 | break; |
474 | 411 | } |
475 | 412 | } |
r17678 | r17679 | |
479 | 416 | mos6560_port_r - read from regs |
480 | 417 | -------------------------------------------------*/ |
481 | 418 | |
482 | | READ8_DEVICE_HANDLER( mos6560_port_r ) |
| 419 | READ8_MEMBER( mos6560_device::read ) |
483 | 420 | { |
484 | | mos6560_state *mos6560 = get_safe_token(device); |
485 | 421 | int val; |
486 | 422 | |
487 | 423 | switch (offset) |
488 | 424 | { |
489 | 425 | case 3: |
490 | | val = ((mos6560->rasterline & 1) << 7) | (mos6560->reg[offset] & 0x7f); |
| 426 | val = ((m_rasterline & 1) << 7) | (m_reg[offset] & 0x7f); |
491 | 427 | break; |
492 | 428 | case 4: /*rasterline */ |
493 | | mos6560_drawlines(device, mos6560->lastline, mos6560->rasterline); |
494 | | val = (mos6560->rasterline / 2) & 0xff; |
| 429 | drawlines(m_lastline, m_rasterline); |
| 430 | val = (m_rasterline / 2) & 0xff; |
495 | 431 | break; |
496 | 432 | case 6: /*lightpen horizontal */ |
497 | 433 | case 7: /*lightpen vertical */ |
498 | | if (LIGHTPEN_BUTTON && ((device->machine().time().as_double() - mos6560->lightpenreadtime) * MOS656X_VRETRACERATE >= 1)) |
| 434 | #ifdef UNUSED_FUNCTION |
| 435 | if (LIGHTPEN_BUTTON && ((machine().time().as_double() - m_lightpenreadtime) * MOS656X_VRETRACERATE >= 1)) |
499 | 436 | { |
500 | 437 | /* only 1 update each frame */ |
501 | 438 | /* and diode must recognize light */ |
502 | 439 | if (1) |
503 | 440 | { |
504 | | mos6560->reg[6] = MOS656X_X_VALUE; |
505 | | mos6560->reg[7] = MOS656X_Y_VALUE; |
| 441 | m_reg[6] = MOS656X_X_VALUE; |
| 442 | m_reg[7] = MOS656X_Y_VALUE; |
506 | 443 | } |
507 | | mos6560->lightpenreadtime = device->machine().time().as_double(); |
| 444 | m_lightpenreadtime = machine().time().as_double(); |
508 | 445 | } |
509 | | val = mos6560->reg[offset]; |
| 446 | #endif |
| 447 | val = m_reg[offset]; |
510 | 448 | break; |
511 | 449 | case 8: /* poti 1 */ |
512 | 450 | case 9: /* poti 2 */ |
513 | | val = (!mos6560->paddle_cb->isnull()) ? mos6560->paddle_cb[offset - 8](0) : mos6560->reg[offset]; |
| 451 | val = (!m_paddle_cb->isnull()) ? m_paddle_cb[offset - 8](0) : m_reg[offset]; |
514 | 452 | break; |
515 | 453 | default: |
516 | | val = mos6560->reg[offset]; |
| 454 | val = m_reg[offset]; |
517 | 455 | break; |
518 | 456 | } |
519 | 457 | DBG_LOG(3, "mos6560_port_r", ("%.4x:%.2x\n", offset, val)); |
520 | 458 | return val; |
521 | 459 | } |
522 | 460 | |
523 | | UINT8 mos6560_device::bus_r() |
| 461 | WRITE_LINE_MEMBER( mos6560_device::lp_w ) |
524 | 462 | { |
525 | | mos6560_state *mos6560 = get_safe_token(this); |
| 463 | // TODO |
| 464 | } |
526 | 465 | |
527 | | return mos6560->last_data; |
| 466 | UINT8 mos6560_device::bus_r() |
| 467 | { |
| 468 | return m_last_data; |
528 | 469 | } |
529 | 470 | |
530 | 471 | /*------------------------------------------------- |
531 | 472 | mos6560_raster_interrupt_gen |
532 | 473 | -------------------------------------------------*/ |
533 | 474 | |
534 | | void mos6560_raster_interrupt_gen( device_t *device ) |
| 475 | void mos6560_device::raster_interrupt_gen() |
535 | 476 | { |
536 | | mos6560_state *mos6560 = get_safe_token(device); |
537 | | |
538 | | mos6560->rasterline++; |
539 | | if (mos6560->rasterline >= mos6560->total_lines) |
| 477 | m_rasterline++; |
| 478 | if (m_rasterline >= m_total_lines) |
540 | 479 | { |
541 | | mos6560->rasterline = 0; |
542 | | mos6560_drawlines(device, mos6560->lastline, mos6560->total_lines); |
543 | | mos6560->lastline = 0; |
| 480 | m_rasterline = 0; |
| 481 | drawlines(m_lastline, m_total_lines); |
| 482 | m_lastline = 0; |
544 | 483 | } |
545 | 484 | } |
546 | 485 | |
r17678 | r17679 | |
550 | 489 | main screen bitmap |
551 | 490 | -------------------------------------------------*/ |
552 | 491 | |
553 | | UINT32 mos6560_video_update( device_t *device, bitmap_ind16 &bitmap, const rectangle &cliprect ) |
| 492 | UINT32 mos6560_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) |
554 | 493 | { |
555 | | mos6560_state *mos6560 = get_safe_token(device); |
| 494 | copybitmap(bitmap, m_bitmap, 0, 0, 0, 0, cliprect); |
556 | 495 | |
557 | | copybitmap(bitmap, *mos6560->bitmap, 0, 0, 0, 0, cliprect); |
558 | 496 | return 0; |
559 | 497 | } |
560 | 498 | |
561 | | UINT32 mos6560_device::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) |
562 | | { |
563 | | return mos6560_video_update(this, bitmap, cliprect); |
564 | | } |
565 | | |
566 | 499 | /***************************************************************************** |
567 | 500 | SOUND IMPLEMENTATION |
568 | 501 | *****************************************************************************/ |
r17678 | r17679 | |
591 | 524 | |
592 | 525 | #define NOISE_BUFFER_SIZE_SEC 5 |
593 | 526 | |
594 | | #define TONE1_ON (mos6560->reg[0x0a] & 0x80) |
595 | | #define TONE2_ON (mos6560->reg[0x0b] & 0x80) |
596 | | #define TONE3_ON (mos6560->reg[0x0c] & 0x80) |
597 | | #define NOISE_ON (mos6560->reg[0x0d] & 0x80) |
598 | | #define VOLUME (mos6560->reg[0x0e] & 0x0f) |
| 527 | #define TONE1_ON (m_reg[0x0a] & 0x80) |
| 528 | #define TONE2_ON (m_reg[0x0b] & 0x80) |
| 529 | #define TONE3_ON (m_reg[0x0c] & 0x80) |
| 530 | #define NOISE_ON (m_reg[0x0d] & 0x80) |
| 531 | #define VOLUME (m_reg[0x0e] & 0x0f) |
599 | 532 | |
600 | | #define MOS656X_CLOCK ((mos6560->type == MOS6561) ? MOS6561_CLOCK : MOS6560_CLOCK) |
| 533 | #define TONE_FREQUENCY_MIN (clock()/256/128) |
601 | 534 | |
602 | | #define TONE_FREQUENCY_MIN (MOS656X_CLOCK/256/128) |
| 535 | #define TONE1_VALUE (8 * (128 - ((m_reg[0x0a] + 1) & 0x7f))) |
| 536 | #define TONE1_FREQUENCY (clock()/32/TONE1_VALUE) |
603 | 537 | |
604 | | #define TONE1_VALUE (8 * (128 - ((mos6560->reg[0x0a] + 1) & 0x7f))) |
605 | | #define TONE1_FREQUENCY (MOS656X_CLOCK/32/TONE1_VALUE) |
| 538 | #define TONE2_VALUE (4 * (128 - ((m_reg[0x0b] + 1) & 0x7f))) |
| 539 | #define TONE2_FREQUENCY (clock()/32/TONE2_VALUE) |
606 | 540 | |
607 | | #define TONE2_VALUE (4 * (128 - ((mos6560->reg[0x0b] + 1) & 0x7f))) |
608 | | #define TONE2_FREQUENCY (MOS656X_CLOCK/32/TONE2_VALUE) |
| 541 | #define TONE3_VALUE (2 * (128 - ((m_reg[0x0c] + 1) & 0x7f))) |
| 542 | #define TONE3_FREQUENCY (clock()/32/TONE3_VALUE) |
609 | 543 | |
610 | | #define TONE3_VALUE (2 * (128 - ((mos6560->reg[0x0c] + 1) & 0x7f))) |
611 | | #define TONE3_FREQUENCY (MOS656X_CLOCK/32/TONE3_VALUE) |
| 544 | #define NOISE_VALUE (32 * (128 - ((m_reg[0x0d] + 1) & 0x7f))) |
| 545 | #define NOISE_FREQUENCY (clock()/NOISE_VALUE) |
612 | 546 | |
613 | | #define NOISE_VALUE (32 * (128 - ((mos6560->reg[0x0d] + 1) & 0x7f))) |
614 | | #define NOISE_FREQUENCY (MOS656X_CLOCK/NOISE_VALUE) |
| 547 | #define NOISE_FREQUENCY_MAX (clock()/32/1) |
615 | 548 | |
616 | | #define NOISE_FREQUENCY_MAX (MOS656X_CLOCK/32/1) |
617 | 549 | |
618 | | |
619 | 550 | /*------------------------------------------------- |
620 | 551 | mos6560_soundport_w - write to regs |
621 | 552 | -------------------------------------------------*/ |
622 | 553 | |
623 | | static void mos6560_soundport_w( device_t *device, int offset, int data ) |
| 554 | void mos6560_device::soundport_w( int offset, int data ) |
624 | 555 | { |
625 | | mos6560_state *mos6560 = get_safe_token(device); |
626 | | int old = mos6560->reg[offset]; |
627 | | mos6560->channel->update(); |
| 556 | int old = m_reg[offset]; |
| 557 | m_channel->update(); |
628 | 558 | |
629 | 559 | switch (offset) |
630 | 560 | { |
631 | 561 | case 0x0a: |
632 | | mos6560->reg[offset] = data; |
| 562 | m_reg[offset] = data; |
633 | 563 | if (!(old & 0x80) && TONE1_ON) |
634 | 564 | { |
635 | | mos6560->tone1pos = 0; |
636 | | mos6560->tone1samples = device->machine().sample_rate() / TONE1_FREQUENCY; |
637 | | if (!mos6560->tone1samples == 0) |
638 | | mos6560->tone1samples = 1; |
| 565 | m_tone1pos = 0; |
| 566 | m_tone1samples = machine().sample_rate() / TONE1_FREQUENCY; |
| 567 | if (!m_tone1samples == 0) |
| 568 | m_tone1samples = 1; |
639 | 569 | } |
640 | 570 | DBG_LOG(1, "mos6560", ("tone1 %.2x %d\n", data, TONE1_FREQUENCY)); |
641 | 571 | break; |
642 | 572 | case 0x0b: |
643 | | mos6560->reg[offset] = data; |
| 573 | m_reg[offset] = data; |
644 | 574 | if (!(old & 0x80) && TONE2_ON) |
645 | 575 | { |
646 | | mos6560->tone2pos = 0; |
647 | | mos6560->tone2samples = device->machine().sample_rate() / TONE2_FREQUENCY; |
648 | | if (mos6560->tone2samples == 0) |
649 | | mos6560->tone2samples = 1; |
| 576 | m_tone2pos = 0; |
| 577 | m_tone2samples = machine().sample_rate() / TONE2_FREQUENCY; |
| 578 | if (m_tone2samples == 0) |
| 579 | m_tone2samples = 1; |
650 | 580 | } |
651 | 581 | DBG_LOG(1, "mos6560", ("tone2 %.2x %d\n", data, TONE2_FREQUENCY)); |
652 | 582 | break; |
653 | 583 | case 0x0c: |
654 | | mos6560->reg[offset] = data; |
| 584 | m_reg[offset] = data; |
655 | 585 | if (!(old & 0x80) && TONE3_ON) |
656 | 586 | { |
657 | | mos6560->tone3pos = 0; |
658 | | mos6560->tone3samples = device->machine().sample_rate() / TONE3_FREQUENCY; |
659 | | if (mos6560->tone3samples == 0) |
660 | | mos6560->tone3samples = 1; |
| 587 | m_tone3pos = 0; |
| 588 | m_tone3samples = machine().sample_rate() / TONE3_FREQUENCY; |
| 589 | if (m_tone3samples == 0) |
| 590 | m_tone3samples = 1; |
661 | 591 | } |
662 | 592 | DBG_LOG(1, "mos6560", ("tone3 %.2x %d\n", data, TONE3_FREQUENCY)); |
663 | 593 | break; |
664 | 594 | case 0x0d: |
665 | | mos6560->reg[offset] = data; |
| 595 | m_reg[offset] = data; |
666 | 596 | if (NOISE_ON) |
667 | 597 | { |
668 | | mos6560->noisesamples = (int) ((double) NOISE_FREQUENCY_MAX * device->machine().sample_rate() |
| 598 | m_noisesamples = (int) ((double) NOISE_FREQUENCY_MAX * machine().sample_rate() |
669 | 599 | * NOISE_BUFFER_SIZE_SEC / NOISE_FREQUENCY); |
670 | 600 | DBG_LOG (1, "mos6560", ("noise %.2x %d sample:%d\n", |
671 | | data, NOISE_FREQUENCY, mos6560->noisesamples)); |
672 | | if ((double) mos6560->noisepos / mos6560->noisesamples >= 1.0) |
| 601 | data, NOISE_FREQUENCY, m_noisesamples)); |
| 602 | if ((double) m_noisepos / m_noisesamples >= 1.0) |
673 | 603 | { |
674 | | mos6560->noisepos = 0; |
| 604 | m_noisepos = 0; |
675 | 605 | } |
676 | 606 | } |
677 | 607 | else |
678 | 608 | { |
679 | | mos6560->noisepos = 0; |
| 609 | m_noisepos = 0; |
680 | 610 | } |
681 | 611 | break; |
682 | 612 | case 0x0e: |
683 | | mos6560->reg[offset] = (old & ~0x0f) | (data & 0x0f); |
| 613 | m_reg[offset] = (old & ~0x0f) | (data & 0x0f); |
684 | 614 | DBG_LOG (3, "mos6560", ("volume %d\n", data & 0x0f)); |
685 | 615 | break; |
686 | 616 | } |
687 | 617 | } |
688 | 618 | |
689 | 619 | |
690 | | /*------------------------------------------------- |
691 | | mos6560_update - update audio stream |
692 | | -------------------------------------------------*/ |
693 | | |
694 | | static STREAM_UPDATE( mos6560_update ) |
695 | | { |
696 | | mos6560_state *mos6560 = get_safe_token(device); |
697 | | int i, v; |
698 | | stream_sample_t *buffer = outputs[0]; |
699 | | |
700 | | for (i = 0; i < samples; i++) |
701 | | { |
702 | | v = 0; |
703 | | if (TONE1_ON /*||(mos6560->tone1pos != 0) */ ) |
704 | | { |
705 | | v += mos6560->tone[mos6560->tone1pos * mos6560->tonesize / mos6560->tone1samples]; |
706 | | mos6560->tone1pos++; |
707 | | #if 0 |
708 | | mos6560->tone1pos %= mos6560->tone1samples; |
709 | | #else |
710 | | if (mos6560->tone1pos >= mos6560->tone1samples) |
711 | | { |
712 | | mos6560->tone1pos = 0; |
713 | | mos6560->tone1samples = device->machine().sample_rate() / TONE1_FREQUENCY; |
714 | | if (mos6560->tone1samples == 0) |
715 | | mos6560->tone1samples = 1; |
716 | | } |
717 | | #endif |
718 | | } |
719 | | if (TONE2_ON /*||(mos6560->tone2pos != 0) */ ) |
720 | | { |
721 | | v += mos6560->tone[mos6560->tone2pos * mos6560->tonesize / mos6560->tone2samples]; |
722 | | mos6560->tone2pos++; |
723 | | #if 0 |
724 | | mos6560->tone2pos %= mos6560->tone2samples; |
725 | | #else |
726 | | if (mos6560->tone2pos >= mos6560->tone2samples) |
727 | | { |
728 | | mos6560->tone2pos = 0; |
729 | | mos6560->tone2samples = device->machine().sample_rate() / TONE2_FREQUENCY; |
730 | | if (mos6560->tone2samples == 0) |
731 | | mos6560->tone2samples = 1; |
732 | | } |
733 | | #endif |
734 | | } |
735 | | if (TONE3_ON /*||(mos6560->tone3pos != 0) */ ) |
736 | | { |
737 | | v += mos6560->tone[mos6560->tone3pos * mos6560->tonesize / mos6560->tone3samples]; |
738 | | mos6560->tone3pos++; |
739 | | #if 0 |
740 | | mos6560->tone3pos %= mos6560->tone3samples; |
741 | | #else |
742 | | if (mos6560->tone3pos >= mos6560->tone3samples) |
743 | | { |
744 | | mos6560->tone3pos = 0; |
745 | | mos6560->tone3samples = device->machine().sample_rate() / TONE3_FREQUENCY; |
746 | | if (mos6560->tone3samples == 0) |
747 | | mos6560->tone3samples = 1; |
748 | | } |
749 | | #endif |
750 | | } |
751 | | if (NOISE_ON) |
752 | | { |
753 | | v += mos6560->noise[(int) ((double) mos6560->noisepos * mos6560->noisesize / mos6560->noisesamples)]; |
754 | | mos6560->noisepos++; |
755 | | if ((double) mos6560->noisepos / mos6560->noisesamples >= 1.0) |
756 | | { |
757 | | mos6560->noisepos = 0; |
758 | | } |
759 | | } |
760 | | v = (v * VOLUME) << 2; |
761 | | if (v > 32767) |
762 | | buffer[i] = 32767; |
763 | | else if (v < -32767) |
764 | | buffer[i] = -32767; |
765 | | else |
766 | | buffer[i] = v; |
767 | | |
768 | | |
769 | | |
770 | | } |
771 | | } |
772 | | |
773 | | |
774 | 620 | /***************************************************************************** |
775 | 621 | DEVICE INTERFACE |
776 | 622 | *****************************************************************************/ |
r17678 | r17679 | |
780 | 626 | (to be called at device start) |
781 | 627 | -------------------------------------------------*/ |
782 | 628 | |
783 | | static void mos6560_sound_start( device_t *device ) |
| 629 | void mos6560_device::sound_start() |
784 | 630 | { |
785 | | mos6560_state *mos6560 = get_safe_token(device); |
786 | 631 | int i; |
787 | 632 | |
788 | | mos6560->channel = device->machine().sound().stream_alloc(*device, 0, 1, device->machine().sample_rate(), 0, mos6560_update); |
| 633 | m_channel = machine().sound().stream_alloc(*this, 0, 1, machine().sample_rate()); |
789 | 634 | |
790 | 635 | /* buffer for fastest played sample for 5 second so we have enough data for min 5 second */ |
791 | | mos6560->noisesize = NOISE_FREQUENCY_MAX * NOISE_BUFFER_SIZE_SEC; |
792 | | mos6560->noise = auto_alloc_array(device->machine(), INT8, mos6560->noisesize); |
| 636 | m_noisesize = NOISE_FREQUENCY_MAX * NOISE_BUFFER_SIZE_SEC; |
| 637 | m_noise = auto_alloc_array(machine(), INT8, m_noisesize); |
793 | 638 | { |
794 | 639 | int noiseshift = 0x7ffff8; |
795 | 640 | char data; |
796 | 641 | |
797 | | for (i = 0; i < mos6560->noisesize; i++) |
| 642 | for (i = 0; i < m_noisesize; i++) |
798 | 643 | { |
799 | 644 | data = 0; |
800 | 645 | if (noiseshift & 0x400000) |
r17678 | r17679 | |
813 | 658 | data |= 0x02; |
814 | 659 | if (noiseshift & 0x000004) |
815 | 660 | data |= 0x01; |
816 | | mos6560->noise[i] = data; |
| 661 | m_noise[i] = data; |
817 | 662 | if (((noiseshift & 0x400000) == 0) != ((noiseshift & 0x002000) == 0)) |
818 | 663 | noiseshift = (noiseshift << 1) | 1; |
819 | 664 | else |
820 | 665 | noiseshift <<= 1; |
821 | 666 | } |
822 | 667 | } |
823 | | mos6560->tonesize = device->machine().sample_rate() / TONE_FREQUENCY_MIN; |
| 668 | m_tonesize = machine().sample_rate() / TONE_FREQUENCY_MIN; |
824 | 669 | |
825 | | if (mos6560->tonesize > 0) |
| 670 | if (m_tonesize > 0) |
826 | 671 | { |
827 | | mos6560->tone = auto_alloc_array(device->machine(), INT16, mos6560->tonesize); |
| 672 | m_tone = auto_alloc_array(machine(), INT16, m_tonesize); |
828 | 673 | |
829 | | for (i = 0; i < mos6560->tonesize; i++) |
| 674 | for (i = 0; i < m_tonesize; i++) |
830 | 675 | { |
831 | | mos6560->tone[i] = (INT16)(sin (2 * M_PI * i / mos6560->tonesize) * 127 + 0.5); |
| 676 | m_tone[i] = (INT16)(sin (2 * M_PI * i / m_tonesize) * 127 + 0.5); |
832 | 677 | } |
833 | 678 | } |
834 | 679 | else |
835 | 680 | { |
836 | | mos6560->tone = NULL; |
| 681 | m_tone = NULL; |
837 | 682 | } |
838 | 683 | } |
839 | 684 | |
840 | 685 | |
841 | | /*------------------------------------------------- |
842 | | DEVICE_START( mos6560 ) |
843 | | -------------------------------------------------*/ |
| 686 | const device_type MOS6560 = &device_creator<mos6560_device>; |
| 687 | const device_type MOS6561 = &device_creator<mos6561_device>; |
| 688 | const device_type MOS656X_ATTACK_UFO = &device_creator<mos656x_attack_ufo_device>; |
844 | 689 | |
845 | | static DEVICE_START( mos6560 ) |
846 | | { |
847 | | mos6560_state *mos6560 = get_safe_token(device); |
848 | | const mos6560_interface *intf = (mos6560_interface *)device->static_config(); |
849 | | int width, height; |
| 690 | // default address maps |
| 691 | static ADDRESS_MAP_START( mos6560_videoram_map, AS_0, 8, mos6560_device ) |
| 692 | AM_RANGE(0x0000, 0x3fff) AM_RAM |
| 693 | ADDRESS_MAP_END |
850 | 694 | |
851 | | mos6560->screen = downcast<screen_device *>(device->machine().device(intf->screen)); |
852 | | width = mos6560->screen->width(); |
853 | | height = mos6560->screen->height(); |
| 695 | static ADDRESS_MAP_START( mos6560_colorram_map, AS_1, 8, mos6560_device ) |
| 696 | AM_RANGE(0x000, 0x3ff) AM_RAM |
| 697 | ADDRESS_MAP_END |
854 | 698 | |
855 | | mos6560->type = intf->type; |
| 699 | mos6560_device::mos6560_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) |
| 700 | : device_t(mconfig, type, name, tag, owner, clock), |
| 701 | device_memory_interface(mconfig, *this), |
| 702 | device_sound_interface(mconfig, *this), |
| 703 | m_videoram_space_config("videoram", ENDIANNESS_LITTLE, 8, 14, 0, NULL, *ADDRESS_MAP_NAME(mos6560_videoram_map)), |
| 704 | m_colorram_space_config("colorram", ENDIANNESS_LITTLE, 8, 10, 0, NULL, *ADDRESS_MAP_NAME(mos6560_colorram_map)) |
| 705 | { |
| 706 | } |
856 | 707 | |
857 | | mos6560->bitmap = auto_bitmap_ind16_alloc(device->machine(), width, height); |
| 708 | mos6560_device::mos6560_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 709 | : device_t(mconfig, MOS6560, "MOS6560", tag, owner, clock), |
| 710 | device_memory_interface(mconfig, *this), |
| 711 | device_sound_interface(mconfig, *this), |
| 712 | m_variant(TYPE_6560), |
| 713 | m_videoram_space_config("videoram", ENDIANNESS_LITTLE, 8, 14, 0, NULL, *ADDRESS_MAP_NAME(mos6560_videoram_map)), |
| 714 | m_colorram_space_config("colorram", ENDIANNESS_LITTLE, 8, 10, 0, NULL, *ADDRESS_MAP_NAME(mos6560_colorram_map)) |
| 715 | { |
| 716 | } |
858 | 717 | |
859 | | // resolve callbacks |
860 | | mos6560->dma_read.resolve(intf->dma_read, *device); |
861 | | mos6560->dma_read_color.resolve(intf->dma_read_color, *device); |
862 | | mos6560->lightpen_button_cb.resolve(intf->button_cb, *device); |
863 | | mos6560->lightpen_x_cb.resolve(intf->x_cb, *device); |
864 | | mos6560->lightpen_y_cb.resolve(intf->y_cb, *device); |
865 | | mos6560->paddle_cb[0].resolve(intf->paddle0_cb, *device); |
866 | | mos6560->paddle_cb[1].resolve(intf->paddle1_cb, *device); |
| 718 | mos6561_device::mos6561_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 719 | :mos6560_device(mconfig, MOS6561, "MOS6561", tag, owner, clock) { m_variant = TYPE_6561; } |
867 | 720 | |
868 | | switch (mos6560->type) |
869 | | { |
870 | | case MOS6560: |
871 | | mos6560->total_xsize = MOS6560_XSIZE; |
872 | | mos6560->total_ysize = MOS6560_YSIZE; |
873 | | mos6560->total_lines = MOS6560_LINES; |
874 | | mos6560->total_vretracerate = MOS6560_VRETRACERATE; |
875 | | break; |
876 | | case MOS6560_ATTACKUFO: |
877 | | mos6560->total_xsize = 23 * 8; |
878 | | mos6560->total_ysize = 22 * 8; |
879 | | mos6560->total_lines = MOS6560_LINES; |
880 | | mos6560->total_vretracerate = MOS6560_VRETRACERATE; |
881 | | break; |
882 | | case MOS6561: |
883 | | mos6560->total_xsize = MOS6561_XSIZE; |
884 | | mos6560->total_ysize = MOS6561_YSIZE; |
885 | | mos6560->total_lines = MOS6561_LINES; |
886 | | mos6560->total_vretracerate = MOS6561_VRETRACERATE; |
887 | | break; |
888 | | } |
| 721 | mos656x_attack_ufo_device::mos656x_attack_ufo_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 722 | :mos6560_device(mconfig, MOS656X_ATTACK_UFO, "MOS656X", tag, owner, clock) { m_variant = TYPE_ATTACK_UFO; } |
889 | 723 | |
890 | | mos6560_sound_start(device); |
| 724 | //------------------------------------------------- |
| 725 | // device_config_complete - perform any |
| 726 | // operations now that the configuration is |
| 727 | // complete |
| 728 | //------------------------------------------------- |
891 | 729 | |
892 | | device->save_item(NAME(mos6560->lightpenreadtime)); |
893 | | device->save_item(NAME(mos6560->rasterline)); |
894 | | device->save_item(NAME(mos6560->lastline)); |
| 730 | void mos6560_device::device_config_complete() |
| 731 | { |
| 732 | // inherit a copy of the static data |
| 733 | const mos6560_interface *intf = reinterpret_cast<const mos6560_interface *>(static_config()); |
| 734 | if (intf != NULL) |
| 735 | *static_cast<mos6560_interface *>(this) = *intf; |
895 | 736 | |
896 | | device->save_item(NAME(mos6560->charheight)); |
897 | | device->save_item(NAME(mos6560->matrix8x16)); |
898 | | device->save_item(NAME(mos6560->inverted)); |
899 | | device->save_item(NAME(mos6560->chars_x)); |
900 | | device->save_item(NAME(mos6560->chars_y)); |
901 | | device->save_item(NAME(mos6560->xsize)); |
902 | | device->save_item(NAME(mos6560->ysize)); |
903 | | device->save_item(NAME(mos6560->xpos)); |
904 | | device->save_item(NAME(mos6560->ypos)); |
905 | | device->save_item(NAME(mos6560->chargenaddr)); |
906 | | device->save_item(NAME(mos6560->videoaddr)); |
| 737 | // or initialize to defaults if none provided |
| 738 | else |
| 739 | { |
| 740 | // TODO |
| 741 | } |
| 742 | } |
907 | 743 | |
908 | | device->save_item(NAME(mos6560->backgroundcolor)); |
909 | | device->save_item(NAME(mos6560->framecolor)); |
910 | | device->save_item(NAME(mos6560->helpercolor)); |
911 | 744 | |
912 | | device->save_item(NAME(mos6560->reg)); |
| 745 | //------------------------------------------------- |
| 746 | // memory_space_config - return a description of |
| 747 | // any address spaces owned by this device |
| 748 | //------------------------------------------------- |
913 | 749 | |
914 | | device->save_item(NAME(mos6560->mono)); |
915 | | device->save_item(NAME(mos6560->monoinverted)); |
916 | | device->save_item(NAME(mos6560->multi)); |
917 | | device->save_item(NAME(mos6560->multiinverted)); |
918 | | |
919 | | device->save_item(NAME(mos6560->last_data)); |
920 | | |
921 | | device->save_item(NAME(*mos6560->bitmap)); |
922 | | |
923 | | device->save_item(NAME(mos6560->tone1pos)); |
924 | | device->save_item(NAME(mos6560->tone2pos)); |
925 | | device->save_item(NAME(mos6560->tone3pos)); |
926 | | device->save_item(NAME(mos6560->tone1samples)); |
927 | | device->save_item(NAME(mos6560->tone2samples)); |
928 | | device->save_item(NAME(mos6560->tone3samples)); |
929 | | device->save_item(NAME(mos6560->noisepos)); |
930 | | device->save_item(NAME(mos6560->noisesamples)); |
| 750 | const address_space_config *mos6560_device::memory_space_config(address_spacenum spacenum) const |
| 751 | { |
| 752 | switch (spacenum) |
| 753 | { |
| 754 | case AS_0: return &m_videoram_space_config; |
| 755 | case AS_1: return &m_colorram_space_config; |
| 756 | default: return NULL; |
| 757 | } |
931 | 758 | } |
932 | 759 | |
933 | | /*------------------------------------------------- |
934 | | DEVICE_RESET( mos6560 ) |
935 | | -------------------------------------------------*/ |
| 760 | //------------------------------------------------- |
| 761 | // device_start - device-specific startup |
| 762 | //------------------------------------------------- |
936 | 763 | |
937 | | static DEVICE_RESET( mos6560 ) |
| 764 | void mos6560_device::device_start() |
938 | 765 | { |
939 | | mos6560_state *mos6560 = get_safe_token(device); |
| 766 | m_screen = machine().device<screen_device>(m_screen_tag); |
| 767 | m_screen->register_screen_bitmap(m_bitmap); |
940 | 768 | |
941 | | mos6560->lightpenreadtime = 0.0; |
942 | | mos6560->rasterline = 0; |
943 | | mos6560->lastline = 0; |
| 769 | // resolve callbacks |
| 770 | m_paddle_cb[0].resolve(m_potx_cb, *this); |
| 771 | m_paddle_cb[1].resolve(m_poty_cb, *this); |
944 | 772 | |
945 | | memset(mos6560->reg, 0, 16); |
| 773 | switch (m_variant) |
| 774 | { |
| 775 | case TYPE_6560: |
| 776 | m_total_xsize = MOS6560_XSIZE; |
| 777 | m_total_ysize = MOS6560_YSIZE; |
| 778 | m_total_lines = MOS6560_LINES; |
| 779 | m_total_vretracerate = MOS6560_VRETRACERATE; |
| 780 | break; |
| 781 | case TYPE_ATTACK_UFO: |
| 782 | m_total_xsize = 23 * 8; |
| 783 | m_total_ysize = 22 * 8; |
| 784 | m_total_lines = MOS6560_LINES; |
| 785 | m_total_vretracerate = MOS6560_VRETRACERATE; |
| 786 | break; |
| 787 | case TYPE_6561: |
| 788 | m_total_xsize = MOS6561_XSIZE; |
| 789 | m_total_ysize = MOS6561_YSIZE; |
| 790 | m_total_lines = MOS6561_LINES; |
| 791 | m_total_vretracerate = MOS6561_VRETRACERATE; |
| 792 | break; |
| 793 | } |
946 | 794 | |
947 | | mos6560->charheight = 8; |
948 | | mos6560->matrix8x16 = 0; |
949 | | mos6560->inverted = 0; |
950 | | mos6560->chars_x = 0; |
951 | | mos6560->chars_y = 0; |
952 | | mos6560->xsize = 0; |
953 | | mos6560->ysize = 0; |
954 | | mos6560->xpos = 0; |
955 | | mos6560->ypos = 0; |
956 | | mos6560->chargenaddr = 0; |
957 | | mos6560->videoaddr = 0; |
| 795 | // initialize palette |
| 796 | initialize_palette(); |
958 | 797 | |
959 | | mos6560->backgroundcolor = 0; |
960 | | mos6560->framecolor = 0; |
961 | | mos6560->helpercolor = 0; |
| 798 | sound_start(); |
962 | 799 | |
963 | | mos6560->mono[0] = 0; |
964 | | mos6560->mono[1] = 0; |
965 | | mos6560->monoinverted[0] = 0; |
966 | | mos6560->monoinverted[1] = 0; |
967 | | mos6560->multi[0] = 0; |
968 | | mos6560->multi[1] = 0; |
969 | | mos6560->multi[2] = 0; |
970 | | mos6560->multi[3] = 0; |
971 | | mos6560->multiinverted[0] = 0; |
972 | | mos6560->multiinverted[1] = 0; |
973 | | mos6560->multiinverted[2] = 0; |
974 | | mos6560->multiinverted[3] = 0; |
| 800 | save_item(NAME(m_lightpenreadtime)); |
| 801 | save_item(NAME(m_rasterline)); |
| 802 | save_item(NAME(m_lastline)); |
975 | 803 | |
976 | | mos6560->tone1pos = 0; |
977 | | mos6560->tone2pos = 0; |
978 | | mos6560->tone3pos = 0; |
979 | | mos6560->tone1samples = 1; |
980 | | mos6560->tone2samples = 1; |
981 | | mos6560->tone3samples = 1; |
982 | | mos6560->noisepos = 0; |
983 | | mos6560->noisesamples = 1; |
984 | | } |
| 804 | save_item(NAME(m_charheight)); |
| 805 | save_item(NAME(m_matrix8x16)); |
| 806 | save_item(NAME(m_inverted)); |
| 807 | save_item(NAME(m_chars_x)); |
| 808 | save_item(NAME(m_chars_y)); |
| 809 | save_item(NAME(m_xsize)); |
| 810 | save_item(NAME(m_ysize)); |
| 811 | save_item(NAME(m_xpos)); |
| 812 | save_item(NAME(m_ypos)); |
| 813 | save_item(NAME(m_chargenaddr)); |
| 814 | save_item(NAME(m_videoaddr)); |
985 | 815 | |
986 | | const device_type MOS656X = &device_creator<mos6560_device>; |
| 816 | save_item(NAME(m_backgroundcolor)); |
| 817 | save_item(NAME(m_framecolor)); |
| 818 | save_item(NAME(m_helpercolor)); |
987 | 819 | |
988 | | mos6560_device::mos6560_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
989 | | : device_t(mconfig, MOS656X, "MOS 6560 / 6561 VIC", tag, owner, clock), |
990 | | device_sound_interface(mconfig, *this) |
991 | | { |
992 | | m_token = global_alloc_array_clear(UINT8, sizeof(mos6560_state)); |
993 | | } |
| 820 | save_item(NAME(m_reg)); |
994 | 821 | |
995 | | //------------------------------------------------- |
996 | | // device_config_complete - perform any |
997 | | // operations now that the configuration is |
998 | | // complete |
999 | | //------------------------------------------------- |
| 822 | save_item(NAME(m_mono)); |
| 823 | save_item(NAME(m_monoinverted)); |
| 824 | save_item(NAME(m_multi)); |
| 825 | save_item(NAME(m_multiinverted)); |
1000 | 826 | |
1001 | | void mos6560_device::device_config_complete() |
1002 | | { |
1003 | | } |
| 827 | save_item(NAME(m_last_data)); |
1004 | 828 | |
1005 | | //------------------------------------------------- |
1006 | | // device_start - device-specific startup |
1007 | | //------------------------------------------------- |
1008 | | |
1009 | | void mos6560_device::device_start() |
1010 | | { |
1011 | | DEVICE_START_NAME( mos6560 )(this); |
| 829 | save_item(NAME(m_tone1pos)); |
| 830 | save_item(NAME(m_tone2pos)); |
| 831 | save_item(NAME(m_tone3pos)); |
| 832 | save_item(NAME(m_tone1samples)); |
| 833 | save_item(NAME(m_tone2samples)); |
| 834 | save_item(NAME(m_tone3samples)); |
| 835 | save_item(NAME(m_noisepos)); |
| 836 | save_item(NAME(m_noisesamples)); |
1012 | 837 | } |
1013 | 838 | |
1014 | 839 | //------------------------------------------------- |
r17678 | r17679 | |
1017 | 842 | |
1018 | 843 | void mos6560_device::device_reset() |
1019 | 844 | { |
1020 | | DEVICE_RESET_NAME( mos6560 )(this); |
| 845 | m_lightpenreadtime = 0.0; |
| 846 | m_rasterline = 0; |
| 847 | m_lastline = 0; |
| 848 | |
| 849 | memset(m_reg, 0, 16); |
| 850 | |
| 851 | m_charheight = 8; |
| 852 | m_matrix8x16 = 0; |
| 853 | m_inverted = 0; |
| 854 | m_chars_x = 0; |
| 855 | m_chars_y = 0; |
| 856 | m_xsize = 0; |
| 857 | m_ysize = 0; |
| 858 | m_xpos = 0; |
| 859 | m_ypos = 0; |
| 860 | m_chargenaddr = 0; |
| 861 | m_videoaddr = 0; |
| 862 | |
| 863 | m_backgroundcolor = 0; |
| 864 | m_framecolor = 0; |
| 865 | m_helpercolor = 0; |
| 866 | |
| 867 | m_mono[0] = 0; |
| 868 | m_mono[1] = 0; |
| 869 | m_monoinverted[0] = 0; |
| 870 | m_monoinverted[1] = 0; |
| 871 | m_multi[0] = 0; |
| 872 | m_multi[1] = 0; |
| 873 | m_multi[2] = 0; |
| 874 | m_multi[3] = 0; |
| 875 | m_multiinverted[0] = 0; |
| 876 | m_multiinverted[1] = 0; |
| 877 | m_multiinverted[2] = 0; |
| 878 | m_multiinverted[3] = 0; |
| 879 | |
| 880 | m_tone1pos = 0; |
| 881 | m_tone2pos = 0; |
| 882 | m_tone3pos = 0; |
| 883 | m_tone1samples = 1; |
| 884 | m_tone2samples = 1; |
| 885 | m_tone3samples = 1; |
| 886 | m_noisepos = 0; |
| 887 | m_noisesamples = 1; |
1021 | 888 | } |
1022 | 889 | |
1023 | 890 | //------------------------------------------------- |
r17678 | r17679 | |
1026 | 893 | |
1027 | 894 | void mos6560_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
1028 | 895 | { |
1029 | | // should never get here |
1030 | | fatalerror("sound_stream_update called; not applicable to legacy sound devices\n"); |
1031 | | } |
| 896 | int i, v; |
| 897 | stream_sample_t *buffer = outputs[0]; |
1032 | 898 | |
1033 | | |
| 899 | for (i = 0; i < samples; i++) |
| 900 | { |
| 901 | v = 0; |
| 902 | if (TONE1_ON /*||(m_tone1pos != 0) */ ) |
| 903 | { |
| 904 | v += m_tone[m_tone1pos * m_tonesize / m_tone1samples]; |
| 905 | m_tone1pos++; |
| 906 | #if 0 |
| 907 | m_tone1pos %= m_tone1samples; |
| 908 | #else |
| 909 | if (m_tone1pos >= m_tone1samples) |
| 910 | { |
| 911 | m_tone1pos = 0; |
| 912 | m_tone1samples = machine().sample_rate() / TONE1_FREQUENCY; |
| 913 | if (m_tone1samples == 0) |
| 914 | m_tone1samples = 1; |
| 915 | } |
| 916 | #endif |
| 917 | } |
| 918 | if (TONE2_ON /*||(m_tone2pos != 0) */ ) |
| 919 | { |
| 920 | v += m_tone[m_tone2pos * m_tonesize / m_tone2samples]; |
| 921 | m_tone2pos++; |
| 922 | #if 0 |
| 923 | m_tone2pos %= m_tone2samples; |
| 924 | #else |
| 925 | if (m_tone2pos >= m_tone2samples) |
| 926 | { |
| 927 | m_tone2pos = 0; |
| 928 | m_tone2samples = machine().sample_rate() / TONE2_FREQUENCY; |
| 929 | if (m_tone2samples == 0) |
| 930 | m_tone2samples = 1; |
| 931 | } |
| 932 | #endif |
| 933 | } |
| 934 | if (TONE3_ON /*||(m_tone3pos != 0) */ ) |
| 935 | { |
| 936 | v += m_tone[m_tone3pos * m_tonesize / m_tone3samples]; |
| 937 | m_tone3pos++; |
| 938 | #if 0 |
| 939 | m_tone3pos %= m_tone3samples; |
| 940 | #else |
| 941 | if (m_tone3pos >= m_tone3samples) |
| 942 | { |
| 943 | m_tone3pos = 0; |
| 944 | m_tone3samples = machine().sample_rate() / TONE3_FREQUENCY; |
| 945 | if (m_tone3samples == 0) |
| 946 | m_tone3samples = 1; |
| 947 | } |
| 948 | #endif |
| 949 | } |
| 950 | if (NOISE_ON) |
| 951 | { |
| 952 | v += m_noise[(int) ((double) m_noisepos * m_noisesize / m_noisesamples)]; |
| 953 | m_noisepos++; |
| 954 | if ((double) m_noisepos / m_noisesamples >= 1.0) |
| 955 | { |
| 956 | m_noisepos = 0; |
| 957 | } |
| 958 | } |
| 959 | v = (v * VOLUME) << 2; |
| 960 | if (v > 32767) |
| 961 | buffer[i] = 32767; |
| 962 | else if (v < -32767) |
| 963 | buffer[i] = -32767; |
| 964 | else |
| 965 | buffer[i] = v; |
| 966 | } |
| 967 | } |
trunk/src/emu/sound/mos6560.h
r17678 | r17679 | |
1 | | /***************************************************************************** |
2 | | * |
3 | | * audio/vic6560.h |
4 | | * |
5 | | ****************************************************************************/ |
| 1 | /*************************************************************************** |
6 | 2 | |
7 | | #ifndef __MOS6560_H__ |
8 | | #define __MOS6560_H__ |
| 3 | MOS 6560/6561 Video Interface Chip (VIC) emulation |
9 | 4 | |
10 | | #include "devlegcy.h" |
11 | | #include "devcb.h" |
| 5 | Copyright the MESS Team. |
| 6 | Visit http://mamedev.org for licensing and usage restrictions. |
12 | 7 | |
| 8 | **************************************************************************** |
| 9 | _____ _____ |
| 10 | N/C 1 |* \_/ | 40 Vdd |
| 11 | CHROMA 2 | | 39 phi1 |
| 12 | LUMA/SYNC 3 | | 38 phi2 |
| 13 | R/W 4 | | 37 OPTION |
| 14 | D11 5 | | 36 Pphi2 |
| 15 | D10 6 | | 35 Pphi1 |
| 16 | D9 7 | | 34 A13 |
| 17 | D8 8 | | 33 A12 |
| 18 | D7 9 | | 32 A11 |
| 19 | D6 10 | MOS6560 | 31 A10 |
| 20 | D5 11 | MOS6561 | 30 A9 |
| 21 | D4 12 | | 29 A8 |
| 22 | D3 13 | | 28 A7 |
| 23 | D2 14 | | 27 A6 |
| 24 | D1 15 | | 26 A5 |
| 25 | D0 16 | | 25 A4 |
| 26 | POT X 17 | | 24 A3 |
| 27 | POT Y 18 | | 23 A2 |
| 28 | AUDIO 19 | | 22 A1 |
| 29 | Vss 20 |_____________| 21 A0 |
13 | 30 | |
14 | | /*************************************************************************** |
15 | | TYPE DEFINITIONS |
16 | 31 | ***************************************************************************/ |
17 | 32 | |
18 | | typedef enum |
19 | | { |
20 | | MOS6560_ATTACKUFO, // this is a 6560VIC derivative, missing some of the features |
21 | | MOS6560, // this is the NTSC version |
22 | | MOS6561 // this is the PAL version |
23 | | } mos6560_type; |
| 33 | #pragma once |
24 | 34 | |
25 | | typedef struct _mos6560_interface mos6560_interface; |
26 | | struct _mos6560_interface |
27 | | { |
28 | | const char *screen; |
| 35 | #ifndef __MOS6560__ |
| 36 | #define __MOS6560__ |
29 | 37 | |
30 | | mos6560_type type; |
| 38 | #include "emu.h" |
31 | 39 | |
32 | | devcb_read8 x_cb; |
33 | | devcb_read8 y_cb; |
34 | | devcb_read8 button_cb; |
35 | 40 | |
36 | | devcb_read8 paddle0_cb, paddle1_cb; |
37 | 41 | |
38 | | devcb_read8 dma_read; |
39 | | devcb_read8 dma_read_color; |
40 | | }; |
| 42 | //*************************************************************************** |
| 43 | // DEVICE CONFIGURATION MACROS |
| 44 | //*************************************************************************** |
41 | 45 | |
42 | | /*************************************************************************** |
43 | | CONSTANTS |
44 | | ***************************************************************************/ |
| 46 | #define MCFG_MOS6560_ADD(_tag, _screen_tag, _clock, _config, _videoram_map, _colorram_map) \ |
| 47 | MCFG_SCREEN_ADD(_screen_tag, RASTER) \ |
| 48 | MCFG_SCREEN_REFRESH_RATE(MOS6560_VRETRACERATE) \ |
| 49 | MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) \ |
| 50 | MCFG_SCREEN_SIZE((MOS6560_XSIZE + 7) & ~7, MOS6560_YSIZE) \ |
| 51 | MCFG_SCREEN_VISIBLE_AREA(MOS6560_MAME_XPOS, MOS6560_MAME_XPOS + MOS6560_MAME_XSIZE - 1, MOS6560_MAME_YPOS, MOS6560_MAME_YPOS + MOS6560_MAME_YSIZE - 1) \ |
| 52 | MCFG_SCREEN_UPDATE_DEVICE(_tag, mos6560_device, screen_update) \ |
| 53 | MCFG_PALETTE_LENGTH(16) \ |
| 54 | MCFG_SOUND_ADD(_tag, MOS6560, _clock) \ |
| 55 | MCFG_DEVICE_CONFIG(_config) \ |
| 56 | MCFG_DEVICE_ADDRESS_MAP(AS_0, _videoram_map) \ |
| 57 | MCFG_DEVICE_ADDRESS_MAP(AS_1, _colorram_map) |
45 | 58 | |
| 59 | #define MCFG_MOS6561_ADD(_tag, _screen_tag, _clock, _config, _videoram_map, _colorram_map) \ |
| 60 | MCFG_SCREEN_ADD(_screen_tag, RASTER) \ |
| 61 | MCFG_SCREEN_REFRESH_RATE(MOS6561_VRETRACERATE) \ |
| 62 | MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) \ |
| 63 | MCFG_SCREEN_SIZE((MOS6561_XSIZE + 7) & ~7, MOS6561_YSIZE) \ |
| 64 | MCFG_SCREEN_VISIBLE_AREA(MOS6561_MAME_XPOS, MOS6561_MAME_XPOS + MOS6561_MAME_XSIZE - 1, MOS6561_MAME_YPOS, MOS6561_MAME_YPOS + MOS6561_MAME_YSIZE - 1) \ |
| 65 | MCFG_SCREEN_UPDATE_DEVICE(_tag, mos6560_device, screen_update) \ |
| 66 | MCFG_PALETTE_LENGTH(16) \ |
| 67 | MCFG_SOUND_ADD(_tag, MOS6561, _clock) \ |
| 68 | MCFG_DEVICE_CONFIG(_config) \ |
| 69 | MCFG_DEVICE_ADDRESS_MAP(AS_0, _videoram_map) \ |
| 70 | MCFG_DEVICE_ADDRESS_MAP(AS_1, _colorram_map) |
| 71 | |
| 72 | #define MCFG_MOS656X_ATTACK_UFO_ADD(_tag, _screen_tag, _clock, _config, _videoram_map, _colorram_map) \ |
| 73 | MCFG_SCREEN_ADD(_screen_tag, RASTER) \ |
| 74 | MCFG_SCREEN_REFRESH_RATE(MOS6560_VRETRACERATE) \ |
| 75 | MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) \ |
| 76 | MCFG_SCREEN_SIZE((MOS6560_XSIZE + 7) & ~7, MOS6560_YSIZE) \ |
| 77 | MCFG_SCREEN_VISIBLE_AREA(0, 23*8 - 1, 0, 22*8 - 1) \ |
| 78 | MCFG_SCREEN_UPDATE_DEVICE(_tag, mos6560_device, screen_update) \ |
| 79 | MCFG_PALETTE_LENGTH(16) \ |
| 80 | MCFG_SOUND_ADD(_tag, MOS656X_ATTACK_UFO, _clock) \ |
| 81 | MCFG_DEVICE_CONFIG(_config) \ |
| 82 | MCFG_DEVICE_ADDRESS_MAP(AS_0, _videoram_map) \ |
| 83 | MCFG_DEVICE_ADDRESS_MAP(AS_1, _colorram_map) |
| 84 | |
| 85 | |
| 86 | #define MOS6560_INTERFACE(_name) \ |
| 87 | const mos6560_interface (_name) = |
| 88 | |
| 89 | |
| 90 | |
| 91 | //************************************************************************** |
| 92 | // MACROS / CONSTANTS |
| 93 | //************************************************************************** |
| 94 | |
46 | 95 | #define MOS6560_VRETRACERATE 60 |
47 | 96 | #define MOS6561_VRETRACERATE 50 |
48 | 97 | #define MOS656X_HRETRACERATE 15625 |
r17678 | r17679 | |
75 | 124 | #define MOS6561_CLOCK (4433618/4) |
76 | 125 | |
77 | 126 | |
78 | | /*************************************************************************** |
79 | | INFO PROTOTYPES |
80 | | ***************************************************************************/ |
81 | 127 | |
| 128 | //*************************************************************************** |
| 129 | // TYPE DEFINITIONS |
| 130 | //*************************************************************************** |
| 131 | |
| 132 | // ======================> mos6560_interface |
| 133 | |
| 134 | struct mos6560_interface |
| 135 | { |
| 136 | const char *m_screen_tag; |
| 137 | |
| 138 | devcb_read8 m_potx_cb; |
| 139 | devcb_read8 m_poty_cb; |
| 140 | }; |
| 141 | |
| 142 | |
| 143 | // ======================> mos6560_device |
| 144 | |
82 | 145 | class mos6560_device : public device_t, |
83 | | public device_sound_interface |
| 146 | public device_memory_interface, |
| 147 | public device_sound_interface, |
| 148 | public mos6560_interface |
84 | 149 | { |
85 | 150 | public: |
| 151 | mos6560_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock); |
86 | 152 | mos6560_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
87 | | ~mos6560_device() { global_free(m_token); } |
88 | 153 | |
89 | | // access to legacy token |
90 | | void *token() const { assert(m_token != NULL); return m_token; } |
| 154 | virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const; |
91 | 155 | |
| 156 | DECLARE_READ8_MEMBER( read ); |
| 157 | DECLARE_WRITE8_MEMBER( write ); |
| 158 | |
92 | 159 | UINT8 bus_r(); |
93 | 160 | |
| 161 | DECLARE_WRITE_LINE_MEMBER( lp_w ); |
| 162 | |
94 | 163 | UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); |
| 164 | void raster_interrupt_gen(); |
95 | 165 | |
96 | 166 | protected: |
| 167 | enum |
| 168 | { |
| 169 | TYPE_6560, // NTSC-M |
| 170 | TYPE_6561, // PAL-B |
| 171 | TYPE_ATTACK_UFO // NTSC-M, less features |
| 172 | }; |
| 173 | |
97 | 174 | // device-level overrides |
98 | 175 | virtual void device_config_complete(); |
99 | 176 | virtual void device_start(); |
r17678 | r17679 | |
101 | 178 | |
102 | 179 | // sound stream update overrides |
103 | 180 | virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); |
104 | | private: |
105 | | // internal state |
106 | | void *m_token; |
| 181 | |
| 182 | inline void initialize_palette(); |
| 183 | inline UINT8 read_videoram(offs_t offset); |
| 184 | inline UINT8 read_colorram(offs_t offset); |
| 185 | |
| 186 | void draw_character( int ybegin, int yend, int ch, int yoff, int xoff, UINT16 *color ); |
| 187 | void draw_character_multi( int ybegin, int yend, int ch, int yoff, int xoff, UINT16 *color ); |
| 188 | void drawlines( int first, int last ); |
| 189 | void soundport_w( int offset, int data ); |
| 190 | void sound_start(); |
| 191 | |
| 192 | int m_variant; |
| 193 | |
| 194 | const address_space_config m_videoram_space_config; |
| 195 | const address_space_config m_colorram_space_config; |
| 196 | |
| 197 | screen_device *m_screen; |
| 198 | |
| 199 | UINT8 m_reg[16]; |
| 200 | |
| 201 | bitmap_ind16 m_bitmap; |
| 202 | |
| 203 | int m_rasterline, m_lastline; |
| 204 | double m_lightpenreadtime; |
| 205 | |
| 206 | int m_charheight, m_matrix8x16, m_inverted; |
| 207 | int m_chars_x, m_chars_y; |
| 208 | int m_xsize, m_ysize, m_xpos, m_ypos; |
| 209 | int m_chargenaddr, m_videoaddr; |
| 210 | |
| 211 | /* values in videoformat */ |
| 212 | UINT16 m_backgroundcolor, m_framecolor, m_helpercolor; |
| 213 | |
| 214 | /* arrays for bit to color conversion without condition checking */ |
| 215 | UINT16 m_mono[2], m_monoinverted[2], m_multi[4], m_multiinverted[4]; |
| 216 | |
| 217 | /* video chip settings */ |
| 218 | int m_total_xsize, m_total_ysize, m_total_lines, m_total_vretracerate; |
| 219 | |
| 220 | /* DMA */ |
| 221 | UINT8 m_last_data; |
| 222 | |
| 223 | /* paddles */ |
| 224 | devcb_resolved_read8 m_paddle_cb[2]; |
| 225 | |
| 226 | /* sound part */ |
| 227 | int m_tone1pos, m_tone2pos, m_tone3pos, |
| 228 | m_tonesize, m_tone1samples, m_tone2samples, m_tone3samples, |
| 229 | m_noisesize, /* number of samples */ |
| 230 | m_noisepos, /* pos of tone */ |
| 231 | m_noisesamples; /* count of samples to give out per tone */ |
| 232 | |
| 233 | sound_stream *m_channel; |
| 234 | INT16 *m_tone; |
| 235 | INT8 *m_noise; |
107 | 236 | }; |
108 | 237 | |
109 | | extern const device_type MOS656X; |
110 | 238 | |
| 239 | // ======================> mos6561_device |
111 | 240 | |
112 | | /*************************************************************************** |
113 | | DEVICE CONFIGURATION MACROS |
114 | | ***************************************************************************/ |
| 241 | class mos6561_device : public mos6560_device |
| 242 | { |
| 243 | public: |
| 244 | // construction/destruction |
| 245 | mos6561_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 246 | }; |
115 | 247 | |
116 | | #define MCFG_MOS656X_ADD(_tag, _interface) \ |
117 | | MCFG_SOUND_ADD(_tag, MOS656X, 0) \ |
118 | | MCFG_DEVICE_CONFIG(_interface) |
119 | 248 | |
120 | | #define MCFG_MOS6560_ADD(_tag, _screen_tag, _clock, _config) \ |
121 | | MCFG_SCREEN_ADD(_screen_tag, RASTER) \ |
122 | | MCFG_SCREEN_REFRESH_RATE(MOS6560_VRETRACERATE) \ |
123 | | MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) \ |
124 | | MCFG_SCREEN_SIZE((MOS6560_XSIZE + 7) & ~7, MOS6560_YSIZE) \ |
125 | | MCFG_SCREEN_VISIBLE_AREA(MOS6560_MAME_XPOS, MOS6560_MAME_XPOS + MOS6560_MAME_XSIZE - 1, MOS6560_MAME_YPOS, MOS6560_MAME_YPOS + MOS6560_MAME_YSIZE - 1) \ |
126 | | MCFG_SCREEN_UPDATE_DEVICE(_tag, mos6560_device, screen_update) \ |
127 | | MCFG_PALETTE_LENGTH(16) \ |
128 | | MCFG_PALETTE_INIT(mos6560) \ |
129 | | MCFG_SOUND_ADD(_tag, MOS656X, _clock) \ |
130 | | MCFG_DEVICE_CONFIG(_config) |
| 249 | // ======================> mos656x_attack_ufo_device |
131 | 250 | |
132 | | #define MCFG_MOS6561_ADD(_tag, _screen_tag, _clock, _config) \ |
133 | | MCFG_SCREEN_ADD(_screen_tag, RASTER) \ |
134 | | MCFG_SCREEN_REFRESH_RATE(MOS6561_VRETRACERATE) \ |
135 | | MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) \ |
136 | | MCFG_SCREEN_SIZE((MOS6561_XSIZE + 7) & ~7, MOS6561_YSIZE) \ |
137 | | MCFG_SCREEN_VISIBLE_AREA(MOS6561_MAME_XPOS, MOS6561_MAME_XPOS + MOS6561_MAME_XSIZE - 1, MOS6561_MAME_YPOS, MOS6561_MAME_YPOS + MOS6561_MAME_YSIZE - 1) \ |
138 | | MCFG_SCREEN_UPDATE_DEVICE(_tag, mos6560_device, screen_update) \ |
139 | | MCFG_PALETTE_LENGTH(16) \ |
140 | | MCFG_PALETTE_INIT(mos6560) \ |
141 | | MCFG_SOUND_ADD(_tag, MOS656X, _clock) \ |
142 | | MCFG_DEVICE_CONFIG(_config) |
| 251 | class mos656x_attack_ufo_device : public mos6560_device |
| 252 | { |
| 253 | public: |
| 254 | // construction/destruction |
| 255 | mos656x_attack_ufo_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 256 | }; |
143 | 257 | |
144 | | /*************************************************************************** |
145 | | I/O PROTOTYPES |
146 | | ***************************************************************************/ |
147 | 258 | |
148 | | WRITE8_DEVICE_HANDLER( mos6560_port_w ); |
149 | | READ8_DEVICE_HANDLER( mos6560_port_r ); |
| 259 | // device type definitions |
| 260 | extern const device_type MOS6560; |
| 261 | extern const device_type MOS6561; |
| 262 | extern const device_type MOS656X_ATTACK_UFO; |
150 | 263 | |
151 | | void mos6560_raster_interrupt_gen( device_t *device ); |
152 | | UINT32 mos6560_video_update( device_t *device, bitmap_ind16 &bitmap, const rectangle &cliprect ); |
153 | 264 | |
154 | | extern PALETTE_INIT( mos6560 ); |
155 | 265 | |
156 | | #endif /* __MOS6560_H__ */ |
| 266 | #endif |
trunk/src/mess/drivers/vic20.c
r17678 | r17679 | |
135 | 135 | switch ((offset >> 10) & 0x07) |
136 | 136 | { |
137 | 137 | case RAM0: |
138 | | data = m_ram->pointer()[offset]; |
| 138 | data = m_ram->pointer()[offset & 0x3ff]; |
139 | 139 | break; |
140 | 140 | |
141 | 141 | case RAM1: ram1 = 0; break; |
r17678 | r17679 | |
170 | 170 | } |
171 | 171 | else if (offset >= 0x9000 && offset < 0x9010) |
172 | 172 | { |
173 | | data = mos6560_port_r(m_vic, offset & 0x0f); |
| 173 | data = m_vic->read(space, offset & 0x0f); |
174 | 174 | } |
175 | 175 | break; |
176 | 176 | |
r17678 | r17679 | |
245 | 245 | } |
246 | 246 | else if (offset >= 0x9000 && offset < 0x9010) |
247 | 247 | { |
248 | | mos6560_port_w(m_vic, offset & 0x0f, data); |
| 248 | m_vic->write(space, offset & 0x0f, data); |
249 | 249 | } |
250 | 250 | break; |
251 | 251 | |
r17678 | r17679 | |
265 | 265 | } |
266 | 266 | |
267 | 267 | |
| 268 | //------------------------------------------------- |
| 269 | // vic_videoram_r - |
| 270 | //------------------------------------------------- |
268 | 271 | |
| 272 | READ8_MEMBER( vic20_state::vic_videoram_r ) |
| 273 | { |
| 274 | int ram1 = 1, ram2 = 1, ram3 = 1; |
| 275 | int blk1 = 1, blk2 = 1, blk3 = 1, blk5 = 1; |
| 276 | int io2 = 1, io3 = 1; |
| 277 | |
| 278 | UINT8 data = 0; |
| 279 | |
| 280 | if (BIT(offset, 13)) |
| 281 | { |
| 282 | switch ((offset >> 10) & 0x07) |
| 283 | { |
| 284 | case RAM0: |
| 285 | data = m_ram->pointer()[offset & 0x3ff]; |
| 286 | break; |
| 287 | |
| 288 | case RAM1: ram1 = 0; break; |
| 289 | case RAM2: ram2 = 0; break; |
| 290 | case RAM3: ram3 = 0; break; |
| 291 | |
| 292 | default: |
| 293 | data = m_ram->pointer()[0x400 + (offset & 0xfff)]; |
| 294 | break; |
| 295 | } |
| 296 | } |
| 297 | else |
| 298 | { |
| 299 | data = m_charom[offset & 0xfff]; |
| 300 | } |
| 301 | |
| 302 | return m_exp->cd_r(space, offset & 0x1fff, data, ram1, ram2, ram3, blk1, blk2, blk3, blk5, io2, io3); |
| 303 | } |
| 304 | |
| 305 | |
| 306 | |
269 | 307 | //************************************************************************** |
270 | 308 | // VIDEO |
271 | 309 | //************************************************************************** |
r17678 | r17679 | |
273 | 311 | static INTERRUPT_GEN( vic20_raster_interrupt ) |
274 | 312 | { |
275 | 313 | vic20_state *state = device->machine().driver_data<vic20_state>(); |
276 | | mos6560_raster_interrupt_gen(state->m_vic); |
| 314 | state->m_vic->raster_interrupt_gen(); |
277 | 315 | } |
278 | 316 | |
279 | 317 | |
r17678 | r17679 | |
291 | 329 | ADDRESS_MAP_END |
292 | 330 | |
293 | 331 | |
294 | | |
295 | | //************************************************************************** |
296 | | // INPUT PORTS |
297 | | //************************************************************************** |
298 | | |
299 | | #ifdef UNUSED_FUNCTION |
300 | | |
301 | 332 | //------------------------------------------------- |
302 | | // INPUT_PORTS( vic_lightpen_6560 ) |
| 333 | // ADDRESS_MAP( vic_videoram_map ) |
303 | 334 | //------------------------------------------------- |
304 | 335 | |
305 | | static INPUT_PORTS_START( vic_lightpen_6560 ) |
306 | | PORT_START( "LIGHTX" ) |
307 | | PORT_BIT( 0xff, 0, IPT_PADDLE ) PORT_NAME("Lightpen X Axis") PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(30) PORT_KEYDELTA(2) PORT_MINMAX(0,(MOS6560_MAME_XSIZE - 1)) PORT_CODE_DEC(KEYCODE_LEFT) PORT_CODE_INC(KEYCODE_RIGHT) PORT_CODE_DEC(JOYCODE_X_LEFT_SWITCH) PORT_CODE_INC(JOYCODE_X_RIGHT_SWITCH) |
| 336 | static ADDRESS_MAP_START( vic_videoram_map, AS_0, 8, vic20_state ) |
| 337 | AM_RANGE(0x0000, 0x3fff) AM_READ(vic_videoram_r) |
| 338 | ADDRESS_MAP_END |
308 | 339 | |
309 | | PORT_START( "LIGHTY" ) |
310 | | PORT_BIT( 0xff, 0, IPT_PADDLE ) PORT_NAME("Lightpen Y Axis") PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(30) PORT_KEYDELTA(2) PORT_MINMAX(0,(MOS6560_MAME_YSIZE - 1)) PORT_CODE_DEC(KEYCODE_UP) PORT_CODE_INC(KEYCODE_DOWN) PORT_CODE_DEC(JOYCODE_Y_UP_SWITCH) PORT_CODE_INC(JOYCODE_Y_DOWN_SWITCH) |
311 | | INPUT_PORTS_END |
312 | 340 | |
313 | | |
314 | 341 | //------------------------------------------------- |
315 | | // INPUT_PORTS( vic_lightpen_6561 ) |
| 342 | // ADDRESS_MAP( vic_colorram_map ) |
316 | 343 | //------------------------------------------------- |
317 | 344 | |
318 | | static INPUT_PORTS_START( vic_lightpen_6561 ) |
319 | | PORT_START( "LIGHTX" ) |
320 | | PORT_BIT( 0xff, 0, IPT_PADDLE ) PORT_NAME("Lightpen X Axis") PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(30) PORT_KEYDELTA(2) PORT_MINMAX(0,(MOS6560_MAME_XSIZE - 1)) PORT_CODE_DEC(KEYCODE_LEFT) PORT_CODE_INC(KEYCODE_RIGHT) PORT_CODE_DEC(JOYCODE_X_LEFT_SWITCH) PORT_CODE_INC(JOYCODE_X_RIGHT_SWITCH) |
| 345 | static ADDRESS_MAP_START( vic_colorram_map, AS_1, 8, vic20_state ) |
| 346 | AM_RANGE(0x000, 0x3ff) AM_RAM AM_SHARE("color_ram") |
| 347 | ADDRESS_MAP_END |
321 | 348 | |
322 | | PORT_START( "LIGHTY" ) |
323 | | PORT_BIT( 0x1ff, 0, IPT_PADDLE ) PORT_NAME("Lightpen Y Axis") PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_SENSITIVITY(30) PORT_KEYDELTA(2) PORT_MINMAX(0,(MOS6561_MAME_YSIZE - 1)) PORT_CODE_DEC(KEYCODE_UP) PORT_CODE_INC(KEYCODE_DOWN) PORT_CODE_DEC(JOYCODE_Y_UP_SWITCH) PORT_CODE_INC(JOYCODE_Y_DOWN_SWITCH) |
324 | | INPUT_PORTS_END |
325 | | #endif |
326 | 349 | |
327 | 350 | |
| 351 | //************************************************************************** |
| 352 | // INPUT PORTS |
| 353 | //************************************************************************** |
| 354 | |
328 | 355 | //------------------------------------------------- |
329 | 356 | // INPUT_PORTS( vic20 ) |
330 | 357 | //------------------------------------------------- |
r17678 | r17679 | |
333 | 360 | PORT_INCLUDE( vic_keyboard ) // ROW0 -> ROW7 |
334 | 361 | |
335 | 362 | PORT_INCLUDE( vic_special ) // SPECIAL |
336 | | |
337 | | PORT_INCLUDE( vic_controls ) // CTRLSEL, JOY, FAKE0, FAKE1, PADDLE0, PADDLE1 |
338 | 363 | INPUT_PORTS_END |
339 | 364 | |
340 | 365 | |
r17678 | r17679 | |
396 | 421 | |
397 | 422 | PA0 SERIAL CLK IN |
398 | 423 | PA1 SERIAL DATA IN |
399 | | PA2 JOY 0 |
400 | | PA3 JOY 1 |
401 | | PA4 JOY 2 |
402 | | PA5 LITE PEN |
| 424 | PA2 JOY 0 (UP) |
| 425 | PA3 JOY 1 (DOWN) |
| 426 | PA4 JOY 2 (LEFT) |
| 427 | PA5 LITE PEN (FIRE) |
403 | 428 | PA6 CASS SWITCH |
404 | 429 | PA7 |
405 | 430 | |
r17678 | r17679 | |
413 | 438 | // serial data in |
414 | 439 | data |= m_iec->data_r() << 1; |
415 | 440 | |
416 | | // user port |
417 | | data |= m_user->joy0_r() << 2; |
418 | | data |= m_user->joy1_r() << 3; |
419 | | data |= m_user->joy2_r() << 4; |
420 | | data |= m_user->light_pen_r() << 5; |
| 441 | // joystick / user port |
| 442 | UINT8 joy = m_joy1->joy_r(); |
421 | 443 | |
| 444 | data |= (m_user->joy0_r() && BIT(joy, 0)) << 2; |
| 445 | data |= (m_user->joy1_r() && BIT(joy, 1)) << 3; |
| 446 | data |= (m_user->joy2_r() && BIT(joy, 2)) << 4; |
| 447 | data |= (m_user->light_pen_r() && BIT(joy, 5)) << 5; |
| 448 | |
422 | 449 | // cassette switch |
423 | 450 | data |= (m_user->cassette_switch_r() && m_cassette->sense_r()) << 6; |
424 | 451 | |
425 | | // joystick |
426 | | data &= ~(ioport("JOY")->read() & 0x3c); |
427 | | |
428 | 452 | return data; |
429 | 453 | } |
430 | 454 | |
r17678 | r17679 | |
511 | 535 | PB0 COL 0 |
512 | 536 | PB1 COL 1 |
513 | 537 | PB2 COL 2 |
514 | | PB3 COL 3, CASS WRITE |
| 538 | PB3 COL 3 |
515 | 539 | PB4 COL 4 |
516 | 540 | PB5 COL 5 |
517 | 541 | PB6 COL 6 |
518 | | PB7 COL 7, JOY 3 |
| 542 | PB7 COL 7, JOY 3 (RIGHT) |
519 | 543 | |
520 | 544 | */ |
521 | 545 | |
522 | 546 | UINT8 data = 0xff; |
523 | 547 | |
524 | 548 | // joystick |
525 | | data &= ~(ioport("JOY")->read() & 0x80); |
| 549 | UINT8 joy = m_joy1->joy_r(); |
| 550 | |
| 551 | data &= BIT(joy, 3) << 7; |
526 | 552 | |
527 | 553 | return data; |
528 | 554 | } |
r17678 | r17679 | |
540 | 566 | PB4 COL 4 |
541 | 567 | PB5 COL 5 |
542 | 568 | PB6 COL 6 |
543 | | PB7 COL 7, JOY 3 |
| 569 | PB7 COL 7 |
544 | 570 | |
545 | 571 | */ |
546 | 572 | |
r17678 | r17679 | |
611 | 637 | // mos6560_interface vic_ntsc_intf |
612 | 638 | //------------------------------------------------- |
613 | 639 | |
614 | | #define VC20ADDR2MOS6560ADDR(a) (((a) > 0x8000) ? ((a) & 0x1fff) : ((a) | 0x2000)) |
615 | | #define MOS6560ADDR2VC20ADDR(a) (((a) > 0x2000) ? ((a) & 0x1fff) : ((a) | 0x8000)) |
616 | | |
617 | | READ8_MEMBER( vic20_state::vic_dma_read_color ) |
| 640 | static MOS6560_INTERFACE( vic_intf ) |
618 | 641 | { |
619 | | return m_color_ram[offset & 0x3ff]; |
620 | | } |
621 | | |
622 | | READ8_MEMBER( vic20_state::vic_dma_read ) |
623 | | { |
624 | | address_space *program = m_maincpu->memory().space(AS_PROGRAM); |
625 | | |
626 | | return program->read_byte(MOS6560ADDR2VC20ADDR(offset)); |
627 | | } |
628 | | |
629 | | READ8_MEMBER( vic20_state::vic_lightx_cb ) |
630 | | { |
631 | | return (ioport("LIGHTX")->read_safe(0) & ~0x01); |
632 | | } |
633 | | |
634 | | READ8_MEMBER( vic20_state::vic_lighty_cb ) |
635 | | { |
636 | | return (ioport("LIGHTY")->read_safe(0) & ~0x01); |
637 | | } |
638 | | |
639 | | READ8_MEMBER( vic20_state::vic_lightbut_cb ) |
640 | | { |
641 | | return (((ioport("CTRLSEL")->read() & 0xf0) == 0x20) && (ioport("JOY")->read() & 0x40)); |
642 | | } |
643 | | |
644 | | static const mos6560_interface vic_ntsc_intf = |
645 | | { |
646 | 642 | SCREEN_TAG, |
647 | | MOS6560, |
648 | | DEVCB_DRIVER_MEMBER(vic20_state, vic_lightx_cb), |
649 | | DEVCB_DRIVER_MEMBER(vic20_state, vic_lighty_cb), |
650 | | DEVCB_DRIVER_MEMBER(vic20_state, vic_lightbut_cb), |
651 | | DEVCB_INPUT_PORT("PADDLE0"), |
652 | | DEVCB_INPUT_PORT("PADDLE1"), |
653 | | DEVCB_DRIVER_MEMBER(vic20_state, vic_dma_read), |
654 | | DEVCB_DRIVER_MEMBER(vic20_state, vic_dma_read_color) |
| 643 | DEVCB_DEVICE_MEMBER(CONTROL1_TAG, vcs_control_port_device, pot_x_r), |
| 644 | DEVCB_DEVICE_MEMBER(CONTROL1_TAG, vcs_control_port_device, pot_y_r) |
655 | 645 | }; |
656 | 646 | |
657 | 647 | |
658 | 648 | //------------------------------------------------- |
659 | | // mos6560_interface vic_pal_intf |
660 | | //------------------------------------------------- |
661 | | |
662 | | static const mos6560_interface vic_pal_intf = |
663 | | { |
664 | | SCREEN_TAG, |
665 | | MOS6561, |
666 | | DEVCB_DRIVER_MEMBER(vic20_state, vic_lightx_cb), |
667 | | DEVCB_DRIVER_MEMBER(vic20_state, vic_lighty_cb), |
668 | | DEVCB_DRIVER_MEMBER(vic20_state, vic_lightbut_cb), |
669 | | DEVCB_INPUT_PORT("PADDLE0"), |
670 | | DEVCB_INPUT_PORT("PADDLE1"), |
671 | | DEVCB_DRIVER_MEMBER(vic20_state, vic_dma_read), |
672 | | DEVCB_DRIVER_MEMBER(vic20_state, vic_dma_read_color) |
673 | | }; |
674 | | |
675 | | |
676 | | //------------------------------------------------- |
677 | 649 | // VIC20_EXPANSION_INTERFACE( expansion_intf ) |
678 | 650 | //------------------------------------------------- |
679 | 651 | |
r17678 | r17679 | |
699 | 671 | |
700 | 672 | static VIC20_USER_PORT_INTERFACE( user_intf ) |
701 | 673 | { |
| 674 | DEVCB_DEVICE_LINE_MEMBER(M6560_TAG, mos6560_device, lp_w), |
702 | 675 | DEVCB_DEVICE_LINE_MEMBER(M6522_0_TAG, via6522_device, write_cb1), |
703 | 676 | DEVCB_DEVICE_LINE_MEMBER(M6522_0_TAG, via6522_device, write_cb2), |
704 | 677 | DEVCB_DRIVER_LINE_MEMBER(vic20_state, exp_reset_w) |
r17678 | r17679 | |
721 | 694 | m_kernal = memregion("kernal")->base(); |
722 | 695 | m_charom = memregion("charom")->base(); |
723 | 696 | |
724 | | // allocate memory |
725 | | m_color_ram = auto_alloc_array(machine(), UINT8, 0x400); |
726 | | |
727 | 697 | // state saving |
728 | 698 | save_item(NAME(m_key_col)); |
729 | 699 | } |
r17678 | r17679 | |
752 | 722 | // MACHINE_CONFIG( vic20_common ) |
753 | 723 | //------------------------------------------------- |
754 | 724 | |
755 | | static MACHINE_CONFIG_START( vic20_common, vic20_state ) |
| 725 | static MACHINE_CONFIG_START( vic20, vic20_state ) |
756 | 726 | // devices |
757 | 727 | MCFG_VIA6522_ADD(M6522_0_TAG, 0, via0_intf) |
758 | 728 | MCFG_VIA6522_ADD(M6522_1_TAG, 0, via1_intf) |
r17678 | r17679 | |
762 | 732 | MCFG_PET_DATASSETTE_PORT_ADD(PET_DATASSETTE_PORT_TAG, datassette_intf, cbm_datassette_devices, "c1530", NULL) |
763 | 733 | MCFG_CBM_IEC_ADD(cbm_iec_intf, "c1541") |
764 | 734 | |
765 | | MCFG_VCS_CONTROL_PORT_ADD(CONTROL1_TAG, vic20_control_port_devices, NULL, NULL) |
766 | | MCFG_VCS_CONTROL_PORT_ADD(CONTROL2_TAG, vic20_control_port_devices, NULL, NULL) |
| 735 | MCFG_VCS_CONTROL_PORT_ADD(CONTROL1_TAG, vcs_control_port_devices, NULL, NULL) |
767 | 736 | MCFG_VIC20_USER_PORT_ADD(VIC20_USER_PORT_TAG, user_intf, vic20_user_port_cards, NULL, NULL) |
768 | 737 | |
769 | 738 | // software lists |
r17678 | r17679 | |
777 | 746 | |
778 | 747 | |
779 | 748 | //------------------------------------------------- |
780 | | // MACHINE_CONFIG( vic20_ntsc ) |
| 749 | // MACHINE_CONFIG( ntsc ) |
781 | 750 | //------------------------------------------------- |
782 | 751 | |
783 | | static MACHINE_CONFIG_DERIVED( vic20_ntsc, vic20_common ) |
| 752 | static MACHINE_CONFIG_DERIVED( ntsc, vic20 ) |
784 | 753 | // basic machine hardware |
785 | 754 | MCFG_CPU_ADD(M6502_TAG, M6502, MOS6560_CLOCK) |
786 | 755 | MCFG_CPU_PROGRAM_MAP(vic20_mem) |
r17678 | r17679 | |
788 | 757 | |
789 | 758 | // video/sound hardware |
790 | 759 | MCFG_SPEAKER_STANDARD_MONO("mono") |
791 | | MCFG_MOS6560_ADD(M6560_TAG, SCREEN_TAG, MOS6560_CLOCK, vic_ntsc_intf) |
| 760 | MCFG_MOS6560_ADD(M6560_TAG, SCREEN_TAG, MOS6560_CLOCK, vic_intf, vic_videoram_map, vic_colorram_map) |
792 | 761 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
793 | 762 | MCFG_SOUND_ADD("dac", DAC, 0) |
794 | 763 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
r17678 | r17679 | |
803 | 772 | |
804 | 773 | |
805 | 774 | //------------------------------------------------- |
806 | | // MACHINE_CONFIG( vic20_pal ) |
| 775 | // MACHINE_CONFIG( pal ) |
807 | 776 | //------------------------------------------------- |
808 | 777 | |
809 | | static MACHINE_CONFIG_DERIVED( vic20_pal, vic20_common ) |
| 778 | static MACHINE_CONFIG_DERIVED( pal, vic20 ) |
810 | 779 | // basic machine hardware |
811 | 780 | MCFG_CPU_ADD(M6502_TAG, M6502, MOS6561_CLOCK) |
812 | 781 | MCFG_CPU_PROGRAM_MAP(vic20_mem) |
r17678 | r17679 | |
814 | 783 | |
815 | 784 | // video/sound hardware |
816 | 785 | MCFG_SPEAKER_STANDARD_MONO("mono") |
817 | | MCFG_MOS6561_ADD(M6560_TAG, SCREEN_TAG, MOS6561_CLOCK, vic_pal_intf) |
| 786 | MCFG_MOS6561_ADD(M6560_TAG, SCREEN_TAG, MOS6561_CLOCK, vic_intf, vic_videoram_map, vic_colorram_map) |
818 | 787 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
819 | 788 | MCFG_SOUND_ADD("dac", DAC, 0) |
820 | 789 | MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.25) |
r17678 | r17679 | |
908 | 877 | // GAME DRIVERS |
909 | 878 | //************************************************************************** |
910 | 879 | |
911 | | // YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS |
912 | | COMP( 1980, vic1001, 0, 0, vic20_ntsc, vic1001, driver_device, 0, "Commodore Business Machines", "VIC-1001 (Japan)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |
913 | | COMP( 1981, vic20, vic1001, 0, vic20_ntsc, vic20, driver_device, 0, "Commodore Business Machines", "VIC-20 (NTSC)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |
914 | | COMP( 1981, vic20p, vic1001, 0, vic20_pal, vic20, driver_device, 0, "Commodore Business Machines", "VIC-20 / VC-20 (PAL)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |
915 | | COMP( 1981, vic20s, vic1001, 0, vic20_pal, vic20s, driver_device, 0, "Commodore Business Machines", "VIC-20 (Sweden/Finland)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |
| 880 | // YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS |
| 881 | COMP( 1980, vic1001, 0, 0, ntsc, vic1001, driver_device, 0, "Commodore Business Machines", "VIC-1001 (Japan)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |
| 882 | COMP( 1981, vic20, vic1001, 0, ntsc, vic20, driver_device, 0, "Commodore Business Machines", "VIC-20 (NTSC)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |
| 883 | COMP( 1981, vic20p, vic1001, 0, pal, vic20, driver_device, 0, "Commodore Business Machines", "VIC-20 / VC-20 (PAL)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |
| 884 | COMP( 1981, vic20s, vic1001, 0, pal, vic20s, driver_device, 0, "Commodore Business Machines", "VIC-20 (Sweden/Finland)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |