~ubuntu-branches/ubuntu/raring/vice/raring

« back to all changes in this revision

Viewing changes to src/c64dtv/c64dtvblitter.c

  • Committer: Bazaar Package Importer
  • Author(s): Laszlo Boszormenyi (GCS)
  • Date: 2009-03-31 00:37:15 UTC
  • mfrom: (1.1.7 upstream) (9.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20090331003715-i5yisvcfv7mgz3eh
Tags: 2.1.dfsg-1
* New major upstream release (closes: #495937).
* Add desktop files (closes: #501181).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * c64dtvblitter.c - C64DTV blitter and DMA controller
 
3
 *
 
4
 * Written by
 
5
 *  M.Kiesel <mayne@users.sourceforge.net>
 
6
 *  Hannu Nuotio <hannu.nuotio@tut.fi>
 
7
 *  Daniel Kahlin <daniel@kahlin.net>
 
8
 * Based on code by
 
9
 *  Marco van den Heuvel <blackystardust68@yahoo.com>
 
10
 *
 
11
 * This file is part of VICE, the Versatile Commodore Emulator.
 
12
 * See README for copyright notice.
 
13
 *
 
14
 *  This program is free software; you can redistribute it and/or modify
 
15
 *  it under the terms of the GNU General Public License as published by
 
16
 *  the Free Software Foundation; either version 2 of the License, or
 
17
 *  (at your option) any later version.
 
18
 *
 
19
 *  This program is distributed in the hope that it will be useful,
 
20
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
21
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
22
 *  GNU General Public License for more details.
 
23
 *
 
24
 *  You should have received a copy of the GNU General Public License
 
25
 *  along with this program; if not, write to the Free Software
 
26
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 
27
 *  02111-1307  USA.
 
28
 *
 
29
 */
 
30
 
 
31
#include "vice.h"
 
32
 
 
33
#include <string.h>
 
34
 
 
35
#include "c64mem.h"
 
36
#include "c64dtvmem.h"
 
37
#include "c64dtvflash.h"
 
38
#include "c64dtvblitter.h"
 
39
#include "c64dtvdma.h"
 
40
#include "vicii-mem.h"
 
41
#include "cmdline.h"
 
42
#include "lib.h"
 
43
#include "log.h"
 
44
#include "util.h"
 
45
#include "resources.h"
 
46
#include "maincpu.h"
 
47
#include "interrupt.h"
 
48
#include "alarm.h"
 
49
#include "snapshot.h"
 
50
#include "translate.h"
 
51
 
 
52
static log_t c64dtvblitter_log = LOG_ERR;
 
53
 
 
54
/* I/O of the blitter engine ($D3XX) */
 
55
BYTE c64dtvmem_blitter[0x20];
 
56
 
 
57
int blit_sourceA_off;
 
58
int blit_sourceB_off;
 
59
int blit_dest_off;
 
60
int blitter_busy;
 
61
int blitter_irq;
 
62
int blitter_on_irq;
 
63
int blitter_log_enabled = 0;
 
64
int blitter_active;
 
65
 
 
66
static BYTE srca_data[4];
 
67
static int srca_data_offs;
 
68
static int srca_fetched;
 
69
static BYTE srcb_data[4];
 
70
static int srcb_data_offs;
 
71
static BYTE sourceA, sourceB;
 
72
static int blitter_count;
 
73
static enum { BLITTER_IDLE, BLITTER_READ_A, BLITTER_READ_B, BLITTER_WRITE } blitter_state;
 
74
static int sourceA_line_off;
 
75
static int sourceB_line_off;
 
76
static int dest_line_off;
 
77
static BYTE lastA;
 
78
 
 
79
 
 
80
/* resource stuff */
 
81
static int dtvrevision;
 
82
static int have_blitter_bug;
 
83
 
 
84
 
 
85
#define GET_REG24(a) ((c64dtvmem_blitter[a+2]<<16) | (c64dtvmem_blitter[a+1]<<8) | c64dtvmem_blitter[a])
 
86
#define GET_REG16(a) ((c64dtvmem_blitter[a+1]<<8) | c64dtvmem_blitter[a])
 
87
#define GET_REG8(a) (c64dtvmem_blitter[a])
 
88
 
 
89
 
 
90
/* ------------------------------------------------------------------------- */
 
91
 
 
92
void c64dtvblitter_init(void)
 
93
{
 
94
    if(c64dtvblitter_log == LOG_ERR)
 
95
        c64dtvblitter_log = log_open("C64DTVBLITTER");
 
96
 
 
97
    /* init Blitter IRQ */
 
98
    c64dtv_blitter_irq_init();
 
99
}
 
100
 
 
101
 
 
102
void c64dtvblitter_shutdown(void)
 
103
{
 
104
}
 
105
 
 
106
void c64dtvblitter_reset(void)
 
107
{
 
108
    int i;
 
109
    if(blitter_log_enabled) log_message(c64dtvblitter_log, "reset");
 
110
    /* TODO move register file initialization somewhere else? */
 
111
    for (i=0;i<0x20;++i) c64dtvmem_blitter[i] = 0;
 
112
 
 
113
    c64dtvmem_blitter[0x07] = 0x10;
 
114
    c64dtvmem_blitter[0x0f] = 0x10;
 
115
    c64dtvmem_blitter[0x17] = 0x10;
 
116
 
 
117
    blit_sourceA_off = 0;
 
118
    blit_sourceB_off = 0;
 
119
    blit_dest_off = 0;
 
120
    blitter_busy = 0;
 
121
    blitter_irq = 0;
 
122
    blitter_on_irq = 0;
 
123
    blitter_active = 0;
 
124
 
 
125
    blitter_count = 0;
 
126
    blitter_state = BLITTER_IDLE;
 
127
    srca_data_offs = -1;
 
128
    srcb_data_offs = -1;
 
129
    srca_fetched = 0;
 
130
    sourceA = 0;
 
131
    lastA = 0;
 
132
    sourceB = 0;
 
133
    sourceA_line_off = 0;
 
134
    sourceB_line_off = 0;
 
135
    dest_line_off = 0;
 
136
}
 
137
 
 
138
/* ------------------------------------------------------------------------- */
 
139
/* blitter transfer state machine */
 
140
 
 
141
static int do_blitter_read_a(void)
 
142
{
 
143
    int was_read = 0;
 
144
    int offs  = (blit_sourceA_off >> 4) & 0x1ffffc;
 
145
    int loffs = (blit_sourceA_off >> 4) & 0x000003;
 
146
 
 
147
    srca_fetched = 0;
 
148
    if (offs != srca_data_offs) {
 
149
        memcpy(srca_data, &mem_ram[offs], 4);
 
150
        srca_data_offs = offs;
 
151
        srca_fetched = 1;
 
152
        was_read = 1;
 
153
    }
 
154
    sourceA = srca_data[loffs];
 
155
    return was_read;
 
156
}
 
157
 
 
158
static int do_blitter_read_b(void)
 
159
{
 
160
    int force_sourceB_zero = GET_REG8(0x1b) & 0x01;
 
161
 
 
162
    int was_read = 0;
 
163
    int offs  = (blit_sourceB_off >> 4) & 0x1ffffc;
 
164
    int loffs = (blit_sourceB_off >> 4) & 0x000003;
 
165
 
 
166
    if (force_sourceB_zero) {
 
167
        sourceB = 0;
 
168
        return 0;
 
169
    }
 
170
 
 
171
    if (offs != srcb_data_offs) {
 
172
        memcpy(srcb_data, &mem_ram[offs], 4);
 
173
        srcb_data_offs = offs;
 
174
        was_read = 1;
 
175
    }
 
176
    sourceB = srcb_data[loffs];
 
177
    return was_read;
 
178
}
 
179
 
 
180
 
 
181
static int do_blitter_write(void)
 
182
{
 
183
    int sourceA_right_shift = GET_REG8(0x1e) & 0x07;
 
184
    int mintermALU = (GET_REG8(0x1e) >> 3) & 0x07;
 
185
    int write_if_sourceA_zero = GET_REG8(0x1b) & 0x02;
 
186
    int write_if_sourceA_nonzero = GET_REG8(0x1b) & 0x04;
 
187
 
 
188
    int was_write = 0;
 
189
    int offs  = (blit_dest_off >> 4) & 0x1fffff;
 
190
 
 
191
 
 
192
    if(!(write_if_sourceA_zero || write_if_sourceA_nonzero)) {
 
193
        write_if_sourceA_zero = write_if_sourceA_nonzero = 1;
 
194
    }
 
195
        
 
196
    if ( (write_if_sourceA_zero    && sourceA == 0) ||
 
197
         (write_if_sourceA_nonzero && sourceA != 0) ||
 
198
         (have_blitter_bug && srca_fetched) ) {
 
199
        BYTE dest;
 
200
        BYTE lastA_tmp = sourceA;
 
201
        sourceA >>= sourceA_right_shift;
 
202
        sourceA |= lastA << (8 - sourceA_right_shift);
 
203
        lastA = lastA_tmp;
 
204
 
 
205
        dest = 0;
 
206
        switch(mintermALU) {
 
207
        case 0: dest = sourceA & sourceB; break;
 
208
        case 1: dest = ~(sourceA & sourceB); break;
 
209
        case 2: dest = ~(sourceA | sourceB); break;
 
210
        case 3: dest = sourceA | sourceB; break;
 
211
        case 4: dest = sourceA ^ sourceB; break;
 
212
        case 5: dest = ~(sourceA ^ sourceB); break;
 
213
        case 6: dest = sourceA + sourceB; break;
 
214
        case 7: dest = sourceA - sourceB; break;
 
215
        default:
 
216
            break;
 
217
        }
 
218
        mem_ram[offs] = dest;
 
219
        was_write = 1;
 
220
    }
 
221
    if(blitter_log_enabled) log_message(c64dtvblitter_log, "Blitter: %s %x.%x/%x.%x to %x.%x, %d to go, minterm %d", was_write ? "transferred" : "skipped", blit_sourceA_off >> 4, blit_sourceA_off & 15, blit_sourceB_off >> 4, blit_sourceB_off & 15, blit_dest_off >> 4, blit_dest_off & 15, blitter_count - 1, mintermALU);
 
222
    return was_write;
 
223
}
 
224
 
 
225
static void update_counters(void)
 
226
{
 
227
    int sourceA_modulo = GET_REG16(0x03);
 
228
    int sourceA_line_length = GET_REG16(0x05);
 
229
    int sourceA_step = GET_REG8(0x07);
 
230
    int sourceB_modulo = GET_REG16(0x0b);
 
231
    int sourceB_line_length = GET_REG16(0x0d);
 
232
    int sourceB_step = GET_REG8(0x0f);
 
233
    int dest_modulo = GET_REG16(0x13);
 
234
    int dest_line_length = GET_REG16(0x15);
 
235
    int dest_step = GET_REG8(0x17);
 
236
    int sourceA_direction = (GET_REG8(0x1a)&0x02) ? +1 : -1;
 
237
    int sourceB_direction = (GET_REG8(0x1a)&0x04) ? +1 : -1;
 
238
    int dest_direction = (GET_REG8(0x1a)&0x08) ? +1 : -1;
 
239
 
 
240
    if(sourceA_line_off >= sourceA_line_length) {
 
241
        lastA = 0;
 
242
        sourceA_line_off = 0;
 
243
        blit_sourceA_off = ((blit_sourceA_off >> 4) + sourceA_modulo * sourceA_direction) << 4;
 
244
    } else {
 
245
        sourceA_line_off++;
 
246
        blit_sourceA_off += sourceA_step * sourceA_direction;
 
247
    }
 
248
    if(sourceB_line_off >= sourceB_line_length) {
 
249
        sourceB_line_off = 0;
 
250
        blit_sourceB_off = ((blit_sourceB_off >> 4) + sourceB_modulo * sourceB_direction) << 4;
 
251
    } else {
 
252
        sourceB_line_off++;
 
253
        blit_sourceB_off += sourceB_step * sourceB_direction;
 
254
    }
 
255
    if(dest_line_off >= dest_line_length) {
 
256
        dest_line_off = 0;
 
257
        blit_dest_off = ((blit_dest_off >> 4) + dest_modulo * dest_direction) << 4;
 
258
    } else {
 
259
        dest_line_off++;
 
260
        blit_dest_off += dest_step * dest_direction;
 
261
    }
 
262
}
 
263
 
 
264
/* 32 MHz processing clock */
 
265
#define SUBCYCLES 32
 
266
static void perform_blitter_cycle(void)
 
267
{
 
268
    int subcycle = 0;
 
269
    while (subcycle < SUBCYCLES) {
 
270
        switch (blitter_state) {
 
271
        case BLITTER_IDLE:
 
272
            subcycle += SUBCYCLES;
 
273
            break;
 
274
        case BLITTER_READ_A:
 
275
            if (blitter_count == 0) {
 
276
                blitter_state = BLITTER_IDLE;
 
277
                break;
 
278
            }
 
279
 
 
280
            if ( do_blitter_read_a() )
 
281
                subcycle += SUBCYCLES;
 
282
            blitter_state=BLITTER_READ_B;
 
283
            break;
 
284
        case BLITTER_READ_B:
 
285
            if ( do_blitter_read_b() )
 
286
                subcycle += SUBCYCLES;
 
287
            blitter_state=BLITTER_WRITE;
 
288
            break;
 
289
        case BLITTER_WRITE:
 
290
            if ( do_blitter_write() )
 
291
                subcycle += SUBCYCLES;
 
292
            else
 
293
                subcycle += 1;
 
294
 
 
295
            update_counters();
 
296
            blitter_count--;
 
297
 
 
298
            if (blitter_count==0)
 
299
                blitter_state=BLITTER_IDLE;
 
300
            else
 
301
                blitter_state=BLITTER_READ_A;
 
302
            break;
 
303
        default:
 
304
            log_message(c64dtvblitter_log, "invalid state in perform_blitter_cycle()");
 
305
            blitter_state=BLITTER_IDLE;
 
306
            break;
 
307
        }
 
308
    }
 
309
}
 
310
 
 
311
 
 
312
/* ------------------------------------------------------------------------- */
 
313
 
 
314
/* These are the $D3xx Blitter register engine handlers */
 
315
 
 
316
/* Blitter IRQ code */
 
317
 
 
318
static unsigned int c64dtv_blitter_int_num;
 
319
struct alarm_s *c64dtv_blitter_irq_alarm;
 
320
 
 
321
void c64dtvblitter_trigger_blitter(void)
 
322
{
 
323
    if(!blitter_active) {
 
324
        int sourceA_continue = GET_REG8(0x1f) & 0x02;
 
325
        int sourceB_continue = GET_REG8(0x1f) & 0x04;
 
326
        int dest_continue = GET_REG8(0x1f) & 0x08;
 
327
 
 
328
        /* last four bits of offsets are fractional */
 
329
        if(!sourceA_continue) {
 
330
            blit_sourceA_off = GET_REG24(0x00) & 0x3fffff;
 
331
            blit_sourceA_off <<= 4;
 
332
        }
 
333
        if(!sourceB_continue) {
 
334
            blit_sourceB_off = GET_REG24(0x08) & 0x3fffff;
 
335
            blit_sourceB_off <<= 4;
 
336
        }
 
337
        if(!dest_continue) {
 
338
            blit_dest_off = GET_REG24(0x10) & 0x3fffff;
 
339
            blit_dest_off <<= 4;
 
340
        }
 
341
 
 
342
        if(blitter_log_enabled && (sourceA_continue || sourceB_continue || dest_continue)) {
 
343
            log_message(c64dtvblitter_log, "sourceA cont %s, sourceB cont %s, dest cont %s", sourceA_continue ? "on" : "off", sourceB_continue ? "on" : "off", dest_continue ? "on" : "off");
 
344
        }
 
345
 
 
346
        /* total number of bytes to transfer */
 
347
        blitter_count = GET_REG16(0x18);
 
348
 
 
349
        /* initialize state variables */
 
350
        sourceA_line_off = 0;
 
351
        sourceB_line_off = 0;
 
352
        dest_line_off = 0;
 
353
        lastA = 0;
 
354
        srca_data_offs = -1;
 
355
        srcb_data_offs = -1;
 
356
 
 
357
        blitter_state = BLITTER_READ_A;
 
358
 
 
359
#ifndef CYCLE_EXACT_BLITTER
 
360
        int blitter_time = 0;
 
361
 
 
362
        do {
 
363
            perform_blitter_cycle();
 
364
            blitter_time++;
 
365
        } while (blitter_state != BLITTER_IDLE);
 
366
 
 
367
        alarm_set(c64dtv_blitter_irq_alarm, maincpu_clk+blitter_time);
 
368
#endif
 
369
 
 
370
        if (GET_REG8(0x1a) & 0x80) {
 
371
            blitter_irq = 1;
 
372
        } else blitter_irq = 0;
 
373
 
 
374
        blitter_busy = 1;
 
375
        blitter_active = 1;
 
376
    }
 
377
}
 
378
 
 
379
void c64dtv_blitter_irq_alarm_handler(CLOCK offset, void *data)
 
380
{
 
381
    if(blitter_log_enabled) log_message(c64dtvblitter_log, "IRQ/Done");
 
382
    if(blitter_irq) {
 
383
        maincpu_set_irq(c64dtv_blitter_int_num, 1);
 
384
        blitter_busy = 2;
 
385
    }
 
386
    alarm_unset(c64dtv_blitter_irq_alarm);
 
387
    blitter_busy &= 0xfe;
 
388
    blitter_active = 0;
 
389
 
 
390
    /* Scheduled DMA */
 
391
    if (dma_on_irq & 0x20) {
 
392
        c64dtvdma_trigger_dma();
 
393
    }
 
394
}
 
395
 
 
396
void c64dtv_blitter_irq_init(void)
 
397
{
 
398
    c64dtv_blitter_int_num = interrupt_cpu_status_int_new(maincpu_int_status, "C64DTVBLITTER");
 
399
 
 
400
    c64dtv_blitter_irq_alarm = alarm_new(maincpu_alarm_context, "C64DTVBLITTERIrq",
 
401
                                         c64dtv_blitter_irq_alarm_handler, NULL);
 
402
}
 
403
 
 
404
 
 
405
void c64dtv_blitter_store(WORD addr, BYTE value)
 
406
{
 
407
    /* Store first, then check whether DMA access has been requested,
 
408
       perform if necessary. */
 
409
    c64dtvmem_blitter[addr] = value;
 
410
 
 
411
    /* Blitter code */
 
412
    blitter_on_irq = GET_REG8(0x1a)&0x70;
 
413
  
 
414
    /* Clear Blitter IRQ */
 
415
    if((GET_REG8(0x1f)&0x01) && (blitter_busy==2)){
 
416
        if(blitter_log_enabled) log_message(c64dtvblitter_log, "Clear IRQ (%i)", blitter_busy);
 
417
        blitter_busy &= 0xfd;
 
418
        maincpu_set_irq(c64dtv_blitter_int_num, 0);
 
419
        blitter_irq = 0;
 
420
        /* reset clear IRQ strobe bit */
 
421
        c64dtvmem_blitter[0x1f] &= 0xfe;
 
422
    }
 
423
  
 
424
    if(blitter_on_irq && (blitter_busy==0)) {
 
425
        blitter_busy = 1;
 
426
        if(blitter_log_enabled) log_message(c64dtvblitter_log, "Scheduled Blitter (%02x)", blitter_on_irq);
 
427
        return;
 
428
    }
 
429
 
 
430
    /* Force Blitter start */
 
431
    if(GET_REG8(0x1a)&0x01) {
 
432
        c64dtvblitter_trigger_blitter();
 
433
        /* reset force start strobe bit */
 
434
        c64dtvmem_blitter[0x1a] &= 0xfe;
 
435
    }
 
436
}
 
437
 
 
438
 
 
439
int c64dtvblitter_perform_blitter(void)
 
440
{
 
441
#ifdef CYCLE_EXACT_BLITTER
 
442
    if(blitter_active) {
 
443
        perform_blitter_cycle();
 
444
 
 
445
        if(blitter_state == BLITTER_IDLE) {
 
446
            c64dtv_blitter_irq_alarm_handler(0, NULL);
 
447
        }
 
448
        return 1;
 
449
    }
 
450
#endif
 
451
    return 0;
 
452
}
 
453
 
 
454
 
 
455
/* ------------------------------------------------------------------------- */
 
456
 
 
457
/* These are called on read/writes to $D3xx */
 
458
 
 
459
BYTE REGPARM1 c64dtv_dmablit_read(WORD addr)
 
460
{
 
461
    if (!vicii_extended_regs())
 
462
        return vicii_read(addr);
 
463
 
 
464
    if((addr&0xff)==0x1f)
 
465
        return dma_busy;
 
466
    if((addr&0xff)==0x3f)
 
467
        return blitter_busy;
 
468
    /* the default return value is 0x00 too but I have seen some strangeness
 
469
       here.  I've seen something that looks like DMAed data. - tlr */
 
470
    return 0x00;
 
471
}
 
472
 
 
473
 
 
474
void REGPARM2 c64dtv_dmablit_store(WORD addr, BYTE value)
 
475
{
 
476
    if (!vicii_extended_regs()) {
 
477
        vicii_store(addr, value);
 
478
        return;
 
479
    }
 
480
 
 
481
    addr &= 0x3f;
 
482
  
 
483
    if (addr & 0x20) c64dtv_blitter_store((WORD)(addr & 0x1f), value);
 
484
    else c64dtv_dma_store(addr, value);
 
485
}
 
486
 
 
487
 
 
488
/* ------------------------------------------------------------------------- */
 
489
static int set_dtvrevision(int val, void *param)
 
490
{
 
491
    switch (val) {
 
492
    default:
 
493
    case 3:
 
494
        dtvrevision=3;
 
495
        break;
 
496
    case 2:
 
497
        dtvrevision=2;
 
498
        break;
 
499
    }
 
500
    have_blitter_bug = (dtvrevision == 2) ? 1 : 0;
 
501
    return 1;
 
502
}
 
503
 
 
504
static int set_blitter_log(int val, void *param)
 
505
{
 
506
    blitter_log_enabled = val;
 
507
    return 0;
 
508
}
 
509
 
 
510
static const resource_int_t resources_int[] = {
 
511
    { "DtvRevision", 3, RES_EVENT_SAME, NULL,
 
512
      &dtvrevision, set_dtvrevision, NULL },
 
513
    { "DtvBlitterLog", 0, RES_EVENT_NO, (resource_value_t)0,
 
514
      &blitter_log_enabled, set_blitter_log, NULL },
 
515
    { NULL }
 
516
};
 
517
 
 
518
int c64dtvblitter_resources_init(void)
 
519
{
 
520
    return resources_register_int(resources_int);
 
521
}
 
522
 
 
523
void c64dtvblitter_resources_shutdown(void)
 
524
{
 
525
}
 
526
 
 
527
static const cmdline_option_t cmdline_options[] =
 
528
{
 
529
    { "-dtvrev", SET_RESOURCE, 1,
 
530
      NULL, NULL, "DtvRevision", NULL,
 
531
      USE_PARAM_ID, USE_DESCRIPTION_ID,
 
532
      IDCLS_P_REVISION, IDCLS_SPECIFY_DTV_REVISION,
 
533
      NULL, NULL },
 
534
    { "-dtvblitterlog", SET_RESOURCE, 0,
 
535
      NULL, NULL, "DtvBlitterLog", (resource_value_t)1,
 
536
      USE_PARAM_STRING, USE_DESCRIPTION_ID,
 
537
      IDCLS_UNUSED, IDCLS_ENABLE_DTV_BLITTER_LOG,
 
538
      NULL, NULL },
 
539
    { "+dtvblitterlog", SET_RESOURCE, 0,
 
540
      NULL, NULL, "DtvBlitterLog", (resource_value_t)0,
 
541
      USE_PARAM_STRING, USE_DESCRIPTION_ID,
 
542
      IDCLS_UNUSED, IDCLS_DISABLE_DTV_BLITTER_LOG,
 
543
      NULL, NULL },
 
544
    { NULL }
 
545
};
 
546
 
 
547
int c64dtvblitter_cmdline_options_init(void)
 
548
{
 
549
    return cmdline_register_options(cmdline_options);
 
550
}
 
551
 
 
552
/* ------------------------------------------------------------------------- */
 
553
 
 
554
#define SNAP_MAJOR 0
 
555
#define SNAP_MINOR 0
 
556
 
 
557
static log_t c64_snapshot_log = LOG_ERR;
 
558
 
 
559
static const char snap_blitter_module_name[] = "C64DTVBLITTER";
 
560
 
 
561
int c64dtvblitter_snapshot_write_module(snapshot_t *s)
 
562
{
 
563
    snapshot_module_t *m;
 
564
 
 
565
    /* Blitter module.  */                                                       
 
566
    m = snapshot_module_create(s, snap_blitter_module_name, SNAP_MAJOR, SNAP_MINOR);
 
567
    if (m == NULL)
 
568
        return -1;
 
569
 
 
570
    if (SMW_BA(m, c64dtvmem_blitter, 0x20) < 0
 
571
        || SMW_DW(m, blit_sourceA_off) < 0
 
572
        || SMW_DW(m, blit_sourceB_off) < 0
 
573
        || SMW_DW(m, blit_dest_off) < 0
 
574
        || SMW_DW(m, blitter_busy) < 0
 
575
        || SMW_DW(m, blitter_irq) < 0
 
576
        || SMW_DW(m, blitter_on_irq) < 0
 
577
        || SMW_DW(m, blitter_active) < 0
 
578
        || SMW_BA(m, srca_data, 4) < 0
 
579
        || SMW_DW(m, srca_data_offs) < 0
 
580
        || SMW_DW(m, srca_fetched) < 0
 
581
        || SMW_BA(m, srcb_data, 4) < 0
 
582
        || SMW_DW(m, srcb_data_offs) < 0
 
583
        || SMW_B(m, sourceA) < 0
 
584
        || SMW_B(m, sourceB) < 0
 
585
        || SMW_DW(m, blitter_count) < 0
 
586
        || SMW_DW(m, blitter_state) < 0
 
587
        || SMW_DW(m, sourceA_line_off) < 0
 
588
        || SMW_DW(m, sourceB_line_off) < 0
 
589
        || SMW_DW(m, dest_line_off) < 0
 
590
        || SMW_B(m, lastA) < 0)
 
591
        goto fail;
 
592
 
 
593
    if (snapshot_module_close(m) < 0)
 
594
        goto fail;
 
595
    m = NULL;
 
596
 
 
597
    return 0;
 
598
 
 
599
fail:
 
600
    if (m != NULL)
 
601
        snapshot_module_close(m);
 
602
    return -1;
 
603
}
 
604
 
 
605
 
 
606
int c64dtvblitter_snapshot_read_module(snapshot_t *s)
 
607
{
 
608
    BYTE major_version, minor_version;
 
609
    snapshot_module_t *m;
 
610
    int temp_blitter_state;
 
611
 
 
612
    /* Blitter module.  */
 
613
    m = snapshot_module_open(s, snap_blitter_module_name,
 
614
                             &major_version, &minor_version);
 
615
    if (m == NULL)
 
616
        return -1;
 
617
 
 
618
    if (major_version > SNAP_MAJOR || minor_version > SNAP_MINOR) {
 
619
        log_error(c64_snapshot_log,
 
620
                  "Snapshot module version (%d.%d) newer than %d.%d.",
 
621
                  major_version, minor_version,
 
622
                  SNAP_MAJOR, SNAP_MINOR);
 
623
        goto fail;
 
624
    }
 
625
 
 
626
    if (SMR_BA(m, c64dtvmem_blitter, 0x20) < 0
 
627
        || SMR_DW_INT(m, &blit_sourceA_off) < 0
 
628
        || SMR_DW_INT(m, &blit_sourceB_off) < 0
 
629
        || SMR_DW_INT(m, &blit_dest_off) < 0
 
630
        || SMR_DW_INT(m, &blitter_busy) < 0
 
631
        || SMR_DW_INT(m, &blitter_irq) < 0
 
632
        || SMR_DW_INT(m, &blitter_on_irq) < 0
 
633
        || SMR_DW_INT(m, &blitter_active) < 0
 
634
        || SMR_BA(m, srca_data, 4) < 0
 
635
        || SMR_DW_INT(m, &srca_data_offs) < 0
 
636
        || SMR_DW_INT(m, &srca_fetched) < 0
 
637
        || SMR_BA(m, srcb_data, 4) < 0
 
638
        || SMR_DW_INT(m, &srcb_data_offs) < 0
 
639
        || SMR_B(m, &sourceA) < 0
 
640
        || SMR_B(m, &sourceB) < 0
 
641
        || SMR_DW_INT(m, &blitter_count) < 0
 
642
        || SMR_DW_INT(m, &temp_blitter_state) < 0
 
643
        || SMR_DW_INT(m, &sourceA_line_off) < 0
 
644
        || SMR_DW_INT(m, &sourceB_line_off) < 0
 
645
        || SMR_DW_INT(m, &dest_line_off) < 0
 
646
        || SMR_B(m, &lastA) < 0)
 
647
        goto fail;
 
648
 
 
649
    blitter_state = temp_blitter_state;
 
650
 
 
651
    if (snapshot_module_close(m) < 0)
 
652
        goto fail;
 
653
    m = NULL;
 
654
 
 
655
    return 0;
 
656
 
 
657
fail:
 
658
    if (m != NULL)
 
659
        snapshot_module_close(m);
 
660
    return -1;
 
661
}
 
662