~ubuntu-branches/ubuntu/quantal/vice/quantal

« back to all changes in this revision

Viewing changes to src/c64/reu.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
 
/*
 
1
/*! \file reu.c \n
 
2
 *  \author Andreas Boose, Spiro Trikaliotis, Jouko Valta, Richard Hable, Ettore Perazzoli\n
 
3
 *  \brief   REU emulation.
 
4
 *
2
5
 * reu.c - REU emulation.
3
6
 *
4
7
 * Written by
5
8
 *  Andreas Boose <viceteam@t-online.de>
6
 
 * 
 
9
 *  Spiro Trikaliotis <spiro.trikaliotis@gmx.de>
 
10
 *
 
11
 * Additions upon extensive REU hardware testing:
 
12
 *  Wolfgang Moser <http://d81.de>
 
13
 *
7
14
 * Based on old code by
8
15
 *  Jouko Valta <jopi@stekt.oulu.fi>
9
16
 *  Richard Hable <K3027E7@edvz.uni-linz.ac.at>
31
38
 
32
39
#include "vice.h"
33
40
 
 
41
#include <assert.h>
34
42
#include <stdio.h>
35
43
#include <stdlib.h>
36
44
#include <string.h>
48
56
#include "resources.h"
49
57
#include "reu.h"
50
58
#include "snapshot.h"
51
 
#ifdef HAS_TRANSLATION
52
59
#include "translate.h"
53
 
#endif
54
60
#include "types.h"
55
61
#include "util.h"
56
62
 
57
63
 
58
 
/**
59
 
#define REU_DEBUG
60
 
**/
 
64
#if 0
 
65
#define REU_DEBUG 1 /*!< define this if you want to get debugging output for the REU. */
 
66
#endif
 
67
 
 
68
/*! \brief the debug levels to use when REU_DEBUG is defined */
 
69
enum {
 
70
    DEBUG_LEVEL_NONE = 0,              /*!< do not output debugging information */
 
71
    DEBUG_LEVEL_REGISTER,              /*!< output debugging information concerning the REU registers */
 
72
    DEBUG_LEVEL_TRANSFER_HIGH_LEVEL,   /*!< output debugging information on transfers, on a high-level (per operation) */
 
73
    DEBUG_LEVEL_NO_DRAM,               /*!< output debugging information whenever an address is accessed where no DRAM is available  */
 
74
    DEBUG_LEVEL_TRANSFER_LOW_LEVEL     /*!< output debugging information on transfers, on a low-level (per single byte) */
 
75
} debug_level_e;
 
76
 
 
77
#ifdef REU_DEBUG
 
78
    /*! \brief dynamically define the debugging level */
 
79
    static enum debug_level_e DEBUG_LEVEL = DEBUG_LEVEL_NONE;
 
80
 
 
81
    /*! \brief output debugging information
 
82
      \param _level
 
83
         The debugging level on which this data appears
 
84
 
 
85
      \param _x
 
86
        The complete log_message parameter, including the braces
 
87
    */
 
88
    #define DEBUG_LOG( _level, _x ) do { if ( _level <= (DEBUG_LEVEL) ) { log_message _x; } } while (0)
 
89
 
 
90
#else
 
91
 
 
92
    /*! \brief output debugging information
 
93
      \param _level
 
94
         The debugging level on which this data appears
 
95
 
 
96
      \param _x
 
97
        The complete log_message parameter, including the braces
 
98
 
 
99
      \remark
 
100
        This implementation is the dummy if debugging output is disabled
 
101
    */
 
102
    #define DEBUG_LOG( _level, _x )
 
103
 
 
104
#endif
 
105
 
 
106
/*! \brief Shortcut to check for masked bits being all set */
 
107
#define BITS_ARE_ALL_SET(_where, _bits) \
 
108
  ( (((_where) & (_bits)) == (_bits)) )
 
109
 
 
110
/*! \brief Shortcut to check for masked bits being all cleared */
 
111
#define BITS_ARE_ALL_UNSET(_where, _bits) \
 
112
  ( (((_where) & (_bits)) == 0) )
61
113
 
62
114
/*
63
115
 * Status and Command Registers
66
118
 * 01   Exec    0       Load    Delayed 0       0          Mode
67
119
 */
68
120
 
69
 
/*
70
 
 Offsets of the different REU registers
71
 
*/
72
 
#define REU_REG_R_STATUS         0x00
73
 
#define REU_REG_W_COMMAND        0x01
74
 
#define REU_REG_RW_BASEADDR_LOW  0x02
75
 
#define REU_REG_RW_BASEADDR_HIGH 0x03
76
 
#define REU_REG_RW_RAMADDR_LOW   0x04
77
 
#define REU_REG_RW_RAMADDR_HIGH  0x05
78
 
#define REU_REG_RW_BANK          0x06
79
 
#define REU_REG_RW_BLOCKLEN_LOW  0x07
80
 
#define REU_REG_RW_BLOCKLEN_HIGH 0x08
81
 
#define REU_REG_RW_INTERRUPT     0x09
82
 
#define REU_REG_RW_ADDRCONTROL   0x0A
 
121
/*! \brief Offsets of the different REU registers */
 
122
enum {
 
123
    REU_REG_R_STATUS         = 0x00, /*!< the REU status register */
 
124
    REU_REG_RW_COMMAND       = 0x01, /*!< the REU command register */
 
125
    REU_REG_RW_BASEADDR_LOW  = 0x02, /*!< the REU base low address register (computer side) */
 
126
    REU_REG_RW_BASEADDR_HIGH = 0x03, /*!< the REU base high address register (computer side) */
 
127
    REU_REG_RW_RAMADDR_LOW   = 0x04, /*!< the REU RAM low address register (expansion side) */
 
128
    REU_REG_RW_RAMADDR_HIGH  = 0x05, /*!< the REU RAM high address register (expansion side) */
 
129
    REU_REG_RW_BANK          = 0x06, /*!< the REU RAM bank address register (expansion side) */
 
130
    REU_REG_RW_BLOCKLEN_LOW  = 0x07, /*!< the REU transfer length low register */
 
131
    REU_REG_RW_BLOCKLEN_HIGH = 0x08, /*!< the REU transfer length high register */
 
132
    REU_REG_RW_INTERRUPT     = 0x09, /*!< the REU interrupt register */
 
133
    REU_REG_RW_ADDR_CONTROL  = 0x0A, /*!< the REU address register */
 
134
    REU_REG_RW_UNUSED        = 0x0B, /*!< the first unused REU address. The unused area fills up to REU_REG_LAST_REG */
 
135
    REU_REG_LAST_REG         = 0x1F  /*!< the last register of the REU */
 
136
};
 
137
 
 
138
/*! \brief bit definitions for the REU status register at offset REU_REG_R_STATUS */
 
139
enum {
 
140
    REU_REG_R_STATUS_CHIPVERSION_MASK  = 0x0F, /*!< bit mask the extract the chip version no. */
 
141
    REU_REG_R_STATUS_256K_CHIPS        = 0x10, /*!< set if 256K DRAMs (256Kx1) are used (1764, 1750), if unset, 64K DRAMs (64Kx1) are used (1700) */
 
142
    REU_REG_R_STATUS_VERIFY_ERROR      = 0x20, /*!< set if an verify error occurred. Cleared on read. */
 
143
    REU_REG_R_STATUS_END_OF_BLOCK      = 0x40, /*!< set of the operation ended. Cleared on read. */
 
144
    REU_REG_R_STATUS_INTERRUPT_PENDING = 0x80  /*!< set if an interrupt is pending. Cleared on read. */
 
145
};
 
146
 
 
147
/*! \brief bit definitions for the REU command register at offset REU_REG_RW_COMMAND */
 
148
enum {
 
149
    REU_REG_RW_COMMAND_TRANSFER_TYPE_MASK    = 0x03,    /*!< bit mask to extract the transfer type */
 
150
    REU_REG_RW_COMMAND_TRANSFER_TYPE_TO_REU     = 0x00, /*!< transfer type is C64 -> REU */
 
151
    REU_REG_RW_COMMAND_TRANSFER_TYPE_FROM_REU   = 0x01, /*!< transfer type is REU -> C64 */
 
152
    REU_REG_RW_COMMAND_TRANSFER_TYPE_SWAP       = 0x02, /*!< transfer type is swap between C64 and REU */
 
153
    REU_REG_RW_COMMAND_TRANSFER_TYPE_VERIFY     = 0x03, /*!< transfer type is verify between C64 and REU */
 
154
    REU_REG_RW_COMMAND_RESERVED_MASK         = 0x4C,    /*!< the bits defined here are writeable, but unused */
 
155
    REU_REG_RW_COMMAND_FF00_TRIGGER_DISABLED = 0x10,    /*!< if set, $FF00 trigger is disabled. */
 
156
    REU_REG_RW_COMMAND_AUTOLOAD              = 0x20,    /*!< if set, the address registers should be autoloaded after an operation */
 
157
    REU_REG_RW_COMMAND_EXECUTE               = 0x80     /*!< is set, the specified operation should start. */
 
158
};
 
159
 
 
160
/*! \brief bit definitions for the REU bank register at offset REU_REG_RW_BANK */
 
161
enum {
 
162
    REU_REG_RW_BANK_UNUSED = 0xF8  /*!< these bits are unused and always read as 1 */
 
163
};
 
164
 
 
165
/*! \brief bit definitions for the REU interrupt register at offset REU_REG_RW_INTERRUPT */
 
166
enum {
 
167
    REU_REG_RW_INTERRUPT_UNUSED_MASK          = 0x1F, /*!< these bits are unused and always read as 1 */
 
168
    REU_REG_RW_INTERRUPT_VERIFY_ENABLED       = 0x20, /*!< if set (and REU_REG_RW_INTERRUPT_INTERRUPTS_ENABLED is set, too), generate an interrupt if verify fails */
 
169
    REU_REG_RW_INTERRUPT_END_OF_BLOCK_ENABLED = 0x40, /*!< if set (and REU_REG_RW_INTERRUPT_INTERRUPTS_ENABLED is set, too), generate an interrupt if operation finished */
 
170
    REU_REG_RW_INTERRUPT_INTERRUPTS_ENABLED   = 0x80  /*!< is set, the REU can generate an interrupt. If unset, no interrupts can be generated */
 
171
};
 
172
 
 
173
/*! \brief bit definitions for the REU address control register at offset REU_REG_RW_ADDR_CONTROL */
 
174
enum {
 
175
    REU_REG_RW_ADDR_CONTROL_UNUSED_MASK       = 0x3f, /*!< these bits are unused and always read as 1 */
 
176
    REU_REG_RW_ADDR_CONTROL_FIX_REC           = 0x40, /*!< if set, the REU address is fixed, it does not increment */
 
177
    REU_REG_RW_ADDR_CONTROL_FIX_C64           = 0x80  /*!< if set, the C64 address is fixed, it does not increment */
 
178
};
83
179
 
84
180
/* REU registers */
85
 
static BYTE reu[16];
86
 
 
87
 
/* shadow registers for implementing the "Half-Autoload-Bug"
88
 
   Thanks to Wolfgang Moser for pointing this out
89
 
*/
90
 
static BYTE reu_baseaddr_low_shadow;
91
 
static BYTE reu_ramaddr_low_shadow;
92
 
static BYTE reu_blocklen_low_shadow;
93
 
 
94
 
/* REU image.  */
 
181
 
 
182
/*! \brief define a complete set of REC registers */
 
183
struct rec_s {
 
184
    BYTE status;              /*!< status register at offset REU_REG_R_STATUS */
 
185
    BYTE command;             /*!< command register at offset REU_REG_RW_COMMAND */
 
186
 
 
187
    WORD base_computer;       /*!< C64 base address as defined at offsets REU_REG_RW_BASEADDR_LOW and REU_REG_RW_BASEADDR_HIGH */
 
188
    WORD base_reu;            /*!< REU base address as defined at offsets REU_REG_RW_RAMADDR_LOW and REU_REG_RW_RAMADDR_HIGH */
 
189
    BYTE bank_reu;            /*!< REU bank address as defined at offset REU_REG_RW_BANK */
 
190
    WORD transfer_length;     /*!< transfer length as defined at offsets REU_REG_RW_BLOCKLEN_LOW and REU_REG_RW_BLOCKLEN_HIGH */
 
191
 
 
192
    BYTE int_mask_reg;        /*! interrupt mask register as defined at offset REU_REG_RW_INTERRUPT */
 
193
    BYTE address_control_reg; /*! address control register as defined at offset REU_REG_RW_ADDR_CONTROL */
 
194
 
 
195
    /* shadow registers for implementing the "Half-Autoload-Bug" */
 
196
 
 
197
    WORD base_computer_shadow;   /*!< shadow register of base_computer */
 
198
    WORD base_reu_shadow;        /*!< shadow register of base_reu */
 
199
    BYTE bank_reu_shadow;        /*!< shadow register of bank_reu */
 
200
    WORD transfer_length_shadow; /*!< shadow register of transfer_length */
 
201
};
 
202
 
 
203
/*! \brief a complete REC description */
 
204
static struct rec_s rec;
 
205
 
 
206
/*! \brief some rec options which define special behaviour */
 
207
struct rec_options_s {
 
208
    unsigned int wrap_around;                   /*!< address where the REU has a wrap around */
 
209
    unsigned int special_wrap_around_1700;      /*!< address where the special 1700 wrap around occurs; if no 1700, the same avalue as wrap_around */
 
210
    unsigned int not_backedup_addresses;        /*!< beginning from this address up to wrap_around, there is no DRAM at all */
 
211
    unsigned int wrap_around_mask_when_storing; /*!< mask for the wrap around of REU address when putting result back in base_reu and bank_reu */
 
212
    BYTE         reg_bank_unused;               /*!< the unused bits (stuck at 1) of REU_REG_RW_BANK; for original REU, it is REU_REG_RW_BANK_UNUSED */
 
213
    BYTE         status_preset;                 /*!< preset value for the status (can be 0 or REU_REG_R_STATUS_256K_CHIPS) */
 
214
    unsigned int first_unused_register_address; /*!< the highest address the used REU register occupy */
 
215
};
 
216
 
 
217
/*! \brief a complete REC options description */
 
218
static struct rec_options_s rec_options;
 
219
 
 
220
 
 
221
 
 
222
/*! \brief pointer to a buffer which holds the REU image.  */
95
223
static BYTE *reu_ram = NULL;
96
 
static int old_reu_ram_size = 0;
 
224
/*! \brief the old ram size of reu_ram. Used to determine if and how much of the 
 
225
    buffer has to cleared when resizing the REU. */
 
226
static unsigned int old_reu_ram_size = 0;
97
227
 
98
 
static log_t reu_log = LOG_ERR;
 
228
static log_t reu_log = LOG_ERR; /*!< the log output for the REU */
99
229
 
100
230
static int reu_activate(void);
101
231
static int reu_deactivate(void);
104
234
 
105
235
/* ------------------------------------------------------------------------- */
106
236
 
107
 
/* Flag: Do we enable the external REU?  */
 
237
/*! \brief Flag: Is the external REU enabled?  */
108
238
int reu_enabled;
109
239
 
110
 
/* Size of the REU.  */
111
 
static int reu_size = 0;
 
240
/*! \brief Size of the REU.  */
 
241
static unsigned int reu_size = 0;
112
242
 
113
 
/* Size of the REU in KB.  */
 
243
/*! \brief Size of the REU in KB.  */
114
244
static int reu_size_kb = 0;
115
245
 
116
 
/* Filename of the REU image.  */
 
246
/*! \brief Filename of the REU image.  */
117
247
static char *reu_filename = NULL;
118
248
 
119
249
 
 
250
/*! \internal \brief set the reu to the enabled or disabled state
 
251
 
 
252
 \param val
 
253
   if 0, disable the REU; else, enable it.
 
254
 
 
255
 \param param
 
256
   unused
 
257
 
 
258
 \return
 
259
   0 on success. else -1.
 
260
*/
120
261
static int set_reu_enabled(int val, void *param)
121
262
{
122
263
    if (!val) {
139
280
    }
140
281
}
141
282
 
 
283
/*! \internal \brief set the first unused REU register address
 
284
 
 
285
 \param val
 
286
   the end of the used REU register area; should be equal
 
287
   to or bigger than REU_REG_RW_UNUSED.
 
288
 
 
289
 \param param
 
290
   unused
 
291
 
 
292
 \return
 
293
   0 on success, else -1.
 
294
*/
 
295
static int set_reu_first_unused(int val, void *param)
 
296
{
 
297
    int retval = -1;
 
298
 
 
299
    if (val >= REU_REG_RW_UNUSED) {
 
300
        rec_options.first_unused_register_address = val;
 
301
        retval = 0;
 
302
    }
 
303
    else {
 
304
        log_message(reu_log, "Invalid first unused REU address %02x.", val);
 
305
    };
 
306
 
 
307
    return retval;
 
308
}
 
309
 
 
310
/*! \internal \brief set the size of the reu
 
311
 
 
312
 \param val
 
313
   the size of the REU, in KB
 
314
 
 
315
 \param param
 
316
   unused
 
317
 
 
318
 \return
 
319
   0 on success, else -1.
 
320
 
 
321
 \remark
 
322
   val must be one of 128, 256, 512, 1024, 2048, 4096, 8192, or 16384.
 
323
*/
142
324
static int set_reu_size(int val, void *param)
143
325
{
144
326
    if (val == reu_size_kb)
161
343
 
162
344
    if (reu_enabled) {
163
345
        reu_deactivate();
164
 
        reu_size_kb = val;
165
 
        reu_size = reu_size_kb << 10;
 
346
    }
 
347
 
 
348
    reu_size_kb = val;
 
349
    reu_size = reu_size_kb << 10;
 
350
 
 
351
    rec_options.wrap_around = 0x80000;
 
352
    rec_options.special_wrap_around_1700 = rec_options.wrap_around;
 
353
    rec_options.not_backedup_addresses = reu_size;
 
354
    rec_options.wrap_around_mask_when_storing = rec_options.wrap_around - 1;
 
355
    rec_options.reg_bank_unused = REU_REG_RW_BANK_UNUSED;
 
356
    rec_options.status_preset = REU_REG_R_STATUS_256K_CHIPS;
 
357
 
 
358
    switch (val) {
 
359
      case 128:
 
360
        /* special handling to mimic a 1700 as good as possible */
 
361
        rec_options.status_preset = 0; /* we do not have 256K chips, but only 64K chips */
 
362
        rec_options.special_wrap_around_1700 = 0x20000; /* the 1700 has a special wrap around, mimic that one */
 
363
        break;
 
364
      case 256:
 
365
        /* special handling to mimic a 1764 as good as possible */
 
366
        break;
 
367
      case 512:
 
368
        /* special handling to mimic a 1750 as good as possible */
 
369
        break;
 
370
      default:
 
371
        /* for the other (fictive) REUs, assume the bank register would be fully 8 bits wide */
 
372
        rec_options.wrap_around = 
 
373
        rec_options.special_wrap_around_1700 = 0;
 
374
        rec_options.wrap_around_mask_when_storing = 0xffffffff;
 
375
        rec_options.reg_bank_unused = 0;
 
376
        break;
 
377
    }
 
378
 
 
379
    if (reu_enabled) {
166
380
        reu_activate();
167
 
    } else {
168
 
        reu_size_kb = val;
169
 
        reu_size = reu_size_kb << 10;
170
381
    }
171
382
 
172
383
    return 0;
173
384
}
174
385
 
 
386
/*! \internal \brief set the file name of the REU data
 
387
 
 
388
 \param name
 
389
   pointer to a buffer which holds the file name.
 
390
   If NULL, the REU data will not be backed on the disk.
 
391
 
 
392
 \param param
 
393
   unused
 
394
 
 
395
 \return
 
396
   0 on success, else -1.
 
397
 
 
398
 \remark
 
399
   The file name of the REU data is the name of the file which is
 
400
   used to store the REU data onto disk.
 
401
*/
175
402
static int set_reu_filename(const char *name, void *param)
176
403
{
177
404
    if (reu_filename != NULL && name != NULL
185
412
 
186
413
    if (reu_enabled) {
187
414
        reu_deactivate();
188
 
        util_string_set(&reu_filename, name);
 
415
    }
 
416
    util_string_set(&reu_filename, name);
 
417
 
 
418
    if (reu_enabled) {
189
419
        reu_activate();
190
 
    } else {
191
 
        util_string_set(&reu_filename, name);
192
420
    }
193
421
 
194
422
    return 0;
195
423
}
196
424
 
 
425
/*! \brief string resources used by the REU module */
197
426
static const resource_string_t resources_string[] = {
198
427
    { "REUfilename", "", RES_EVENT_NO, NULL,
199
428
      &reu_filename, set_reu_filename, NULL },
200
429
    { NULL }
201
430
};
202
431
 
 
432
/*! \brief integer resources used by the REU module */
203
433
static const resource_int_t resources_int[] = {
204
434
    { "REU", 0, RES_EVENT_STRICT, (resource_value_t)0,
205
435
      &reu_enabled, set_reu_enabled, NULL },
206
436
    { "REUsize", 512, RES_EVENT_NO, NULL,
207
437
      &reu_size_kb, set_reu_size, NULL },
 
438
    { "REUfirstUnusedRegister", REU_REG_RW_UNUSED, RES_EVENT_NO, NULL,
 
439
      (int *) &rec_options.first_unused_register_address, set_reu_first_unused, NULL },
208
440
    { NULL }
209
441
};
210
442
 
 
443
/*! \brief initialize the reu resources
 
444
 \return
 
445
   0 on success, else -1.
 
446
 
 
447
 \remark
 
448
   Registers the string and the integer resources
 
449
*/
211
450
int reu_resources_init(void)
212
451
{
213
452
    if (resources_register_string(resources_string) < 0)
216
455
    return resources_register_int(resources_int);
217
456
}
218
457
 
 
458
/*! \brief uninitialize the reu resources */
219
459
void reu_resources_shutdown(void)
220
460
{
221
461
    lib_free(reu_filename);
223
463
 
224
464
/* ------------------------------------------------------------------------- */
225
465
 
226
 
#ifdef HAS_TRANSLATION
227
 
static const cmdline_option_t cmdline_options[] =
228
 
{
229
 
    { "-reu", SET_RESOURCE, 0, NULL, NULL, "REU", (resource_value_t)1,
230
 
      0, IDCLS_ENABLE_REU },
231
 
    { "+reu", SET_RESOURCE, 0, NULL, NULL, "REU", (resource_value_t)0,
232
 
      0, IDCLS_DISABLE_REU },
233
 
    { "-reuimage", SET_RESOURCE, 1, NULL, NULL, "REUfilename", NULL,
234
 
      IDCLS_P_NAME, IDCLS_SPECIFY_REU_NAME },
235
 
    { "-reusize", SET_RESOURCE, 1, NULL, NULL, "REUsize", NULL,
236
 
      IDCLS_P_SIZE_IN_KB, IDCLS_REU_SIZE },
237
 
    { NULL }
238
 
};
239
 
#else
240
 
static const cmdline_option_t cmdline_options[] =
241
 
{
242
 
    { "-reu", SET_RESOURCE, 0, NULL, NULL, "REU", (resource_value_t)1,
243
 
      NULL, N_("Enable the RAM expansion unit") },
244
 
    { "+reu", SET_RESOURCE, 0, NULL, NULL, "REU", (resource_value_t)0,
245
 
      NULL, N_("Disable the RAM expansion unit") },
246
 
    { "-reuimage", SET_RESOURCE, 1, NULL, NULL, "REUfilename", NULL,
247
 
      N_("<name>"), N_("Specify name of REU image") },
248
 
    { "-reusize", SET_RESOURCE, 1, NULL, NULL, "REUsize", NULL,
249
 
      N_("<size in KB>"), N_("Size of the RAM expansion unit") },
250
 
    { NULL }
251
 
};
252
 
#endif
253
 
 
 
466
static const cmdline_option_t cmdline_options[] =
 
467
{
 
468
    { "-reu", SET_RESOURCE, 0,
 
469
      NULL, NULL, "REU", (resource_value_t)1,
 
470
      USE_PARAM_STRING, USE_DESCRIPTION_ID,
 
471
      IDCLS_UNUSED, IDCLS_ENABLE_REU,
 
472
      NULL, NULL },
 
473
    { "+reu", SET_RESOURCE, 0,
 
474
      NULL, NULL, "REU", (resource_value_t)0,
 
475
      USE_PARAM_STRING, USE_DESCRIPTION_ID,
 
476
      IDCLS_UNUSED, IDCLS_DISABLE_REU,
 
477
      NULL, NULL },
 
478
    { "-reuimage", SET_RESOURCE, 1,
 
479
      NULL, NULL, "REUfilename", NULL,
 
480
      USE_PARAM_ID, USE_DESCRIPTION_ID,
 
481
      IDCLS_P_NAME, IDCLS_SPECIFY_REU_NAME,
 
482
      NULL, NULL },
 
483
    { "-reusize", SET_RESOURCE, 1,
 
484
      NULL, NULL, "REUsize", NULL,
 
485
      USE_PARAM_ID, USE_DESCRIPTION_ID,
 
486
      IDCLS_P_SIZE_IN_KB, IDCLS_REU_SIZE,
 
487
      NULL, NULL },
 
488
    { NULL }
 
489
};
 
490
 
 
491
/*! \brief initialize the command-line options'
 
492
 \return
 
493
   0 on success, else -1.
 
494
 
 
495
 \remark
 
496
   Registers the command-line options
 
497
*/
254
498
int reu_cmdline_options_init(void)
255
499
{
256
500
    return cmdline_register_options(cmdline_options);
258
502
 
259
503
/* ------------------------------------------------------------------------- */
260
504
 
 
505
/*! \brief initialize the REU */
261
506
void reu_init(void)
262
507
{
263
508
    reu_log = log_open("REU");
265
510
    reu_int_num = interrupt_cpu_status_int_new(maincpu_int_status, "REU");
266
511
}
267
512
 
 
513
/*! \brief reset the REU */
268
514
void reu_reset(void)
269
515
{
270
 
    int i;
271
 
 
272
 
    for (i = 0; i < 16; i++)
273
 
        reu[i] = 0;
274
 
 
275
 
    /* clear the shadow registers */
276
 
    reu_baseaddr_low_shadow =
277
 
    reu_ramaddr_low_shadow =
278
 
    reu_blocklen_low_shadow = 0;
279
 
 
280
 
    if (reu_size >= (256 << 10))
281
 
        reu[REU_REG_R_STATUS] = 0x10;
282
 
    else
283
 
        reu[REU_REG_R_STATUS] = 0x00;
284
 
 
285
 
    reu[REU_REG_W_COMMAND] = 0x10;
286
 
 
287
 
    reu[REU_REG_RW_BLOCKLEN_LOW]  = 0xFF;
288
 
    reu[REU_REG_RW_BLOCKLEN_HIGH] = 0xFF;
 
516
    memset(&rec, 0, sizeof rec);
 
517
 
 
518
    rec.status = (rec.status & ~ REU_REG_R_STATUS_256K_CHIPS) 
 
519
                  | rec_options.status_preset;
 
520
 
 
521
    rec.command = REU_REG_RW_COMMAND_FF00_TRIGGER_DISABLED;
 
522
 
 
523
    rec.transfer_length =
 
524
    rec.transfer_length_shadow = 0xffff;
 
525
 
 
526
    rec.bank_reu = 
 
527
    rec.bank_reu_shadow = rec_options.reg_bank_unused;
 
528
 
 
529
    rec.int_mask_reg = REU_REG_RW_INTERRUPT_UNUSED_MASK;
 
530
 
 
531
    rec.address_control_reg = REU_REG_RW_ADDR_CONTROL_UNUSED_MASK;
289
532
}
290
533
 
291
534
static int reu_activate(void)
293
536
    if (!reu_size)
294
537
        return 0;
295
538
 
296
 
    reu_ram = (BYTE *)lib_realloc((void *)reu_ram, (size_t)reu_size);
 
539
    reu_ram = lib_realloc(reu_ram, reu_size);
297
540
 
298
541
    /* Clear newly allocated RAM.  */
299
542
    if (reu_size > old_reu_ram_size)
350
593
}
351
594
 
352
595
/* ------------------------------------------------------------------------- */
353
 
 
354
 
BYTE REGPARM1 reu_read(WORD addr)
 
596
/* helper functions */
 
597
 
 
598
/*! \brief read the REU register values without side effects
 
599
  This function reads the REU values, so they can be accessed like
 
600
  an array of bytes. No side-effects that would be performed if a real
 
601
  read access would occur are executed.
 
602
 
 
603
  \param addr
 
604
    The address of the REC register to read
 
605
 
 
606
  \return
 
607
    The value the register has
 
608
 
 
609
  \remark
 
610
    address must be in the valid range 0..0x1f
 
611
*/
 
612
static BYTE reu_read_without_sideeffects(WORD addr)
355
613
{
356
 
    BYTE retval;
 
614
    BYTE retval = 0xff;
 
615
 
 
616
    addr &= REU_REG_LAST_REG;
357
617
 
358
618
    switch (addr) {
359
619
      case REU_REG_R_STATUS:
360
 
        io_source=IO_SOURCE_REU;
361
 
        retval = reu[REU_REG_R_STATUS];
362
 
 
363
 
        /* Bits 7-5 are cleared when register is read, and pending IRQs are
364
 
           removed. */
365
 
        reu[REU_REG_R_STATUS] &= ~0xe0;
366
 
        maincpu_set_irq(reu_int_num, 0);
 
620
        retval = rec.status;
 
621
        break;
 
622
 
 
623
      case REU_REG_RW_COMMAND:
 
624
        retval = rec.command;
 
625
        break;
 
626
 
 
627
      case REU_REG_RW_BASEADDR_LOW:
 
628
        retval = rec.base_computer & 0xff;
 
629
        break;
 
630
 
 
631
      case REU_REG_RW_BASEADDR_HIGH:
 
632
        retval = (rec.base_computer >> 8) & 0xff;
 
633
        break;
 
634
 
 
635
      case REU_REG_RW_RAMADDR_LOW:
 
636
        retval = rec.base_reu & 0xff;
 
637
        break;
 
638
 
 
639
      case REU_REG_RW_RAMADDR_HIGH:
 
640
        retval = (rec.base_reu >> 8) & 0xff;
367
641
        break;
368
642
 
369
643
      case REU_REG_RW_BANK:
370
 
        io_source=IO_SOURCE_REU;
371
 
        retval = reu[REU_REG_RW_BANK] | 0xf8;
 
644
        retval = rec.bank_reu | rec_options.reg_bank_unused;
 
645
        break;
 
646
 
 
647
      case REU_REG_RW_BLOCKLEN_LOW:
 
648
        retval = rec.transfer_length & 0xff;
 
649
        break;
 
650
 
 
651
      case REU_REG_RW_BLOCKLEN_HIGH:
 
652
        retval = (rec.transfer_length >> 8) & 0xff;
372
653
        break;
373
654
 
374
655
      case REU_REG_RW_INTERRUPT:
375
 
        io_source=IO_SOURCE_REU;
376
 
        retval = reu[REU_REG_RW_INTERRUPT] | 0x1f;
377
 
        break;
378
 
 
379
 
      case REU_REG_RW_ADDRCONTROL:
380
 
        io_source=IO_SOURCE_REU;
381
 
        retval = reu[REU_REG_RW_ADDRCONTROL] | 0x3f;
382
 
        break;
383
 
 
384
 
      case 0xb:
385
 
      case 0xc:
386
 
      case 0xd:
387
 
      case 0xe:
388
 
      case 0xf:
389
 
        retval = 0xff;
390
 
        break;
391
 
 
392
 
      default:
393
 
        io_source=IO_SOURCE_REU;
394
 
        retval = reu[addr];
 
656
        assert( BITS_ARE_ALL_SET(rec.int_mask_reg, REU_REG_RW_INTERRUPT_UNUSED_MASK) );
 
657
        retval = rec.int_mask_reg;
 
658
        break;
 
659
 
 
660
      case REU_REG_RW_ADDR_CONTROL:
 
661
        assert( BITS_ARE_ALL_SET(rec.address_control_reg, REU_REG_RW_ADDR_CONTROL_UNUSED_MASK) );
 
662
        retval = rec.address_control_reg;
 
663
        break;
395
664
    }
396
665
 
397
 
#ifdef REU_DEBUG
398
 
    log_message(reu_log, "read [$%02X] => $%02X.", addr, retval);
399
 
#endif
400
666
    return retval;
401
667
}
402
668
 
403
 
 
404
 
void REGPARM2 reu_store(WORD addr, BYTE byte)
 
669
/*! \brief write the REU register values without side effects
 
670
  This function writes the REU values, so they can be accessed like
 
671
  an array of bytes. No side-effects that would be performed if a real
 
672
  write access would occur are executed.
 
673
 
 
674
  \param addr
 
675
    The address of the REC register to write
 
676
 
 
677
  \param byte
 
678
    The value to set the register to
 
679
 
 
680
  \remark
 
681
    address must be in the valid range 0..0x1f
 
682
*/
 
683
static void reu_store_without_sideeffects(WORD addr, BYTE byte)
405
684
{
 
685
    addr &= REU_REG_LAST_REG;
 
686
 
406
687
    switch (addr)
407
688
    {
408
689
    case REU_REG_R_STATUS:
409
690
        /* REC status register is Read Only */
410
691
        break;
411
692
 
 
693
    case REU_REG_RW_COMMAND:
 
694
        rec.command = byte;
 
695
        break;
 
696
 
412
697
    case REU_REG_RW_BASEADDR_LOW:
413
 
        /* update shadow register, too */
414
 
        reu_baseaddr_low_shadow =
415
 
        reu[addr] = byte;
 
698
        rec.base_computer = 
 
699
        rec.base_computer_shadow = (rec.base_computer_shadow & 0xff00) | byte;
416
700
        break;
417
701
 
418
702
    case REU_REG_RW_BASEADDR_HIGH:
419
 
        /* also set low register from shadow register */
420
 
        reu[REU_REG_RW_BASEADDR_LOW] = reu_baseaddr_low_shadow;
421
 
        reu[addr] = byte;
 
703
        rec.base_computer = 
 
704
        rec.base_computer_shadow = (rec.base_computer_shadow & 0xff) | (byte << 8);
422
705
        break;
423
706
 
424
707
    case REU_REG_RW_RAMADDR_LOW:
425
 
        /* update shadow register, too */
426
 
        reu_ramaddr_low_shadow =
427
 
        reu[addr] = byte;
 
708
        rec.base_reu =
 
709
        rec.base_reu_shadow = (rec.base_reu_shadow & 0xff00) | byte;
428
710
        break;
429
711
 
430
712
    case REU_REG_RW_RAMADDR_HIGH:
431
 
        /* also set low register from shadow register */
432
 
        reu[REU_REG_RW_RAMADDR_LOW] = reu_ramaddr_low_shadow;
433
 
        reu[addr] = byte;
 
713
        rec.base_reu =
 
714
        rec.base_reu_shadow = (rec.base_reu_shadow & 0xff) | (byte << 8);
 
715
        break;
 
716
 
 
717
    case REU_REG_RW_BANK:
 
718
        rec.bank_reu = 
 
719
        rec.bank_reu_shadow = byte & ~ rec_options.reg_bank_unused;
434
720
        break;
435
721
 
436
722
    case REU_REG_RW_BLOCKLEN_LOW:
437
 
        /* update shadow register, too */
438
 
        reu_blocklen_low_shadow =
439
 
        reu[addr] = byte;
 
723
        rec.transfer_length =
 
724
        rec.transfer_length_shadow = (rec.transfer_length_shadow & 0xff00) | byte;
440
725
        break;
441
726
 
442
727
    case REU_REG_RW_BLOCKLEN_HIGH:
443
 
        /* also set low register from shadow register */
444
 
        reu[REU_REG_RW_BLOCKLEN_LOW] = reu_blocklen_low_shadow;
445
 
        reu[addr] = byte;
 
728
        rec.transfer_length =
 
729
        rec.transfer_length_shadow = (rec.transfer_length_shadow & 0xff) | (byte << 8);
 
730
        break;
 
731
 
 
732
    case REU_REG_RW_INTERRUPT:
 
733
        rec.int_mask_reg = byte | REU_REG_RW_INTERRUPT_UNUSED_MASK;
 
734
        break;
 
735
 
 
736
    case REU_REG_RW_ADDR_CONTROL:
 
737
        rec.address_control_reg = byte | REU_REG_RW_ADDR_CONTROL_UNUSED_MASK;
446
738
        break;
447
739
 
448
740
    default:
449
 
        reu[addr] = byte;
450
 
    }
451
 
 
452
 
#ifdef REU_DEBUG
453
 
    log_message(reu_log, "store [$%02X] <= $%02X.", addr, (int)byte);
454
 
#endif
455
 
 
456
 
    /* write REC command register
457
 
     * DMA only if execution bit (7) set  - RH */
458
 
    if ((addr == REU_REG_W_COMMAND) && (byte & 0x80))
459
 
        reu_dma(byte & 0x10);
460
 
}
461
 
 
462
 
/* ------------------------------------------------------------------------- */
463
 
 
 
741
        break;
 
742
    }
 
743
}
 
744
 
 
745
/* ------------------------------------------------------------------------- */
 
746
 
 
747
/*! \brief read the REU register values
 
748
  This function is used to read the REU values from the computer.
 
749
  All side-effects are executed.
 
750
 
 
751
  \param addr
 
752
    The address of the REC register to read
 
753
 
 
754
  \return
 
755
    The value the register has
 
756
*/
 
757
BYTE REGPARM1 reu_read(WORD addr)
 
758
{
 
759
    BYTE retval = 0xff;
 
760
 
 
761
    addr &= 0xff;
 
762
 
 
763
    if (addr < rec_options.first_unused_register_address) {
 
764
        io_source = IO_SOURCE_REU;
 
765
 
 
766
        retval = reu_read_without_sideeffects(addr);
 
767
 
 
768
        switch (addr) {
 
769
          case REU_REG_R_STATUS:
 
770
            /* Bits 7-5 are cleared when register is read, and pending IRQs are
 
771
               removed. */
 
772
            rec.status &= 
 
773
                ~(REU_REG_R_STATUS_VERIFY_ERROR 
 
774
                  | REU_REG_R_STATUS_END_OF_BLOCK 
 
775
                  | REU_REG_R_STATUS_INTERRUPT_PENDING
 
776
                 );
 
777
 
 
778
            maincpu_set_irq(reu_int_num, 0);
 
779
            break;
 
780
          default:
 
781
            break;
 
782
        }
 
783
 
 
784
        DEBUG_LOG( DEBUG_LEVEL_REGISTER, (reu_log, "read [$%02X] => $%02X.", addr, retval) );
 
785
    }
 
786
 
 
787
    return retval;
 
788
}
 
789
 
 
790
 
 
791
/*! \brief write the REU register values
 
792
  This function is used to write the REU values from the computer.
 
793
 
 
794
  \param addr
 
795
    The address of the REC register to write
 
796
 
 
797
  \param byte
 
798
    The value to set the register to
 
799
*/
 
800
void REGPARM2 reu_store(WORD addr, BYTE byte)
 
801
{
 
802
    addr &= 0xff;
 
803
 
 
804
    if (addr < rec_options.first_unused_register_address) {
 
805
        reu_store_without_sideeffects(addr, byte);
 
806
 
 
807
        DEBUG_LOG( DEBUG_LEVEL_REGISTER, (reu_log, "store [$%02X] <= $%02X.", addr, (int)byte) );
 
808
 
 
809
        switch (addr)
 
810
        {
 
811
        case REU_REG_RW_COMMAND:
 
812
            /* write REC command register
 
813
             * DMA only if execution bit (7) set  - RH */
 
814
            if (BITS_ARE_ALL_SET(rec.command, REU_REG_RW_COMMAND_EXECUTE)) {
 
815
                reu_dma(rec.command & REU_REG_RW_COMMAND_FF00_TRIGGER_DISABLED);
 
816
            }
 
817
            break;
 
818
 
 
819
        case REU_REG_RW_INTERRUPT:
 
820
            if (BITS_ARE_ALL_SET(rec.int_mask_reg,
 
821
                    REU_REG_RW_INTERRUPT_END_OF_BLOCK_ENABLED | REU_REG_RW_INTERRUPT_INTERRUPTS_ENABLED)
 
822
                && BITS_ARE_ALL_SET(rec.status, REU_REG_R_STATUS_END_OF_BLOCK))
 
823
            {
 
824
                DEBUG_LOG( DEBUG_LEVEL_REGISTER, (reu_log, "End-of-transfer interrupt pending") );
 
825
                rec.status |= REU_REG_R_STATUS_INTERRUPT_PENDING;
 
826
                maincpu_set_irq(reu_int_num, 1);
 
827
            }
 
828
            if (BITS_ARE_ALL_SET(rec.int_mask_reg,
 
829
                    REU_REG_RW_INTERRUPT_VERIFY_ENABLED | REU_REG_RW_INTERRUPT_INTERRUPTS_ENABLED)
 
830
                && BITS_ARE_ALL_SET(rec.status, REU_REG_R_STATUS_VERIFY_ERROR))
 
831
            {
 
832
                DEBUG_LOG( DEBUG_LEVEL_REGISTER, (reu_log, "Verify interrupt pending") );
 
833
                rec.status |= REU_REG_R_STATUS_INTERRUPT_PENDING;
 
834
                maincpu_set_irq(reu_int_num, 1);
 
835
            }
 
836
            break;
 
837
 
 
838
        default:
 
839
            break;
 
840
        }
 
841
 
 
842
    }
 
843
}
 
844
 
 
845
/* ------------------------------------------------------------------------- */
 
846
 
 
847
/*! \brief increment the reu address, taking wrap around into account
 
848
  This function increments the reu address by the specified step.
 
849
  If a wrap around should occur, perform it, too.
 
850
 
 
851
  \param reu_addr
 
852
     The address to be incremented
 
853
 
 
854
  \param reu_step
 
855
     The increment. Must be either 0 or 1. If 0, reu_addr is not changed at all.
 
856
 
 
857
  \return
 
858
     The incremented reu_addr, taking into account the wrap-around
 
859
*/
 
860
inline static
 
861
unsigned int increment_reu_with_wrap_around(unsigned int reu_addr, unsigned int reu_step)
 
862
{
 
863
    assert(((reu_step == 0) || (reu_step == 1)));
 
864
 
 
865
    reu_addr += reu_step;
 
866
 
 
867
    if ( (reu_addr == rec_options.special_wrap_around_1700) 
 
868
        || (reu_addr == rec_options.wrap_around))
 
869
    {
 
870
        reu_addr = 0;
 
871
    }
 
872
 
 
873
    return reu_addr;
 
874
}
 
875
 
 
876
/*! \brief store a value into the REU
 
877
  This function stores a byte value into the specified location of the REU.
 
878
  It takes into account addresses of the REU not backed up by DRAM.
 
879
 
 
880
  \param reu_addr
 
881
     The REU address where to store the value
 
882
 
 
883
  \param value
 
884
     The value to write into the REU.
 
885
 
 
886
  \remark
 
887
     If the location reu_addr is not backed up by DRAM, the store is simply
 
888
     ignored.
 
889
*/
 
890
inline static
 
891
void store_to_reu(unsigned int reu_addr, BYTE value)
 
892
{
 
893
    reu_addr &= rec_options.special_wrap_around_1700 - 1;
 
894
    if (reu_addr < rec_options.not_backedup_addresses) {
 
895
        assert(reu_addr < reu_size);
 
896
        reu_ram[reu_addr] = value;
 
897
    }
 
898
    else {
 
899
        DEBUG_LOG( DEBUG_LEVEL_NO_DRAM, (reu_log,
 
900
            "--> writing to REU address %05X, but no DRAM!",
 
901
            reu_addr) );
 
902
    }
 
903
}
 
904
 
 
905
/*! \brief read a value from the REU
 
906
  This function reads a byte value from the specified location of the REU.
 
907
  It takes into account addresses of the REU not backed up by DRAM.
 
908
 
 
909
  \param reu_addr
 
910
     The REU address where to read the value from
 
911
 
 
912
  \remark value
 
913
     The value read from the REU.
 
914
 
 
915
  \remark
 
916
     If the location reu_addr is not backed up by DRAM, a dummy
 
917
     value is returned.
 
918
  
 
919
  \todo
 
920
     Check the values a real 17xx returns.
 
921
*/
 
922
inline static
 
923
BYTE read_from_reu(unsigned int reu_addr)
 
924
{
 
925
    BYTE value = 0xff; /* dummy value to return if not DRAM is available */
 
926
 
 
927
    reu_addr &= rec_options.special_wrap_around_1700 - 1;
 
928
    if (reu_addr < rec_options.not_backedup_addresses) {
 
929
        assert(reu_addr < reu_size);
 
930
        value = reu_ram[reu_addr];
 
931
    }
 
932
    else {
 
933
        DEBUG_LOG( DEBUG_LEVEL_NO_DRAM, (reu_log,
 
934
            "--> read from REU address %05X, but no DRAM!",
 
935
            reu_addr) );
 
936
    }
 
937
 
 
938
    return value;
 
939
}
 
940
 
 
941
/* ------------------------------------------------------------------------- */
 
942
 
 
943
/*! \brief update the REU registers after a DMA operation
 
944
 
 
945
  \param host_addr
 
946
    The host (computer) address the operation stopped at
 
947
 
 
948
  \param reu_addr
 
949
    The REU address the operation stopped at
 
950
 
 
951
  \param len
 
952
    The transfer length the operation stopped at
 
953
 
 
954
  \param new_status_or_mask
 
955
    A mask which is used to set bits in the status
 
956
 
 
957
  \remark
 
958
    if autoload is enabled, the shadow registers are written back 
 
959
    to the REU registers.
 
960
*/
464
961
static void reu_dma_update_regs(WORD host_addr, unsigned int reu_addr,
465
 
                                int len)
 
962
                                int len, BYTE new_status_or_mask)
466
963
{
467
 
    if (!(reu[REU_REG_W_COMMAND] & 0x20)) {
 
964
    assert( len >= 1 );
 
965
    assert( new_status_or_mask != 0 );
 
966
 
 
967
    reu_addr &= rec_options.wrap_around_mask_when_storing;
 
968
 
 
969
    rec.status |= new_status_or_mask;
 
970
 
 
971
    if (!(rec.command & REU_REG_RW_COMMAND_AUTOLOAD)) {
468
972
        /* not autoload
469
973
         * incr. of addr. disabled, as already pointing to correct addr.
470
974
         * address changes only if not fixed, correct reu base registers  -RH
471
975
         */
472
 
#ifdef REU_DEBUG
473
 
        log_message(reu_log, "No autoload.");
474
 
#endif
475
 
        if (!(reu[REU_REG_RW_ADDRCONTROL] & 0x80)) {
476
 
            reu[REU_REG_RW_BASEADDR_LOW] = host_addr & 0xff;
477
 
            reu[REU_REG_RW_BASEADDR_HIGH] = (host_addr >> 8) & 0xff;
478
 
        }
479
 
        if (!(reu[REU_REG_RW_ADDRCONTROL] & 0x40)) {
480
 
            reu[REU_REG_RW_RAMADDR_LOW] = reu_addr & 0xff;
481
 
            reu[REU_REG_RW_RAMADDR_HIGH] = (reu_addr >> 8) & 0xff;
482
 
            reu[REU_REG_RW_BANK] = (reu_addr >> 16);
483
 
        }
484
 
 
485
 
        reu[REU_REG_RW_BLOCKLEN_LOW] = len & 0xff;
486
 
        reu[REU_REG_RW_BLOCKLEN_HIGH] = (len >> 8) & 0xff;
 
976
        DEBUG_LOG( DEBUG_LEVEL_REGISTER, (reu_log, "No autoload.") );
 
977
        if ( BITS_ARE_ALL_UNSET(rec.address_control_reg, REU_REG_RW_ADDR_CONTROL_FIX_C64) ) {
 
978
            rec.base_computer = host_addr;
 
979
        }
 
980
 
 
981
        if ( BITS_ARE_ALL_UNSET(rec.address_control_reg, REU_REG_RW_ADDR_CONTROL_FIX_REC) ) {
 
982
            rec.base_reu = reu_addr & 0xffff;
 
983
            rec.bank_reu = (reu_addr >> 16) & 0xff;
 
984
        }
 
985
 
 
986
        rec.transfer_length = len & 0xFFFF;
 
987
    }
 
988
    else {
 
989
        rec.base_computer   = rec.base_computer_shadow;
 
990
        rec.base_reu        = rec.base_reu_shadow;
 
991
        rec.bank_reu        = rec.bank_reu_shadow;
 
992
        rec.transfer_length = rec.transfer_length_shadow;
 
993
 
 
994
        DEBUG_LOG( DEBUG_LEVEL_REGISTER, (reu_log, "Autoload.") );
 
995
    }
 
996
 
 
997
    if ( BITS_ARE_ALL_SET(new_status_or_mask, REU_REG_R_STATUS_END_OF_BLOCK) ) {
 
998
        /* only check for interrupt, when the transfer ended correctly (no verify error) */
 
999
        if ( BITS_ARE_ALL_SET(rec.int_mask_reg,
 
1000
             REU_REG_RW_INTERRUPT_END_OF_BLOCK_ENABLED | REU_REG_RW_INTERRUPT_INTERRUPTS_ENABLED))
 
1001
        {
 
1002
            DEBUG_LOG( DEBUG_LEVEL_REGISTER, (reu_log, "Interrupt pending") );
 
1003
            rec.status |= REU_REG_R_STATUS_INTERRUPT_PENDING;
 
1004
            maincpu_set_irq(reu_int_num, 1);
 
1005
        }
 
1006
    }
 
1007
 
 
1008
    if ( BITS_ARE_ALL_SET(new_status_or_mask, REU_REG_R_STATUS_VERIFY_ERROR)) {
 
1009
        if ( BITS_ARE_ALL_SET(rec.int_mask_reg,
 
1010
             REU_REG_RW_INTERRUPT_VERIFY_ENABLED | REU_REG_RW_INTERRUPT_INTERRUPTS_ENABLED))
 
1011
        {
 
1012
            DEBUG_LOG( DEBUG_LEVEL_REGISTER, (reu_log, "Verify Interrupt pending") );
 
1013
            rec.status |= REU_REG_R_STATUS_INTERRUPT_PENDING;
 
1014
            maincpu_set_irq(reu_int_num, 1);
 
1015
        }
487
1016
    }
488
1017
}
489
1018
 
 
1019
/*! \brief DMA operation writing from the host to the REU
 
1020
 
 
1021
  \param host_addr
 
1022
    The host (computer) address where the operation starts 
 
1023
 
 
1024
  \param reu_addr
 
1025
    The REU address where the operation starts
 
1026
 
 
1027
  \param host_step
 
1028
    The increment to use for the host address; must be either 0 or 1
 
1029
 
 
1030
  \param reu_step
 
1031
    The increment to use for the REU address; must be either 0 or 1
 
1032
 
 
1033
  \param len
 
1034
    The transfer length of the operation
 
1035
*/
490
1036
static void reu_dma_host_to_reu(WORD host_addr, unsigned int reu_addr, 
491
1037
                                int host_step, int reu_step, int len)
492
1038
{
493
1039
    BYTE value;
494
 
#ifdef REU_DEBUG
495
 
    log_message(reu_log,
 
1040
    DEBUG_LOG( DEBUG_LEVEL_TRANSFER_HIGH_LEVEL, (reu_log,
496
1041
                "copy ext $%05X %s<= main $%04X%s, $%04X (%d) bytes.",
497
1042
                reu_addr, reu_step ? "" : "(fixed) ", host_addr,
498
 
                host_step ? "" : " (fixed)", len, len);
499
 
#endif
500
 
 
501
 
    for (; len--; reu_addr += reu_step) {
 
1043
                host_step ? "" : " (fixed)", len, len) );
 
1044
 
 
1045
    assert(((host_step == 0) || (host_step == 1)));
 
1046
    assert(((reu_step == 0) || (reu_step == 1)));
 
1047
    assert(len >= 1);
 
1048
 
 
1049
    while (len) {
502
1050
        maincpu_clk++;
503
1051
        machine_handle_pending_alarms(0);
504
1052
        value = mem_read(host_addr);
505
 
 
506
 
#ifdef REU_DEBUG
507
 
        log_message(reu_log,
 
1053
        DEBUG_LOG( DEBUG_LEVEL_TRANSFER_LOW_LEVEL, (reu_log,
508
1054
                    "Transferring byte: %x from main $%04X to ext $%05X.",
509
 
                    value, host_addr, reu_addr);
510
 
#endif
 
1055
                    value, host_addr, reu_addr) );
511
1056
 
512
 
        reu_ram[reu_addr % reu_size] = value;
 
1057
        store_to_reu(reu_addr, value);
513
1058
        host_addr = (host_addr + host_step) & 0xffff;
 
1059
        reu_addr = increment_reu_with_wrap_around(reu_addr, reu_step);
 
1060
        len--;
514
1061
    }
515
 
    len = 0x1;
516
 
    reu[REU_REG_R_STATUS] |= 0x40;
517
 
    reu_dma_update_regs(host_addr, reu_addr, len);
 
1062
    DEBUG_LOG( DEBUG_LEVEL_REGISTER, (reu_log, "END OF BLOCK") );
 
1063
    reu_dma_update_regs(host_addr, reu_addr, ++len, REU_REG_R_STATUS_END_OF_BLOCK);
518
1064
}
519
1065
 
 
1066
/*! \brief DMA operation writing from the REU to the host
 
1067
 
 
1068
  \param host_addr
 
1069
    The host (computer) address where the operation starts 
 
1070
 
 
1071
  \param reu_addr
 
1072
    The REU address where the operation starts
 
1073
 
 
1074
  \param host_step
 
1075
    The increment to use for the host address; must be either 0 or 1
 
1076
 
 
1077
  \param reu_step
 
1078
    The increment to use for the REU address; must be either 0 or 1
 
1079
 
 
1080
  \param len
 
1081
    The transfer length of the operation
 
1082
*/
520
1083
static void reu_dma_reu_to_host(WORD host_addr, unsigned int reu_addr,
521
1084
                                int host_step, int reu_step, int len)
522
1085
{
523
 
#ifdef REU_DEBUG
524
 
    log_message(reu_log,
 
1086
    BYTE value;
 
1087
    DEBUG_LOG( DEBUG_LEVEL_TRANSFER_HIGH_LEVEL, (reu_log,
525
1088
                "copy ext $%05X %s=> main $%04X%s, $%04X (%d) bytes.",
526
1089
                reu_addr, reu_step ? "" : "(fixed) ", host_addr,
527
 
                host_step ? "" : " (fixed)", len, len);
528
 
#endif
529
 
 
530
 
    for (; len--; reu_addr += reu_step) {
531
 
#ifdef REU_DEBUG
532
 
        log_message(reu_log,
 
1090
                host_step ? "" : " (fixed)", len, len) );
 
1091
 
 
1092
    assert(((host_step == 0) || (host_step == 1)));
 
1093
    assert(((reu_step == 0) || (reu_step == 1)));
 
1094
    assert(len >= 1);
 
1095
 
 
1096
    while (len) {
 
1097
        DEBUG_LOG( DEBUG_LEVEL_TRANSFER_LOW_LEVEL, (reu_log,
533
1098
                    "Transferring byte: %x from ext $%05X to main $%04X.",
534
 
                    reu_ram[reu_addr % reu_size], reu_addr, host_addr);
535
 
#endif
 
1099
                    reu_ram[reu_addr % reu_size], reu_addr, host_addr) );
536
1100
        maincpu_clk++;
537
 
        mem_store(host_addr, reu_ram[reu_addr % reu_size]);
 
1101
        value = read_from_reu(reu_addr);
 
1102
        mem_store(host_addr, value);
538
1103
        machine_handle_pending_alarms(0);
539
1104
        host_addr = (host_addr + host_step) & 0xffff;
 
1105
        reu_addr = increment_reu_with_wrap_around(reu_addr, reu_step);
 
1106
        len--;
540
1107
    }
541
 
    len = 1;
542
 
    reu[REU_REG_R_STATUS] |= 0x40;
543
 
    reu_dma_update_regs(host_addr, reu_addr, len);
 
1108
    DEBUG_LOG( DEBUG_LEVEL_REGISTER, (reu_log, "END OF BLOCK") );
 
1109
    reu_dma_update_regs(host_addr, reu_addr, ++len, REU_REG_R_STATUS_END_OF_BLOCK);
544
1110
}
545
1111
 
 
1112
/*! \brief DMA operation swaping data between host and REU
 
1113
 
 
1114
  \param host_addr
 
1115
    The host (computer) address where the operation starts 
 
1116
 
 
1117
  \param reu_addr
 
1118
    The REU address where the operation starts
 
1119
 
 
1120
  \param host_step
 
1121
    The increment to use for the host address; must be either 0 or 1
 
1122
 
 
1123
  \param reu_step
 
1124
    The increment to use for the REU address; must be either 0 or 1
 
1125
 
 
1126
  \param len
 
1127
    The transfer length of the operation
 
1128
*/
546
1129
static void reu_dma_swap(WORD host_addr, unsigned int reu_addr,
547
1130
                         int host_step, int reu_step, int len)
548
1131
{
549
 
    BYTE c;
550
 
#ifdef REU_DEBUG
551
 
    log_message(reu_log,
 
1132
    BYTE value_from_reu;
 
1133
    BYTE value_from_c64;
 
1134
    DEBUG_LOG( DEBUG_LEVEL_TRANSFER_HIGH_LEVEL, (reu_log,
552
1135
                "swap ext $%05X %s<=> main $%04X%s, $%04X (%d) bytes.",
553
1136
                reu_addr, reu_step ? "" : "(fixed) ", host_addr,
554
 
                host_step ? "" : " (fixed)", len, len);
555
 
#endif
556
 
 
557
 
    for (; len--; reu_addr += reu_step ) {
558
 
        c = reu_ram[reu_addr % reu_size];
 
1137
                host_step ? "" : " (fixed)", len, len) );
 
1138
 
 
1139
    assert(((host_step == 0) || (host_step == 1)));
 
1140
    assert(((reu_step == 0) || (reu_step == 1)));
 
1141
    assert(len >= 1);
 
1142
 
 
1143
    while (len) {
 
1144
        value_from_reu = read_from_reu(reu_addr);
559
1145
        maincpu_clk++;
560
1146
        machine_handle_pending_alarms(0);
561
 
        reu_ram[reu_addr % reu_size] = mem_read(host_addr);
562
 
        mem_store(host_addr, c);
 
1147
        value_from_c64 = mem_read(host_addr);
 
1148
        DEBUG_LOG( DEBUG_LEVEL_TRANSFER_LOW_LEVEL, (reu_log,
 
1149
                    "Exchanging bytes: %x from main $%04X with %x from ext $%05X.",
 
1150
                    value_from_c64, host_addr, value_from_reu, reu_addr) );
 
1151
        store_to_reu(reu_addr, value_from_c64);
 
1152
        mem_store(host_addr, value_from_reu);
563
1153
        maincpu_clk++;
564
1154
        machine_handle_pending_alarms(0);
565
1155
        host_addr = (host_addr + host_step) & 0xffff;
 
1156
        reu_addr = increment_reu_with_wrap_around(reu_addr, reu_step);
 
1157
        len--;
566
1158
    }
567
 
    len = 1;
568
 
    reu[REU_REG_R_STATUS] |= 0x40;
569
 
    reu_dma_update_regs(host_addr, reu_addr, len);
 
1159
    DEBUG_LOG( DEBUG_LEVEL_REGISTER, (reu_log, "END OF BLOCK") );
 
1160
    reu_dma_update_regs(host_addr, reu_addr, ++len, REU_REG_R_STATUS_END_OF_BLOCK);
570
1161
}
571
1162
 
 
1163
/*! \brief DMA operation comparing data between host and REU
 
1164
 
 
1165
  \param host_addr
 
1166
    The host (computer) address where the operation starts 
 
1167
 
 
1168
  \param reu_addr
 
1169
    The REU address where the operation starts
 
1170
 
 
1171
  \param host_step
 
1172
    The increment to use for the host address; must be either 0 or 1
 
1173
 
 
1174
  \param reu_step
 
1175
    The increment to use for the REU address; must be either 0 or 1
 
1176
 
 
1177
  \param len
 
1178
    The transfer length of the operation
 
1179
*/
572
1180
static void reu_dma_compare(WORD host_addr, unsigned int reu_addr,
573
1181
                            int host_step, int reu_step, int len)
574
1182
{
575
 
#ifdef REU_DEBUG
576
 
    log_message(reu_log,
 
1183
    BYTE value_from_reu;
 
1184
    BYTE value_from_c64;
 
1185
 
 
1186
    BYTE new_status_or_mask = 0;
 
1187
 
 
1188
    DEBUG_LOG( DEBUG_LEVEL_TRANSFER_HIGH_LEVEL, (reu_log,
577
1189
                "compare ext $%05X %s<=> main $%04X%s, $%04X (%d) bytes.",
578
1190
                reu_addr, reu_step ? "" : "(fixed) ", host_addr,
579
 
                host_step ? "" : " (fixed)", len, len);
580
 
#endif
581
 
 
582
 
    reu[REU_REG_R_STATUS] &= ~0x60;
583
 
 
584
 
    while (len--) {
 
1191
                host_step ? "" : " (fixed)", len, len) );
 
1192
 
 
1193
    assert(((host_step == 0) || (host_step == 1)));
 
1194
    assert(((reu_step == 0) || (reu_step == 1)));
 
1195
    assert(len >= 1);
 
1196
 
 
1197
    /* the real 17xx does not clear these bits on compare;
 
1198
     * thus, we do not clear them, either! */
 
1199
 
 
1200
    /* rec.status &= ~ (REU_REG_R_STATUS_VERIFY_ERROR | REU_REG_R_STATUS_END_OF_BLOCK); */
 
1201
 
 
1202
    while (len) {
585
1203
        maincpu_clk++;
586
1204
        machine_handle_pending_alarms(0);
587
 
        if (reu_ram[reu_addr % reu_size] != mem_read(host_addr)) {
588
 
            host_addr = (host_addr + host_step) & 0xffff;
589
 
            reu_addr += reu_step;
590
 
 
591
 
            reu[REU_REG_R_STATUS] |=  0x20; /* FAULT */
592
 
 
593
 
            /* Bit 7: interrupt enable
594
 
               Bit 5: interrupt on verify error */
595
 
            if (reu[REU_REG_RW_INTERRUPT] & 0xa0) {
596
 
                reu[REU_REG_R_STATUS] |= 0x80;
597
 
                maincpu_set_irq(reu_int_num, 1);
 
1205
        value_from_reu = read_from_reu(reu_addr);
 
1206
        value_from_c64 = mem_read(host_addr);
 
1207
        DEBUG_LOG( DEBUG_LEVEL_TRANSFER_LOW_LEVEL, (reu_log,
 
1208
                    "Comparing bytes: %x from main $%04X with %x from ext $%05X.",
 
1209
                    value_from_c64, host_addr, value_from_reu, reu_addr) );
 
1210
        reu_addr = increment_reu_with_wrap_around(reu_addr, reu_step);
 
1211
        host_addr = (host_addr + host_step) & 0xffff;
 
1212
        len--;
 
1213
        if (value_from_reu != value_from_c64) {
 
1214
 
 
1215
            DEBUG_LOG( DEBUG_LEVEL_REGISTER, (reu_log, "VERIFY ERROR") );
 
1216
            new_status_or_mask |= REU_REG_R_STATUS_VERIFY_ERROR;
 
1217
 
 
1218
            /* weird behaviour no. 1 of the 17xx:
 
1219
             * failed verify operations consume one extra cycle, except if
 
1220
             * the failed comparison happened on the last byte of the buffer.
 
1221
             */
 
1222
            if( len >= 1 ) {
 
1223
                maincpu_clk++;
 
1224
                machine_handle_pending_alarms(0);
598
1225
            }
599
1226
            break;
600
1227
        }
601
 
        host_addr = (host_addr + host_step) & 0xffff;;
602
 
        reu_addr += reu_step;
603
1228
    }
604
1229
 
605
 
    if (len < 0) {
 
1230
    /* the length was decremented once too much, correct this */
 
1231
    if (len == 0) {
 
1232
        ++len;
 
1233
 
 
1234
        /* weird behaviour no. 2 of the 17xx:
 
1235
         * If the last byte failed, the "end of block transfer" bit is set, too
 
1236
         */
606
1237
        /* all bytes are equal, mark End Of Block */
607
 
        reu[REU_REG_R_STATUS] |= 0x40;
608
 
        len = 1;
609
 
    }
610
 
 
611
 
    reu_dma_update_regs(host_addr, reu_addr, len);
 
1238
        new_status_or_mask |= REU_REG_R_STATUS_END_OF_BLOCK;
 
1239
    }
 
1240
    else if (len == 1) {
 
1241
        /* weird behaviour no. 3 of the 17xx:
 
1242
         * If the next-to-last byte failed, the "end of block transfer" bit is
 
1243
         * set, but only if the last byte compares equal
 
1244
         */
 
1245
 
 
1246
        value_from_reu = read_from_reu(reu_addr);
 
1247
        value_from_c64 = mem_read(host_addr);
 
1248
        DEBUG_LOG( DEBUG_LEVEL_TRANSFER_LOW_LEVEL, (reu_log,
 
1249
                    "Comparing bytes after verify error: %x from main $%04X with %x from ext $%05X.",
 
1250
                    value_from_c64, host_addr, value_from_reu, reu_addr) );
 
1251
        if (value_from_reu == value_from_c64) {
 
1252
            new_status_or_mask |= REU_REG_R_STATUS_END_OF_BLOCK;
 
1253
        }
 
1254
    }
 
1255
 
 
1256
    assert( len >= 1 );
 
1257
    reu_dma_update_regs(host_addr, reu_addr, len, new_status_or_mask);
612
1258
}
613
1259
 
614
1260
/* ------------------------------------------------------------------------- */
615
1261
 
616
 
/* This function is called when write to REC command register or memory
617
 
 * location FF00 is detected.
618
 
 *
619
 
 * If host address exceeds ffff transfer contiues at 0000.
620
 
 * If reu address exceeds 7ffff transfer continues at 00000.
621
 
 * If address is fixed the same value is used during the whole transfer.
622
 
 */
623
 
/* Added correct handling of fixed addresses with transfer length 1  - RH */
624
 
/* Added fixed address support - [EP] */
625
 
 
626
 
void reu_dma(int immed)
 
1262
/*! \brief perform REU DMA
 
1263
 
 
1264
 This function is called when a write to REC command register or memory
 
1265
 location FF00 is detected.
 
1266
 
 
1267
 \param immediate
 
1268
   If 0, the DMA should not started immediately. It is only prepared, so it
 
1269
   can be executed when the next call to reu_dma() occurs with something different
 
1270
   than immediate == 0.
 
1271
 
 
1272
 \remark
 
1273
   If the REC command register is written and 
 
1274
   REU_REG_RW_COMMAND_FF00_TRIGGER_DISABLED is *not* set, this function is called
 
1275
   with immediate == 0. In this case, this function is armed for an execution of
 
1276
   the DMA as soon as it is called with immediate == -1.\n
 
1277
   If the REC command register is written and
 
1278
   REU_REG_RW_COMMAND_FF00_TRIGGER_DISABLED *is* set, this function is called with
 
1279
   immediate == 1. In this case, the DMA is executed immediately.\n
 
1280
   If a write to $FF00 is encountered, this function is called with immediate == -1.
 
1281
   If it has been previously armed (with immediate == 0), then the DMA operation is
 
1282
   executed.
 
1283
*/
 
1284
void reu_dma(int immediate)
627
1285
{
628
1286
    static int delay = 0;
629
1287
    int len;
630
1288
    int reu_step, host_step;
631
1289
    WORD host_addr;
632
 
    unsigned int reu_addr, reu6_mask;
 
1290
    unsigned int reu_addr;
633
1291
 
634
1292
    if (!reu_enabled)
635
1293
        return;
636
1294
 
637
 
    if (!immed) {
 
1295
    if (!immediate) {
638
1296
        delay = 1;
639
1297
        return;
640
1298
    } else {
641
 
        if (!delay && immed < 0)
 
1299
        if (!delay && immediate < 0)
642
1300
            return;
643
1301
        delay = 0;
644
1302
    }
645
1303
 
646
 
    reu6_mask = (reu_size >> 16) - 1;
647
 
 
648
1304
    /* wrong address of bank register & calculations corrected  - RH */
649
 
    host_addr = (WORD)reu[REU_REG_RW_BASEADDR_LOW] 
650
 
                | ((WORD)reu[REU_REG_RW_BASEADDR_HIGH] << 8);
651
 
    reu_addr = ((unsigned int)reu[REU_REG_RW_RAMADDR_LOW]
652
 
               | ((unsigned int)reu[REU_REG_RW_RAMADDR_HIGH] << 8)
653
 
               | (((unsigned int)reu[REU_REG_RW_BANK] & reu6_mask) << 16));
654
 
 
655
 
    len = (int)(reu[REU_REG_RW_BLOCKLEN_LOW])
656
 
          | ((int)(reu[REU_REG_RW_BLOCKLEN_HIGH]) << 8);
657
 
 
658
 
    if (len == 0)
659
 
        len = 0x10000;
 
1305
    host_addr = rec.base_computer;
 
1306
    reu_addr = rec.base_reu | (rec.bank_reu << 16);
 
1307
    len = rec.transfer_length ? rec.transfer_length : 0x10000;
660
1308
 
661
1309
    /* Fixed addresses implemented -- [EP] 04-16-97. */
662
 
    host_step = (reu[REU_REG_RW_ADDRCONTROL] & 0x80) ? 0 : 1;
663
 
    reu_step = (reu[REU_REG_RW_ADDRCONTROL] & 0x40) ? 0 : 1;
 
1310
    host_step = rec.address_control_reg & REU_REG_RW_ADDR_CONTROL_FIX_C64 ? 0 : 1;
 
1311
    reu_step  = rec.address_control_reg & REU_REG_RW_ADDR_CONTROL_FIX_REC ? 0 : 1;
664
1312
 
665
 
    switch (reu[REU_REG_W_COMMAND] & 0x03) {
666
 
      case 0:
 
1313
    switch (rec.command & REU_REG_RW_COMMAND_TRANSFER_TYPE_MASK) {
 
1314
      case REU_REG_RW_COMMAND_TRANSFER_TYPE_TO_REU:
667
1315
        reu_dma_host_to_reu(host_addr, reu_addr, host_step, reu_step, len);
668
1316
        break;
669
 
      case 1:
 
1317
      case REU_REG_RW_COMMAND_TRANSFER_TYPE_FROM_REU:
670
1318
        reu_dma_reu_to_host(host_addr, reu_addr, host_step, reu_step, len);
671
1319
        break;
672
 
      case 2:
 
1320
      case REU_REG_RW_COMMAND_TRANSFER_TYPE_SWAP:
673
1321
        reu_dma_swap(host_addr, reu_addr, host_step, reu_step, len);
674
1322
        break;
675
 
      case 3:
 
1323
      case REU_REG_RW_COMMAND_TRANSFER_TYPE_VERIFY:
676
1324
        reu_dma_compare(host_addr, reu_addr, host_step, reu_step, len);
677
1325
        break;
678
1326
    }
679
1327
 
680
 
    reu[REU_REG_W_COMMAND] &= 0x7f;
681
 
 
682
 
    /* Bit 7: interrupt enable.  */
683
 
    /* Bit 6: interrupt on end of block */
684
 
    if ((reu[REU_REG_RW_INTERRUPT] & 0xc0) == 0xc0) {
685
 
        reu[REU_REG_R_STATUS] |= 0x80;
686
 
        maincpu_set_irq(reu_int_num, 1);
687
 
    }
 
1328
    rec.command = (rec.command & ~ REU_REG_RW_COMMAND_EXECUTE) 
 
1329
                  | REU_REG_RW_COMMAND_FF00_TRIGGER_DISABLED;
688
1330
}
689
1331
 
690
1332
/* ------------------------------------------------------------------------- */
691
1333
 
692
 
static char snap_module_name[] = "REU1764";
693
 
#define SNAP_MAJOR 0
694
 
#define SNAP_MINOR 0
695
 
 
 
1334
static char snap_module_name[] = "REU1764"; /*!< the name of the module for the snapshot */
 
1335
#define SNAP_MAJOR 0 /*!< version number for this module, major number */
 
1336
#define SNAP_MINOR 0 /*!< version number for this module, minor number */
 
1337
 
 
1338
/*! \brief type for the REU data as being stored in the snapshot.
 
1339
 \remark
 
1340
   Here, 16 byte are used (instead of only 11, which would be enough) to be
 
1341
   compatible with the original implementation. Otherwise, we would have to
 
1342
   change the version number. This way, it is much simpler.
 
1343
 */
 
1344
typedef BYTE reu_as_stored_in_snapshot_t[16];
 
1345
 
 
1346
/*! \brief write the REU module data to the snapshot
 
1347
 \param s
 
1348
    The snapshot data where to add the information for this module.
 
1349
 
 
1350
 \return
 
1351
    0 on success, else -1.
 
1352
*/
696
1353
int reu_write_snapshot_module(snapshot_t *s)
697
1354
{
698
1355
    snapshot_module_t *m;
699
1356
 
 
1357
    reu_as_stored_in_snapshot_t reu;
 
1358
    WORD reu_address;
 
1359
 
 
1360
    memset(reu, 0xff, sizeof reu);
 
1361
 
 
1362
    for (reu_address = 0; reu_address < sizeof(reu); reu_address++) {
 
1363
        reu[reu_address] = reu_read_without_sideeffects(reu_address);
 
1364
    }
 
1365
 
700
1366
    m = snapshot_module_create(s, snap_module_name, SNAP_MAJOR, SNAP_MINOR);
701
1367
    if (m == NULL)
702
1368
        return -1;
712
1378
    return 0;
713
1379
}
714
1380
 
 
1381
/*! \brief read the REU module data from the snapshot
 
1382
 \param s
 
1383
    The snapshot data from where to read the information for this module.
 
1384
 
 
1385
 \return
 
1386
    0 on success, else -1.
 
1387
 */
715
1388
int reu_read_snapshot_module(snapshot_t *s)
716
1389
{
717
1390
    BYTE major_version, minor_version;
718
1391
    snapshot_module_t *m;
719
1392
    DWORD size;
720
1393
 
 
1394
    reu_as_stored_in_snapshot_t reu;
 
1395
    WORD reu_address;
 
1396
 
 
1397
    memset(reu, 0xff, sizeof reu);
 
1398
 
721
1399
    m = snapshot_module_open(s, snap_module_name,
722
1400
                             &major_version, &minor_version);
723
1401
    if (m == NULL)
751
1429
    else
752
1430
        interrupt_restore_irq(maincpu_int_status, reu_int_num, 0);
753
1431
 
 
1432
    for (reu_address = 0; reu_address < sizeof(reu); reu_address++) {
 
1433
         reu_store_without_sideeffects(reu_address, reu[reu_address]);
 
1434
    }
 
1435
 
 
1436
 
754
1437
    snapshot_module_close(m);
755
1438
    return 0;
756
1439
 
758
1441
    snapshot_module_close(m);
759
1442
    return -1;
760
1443
}
761