66
118
* 01 Exec 0 Load Delayed 0 0 Mode
70
Offsets of the different REU registers
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 */
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 */
138
/*! \brief bit definitions for the REU status register at offset REU_REG_R_STATUS */
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. */
147
/*! \brief bit definitions for the REU command register at offset REU_REG_RW_COMMAND */
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. */
160
/*! \brief bit definitions for the REU bank register at offset REU_REG_RW_BANK */
162
REU_REG_RW_BANK_UNUSED = 0xF8 /*!< these bits are unused and always read as 1 */
165
/*! \brief bit definitions for the REU interrupt register at offset REU_REG_RW_INTERRUPT */
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 */
173
/*! \brief bit definitions for the REU address control register at offset REU_REG_RW_ADDR_CONTROL */
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 */
84
180
/* REU registers */
87
/* shadow registers for implementing the "Half-Autoload-Bug"
88
Thanks to Wolfgang Moser for pointing this out
90
static BYTE reu_baseaddr_low_shadow;
91
static BYTE reu_ramaddr_low_shadow;
92
static BYTE reu_blocklen_low_shadow;
182
/*! \brief define a complete set of REC registers */
184
BYTE status; /*!< status register at offset REU_REG_R_STATUS */
185
BYTE command; /*!< command register at offset REU_REG_RW_COMMAND */
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 */
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 */
195
/* shadow registers for implementing the "Half-Autoload-Bug" */
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 */
203
/*! \brief a complete REC description */
204
static struct rec_s rec;
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 */
217
/*! \brief a complete REC options description */
218
static struct rec_options_s rec_options;
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;
98
static log_t reu_log = LOG_ERR;
228
static log_t reu_log = LOG_ERR; /*!< the log output for the REU */
100
230
static int reu_activate(void);
101
231
static int reu_deactivate(void);
352
595
/* ------------------------------------------------------------------------- */
354
BYTE REGPARM1 reu_read(WORD addr)
596
/* helper functions */
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.
604
The address of the REC register to read
607
The value the register has
610
address must be in the valid range 0..0x1f
612
static BYTE reu_read_without_sideeffects(WORD addr)
616
addr &= REU_REG_LAST_REG;
359
619
case REU_REG_R_STATUS:
360
io_source=IO_SOURCE_REU;
361
retval = reu[REU_REG_R_STATUS];
363
/* Bits 7-5 are cleared when register is read, and pending IRQs are
365
reu[REU_REG_R_STATUS] &= ~0xe0;
366
maincpu_set_irq(reu_int_num, 0);
623
case REU_REG_RW_COMMAND:
624
retval = rec.command;
627
case REU_REG_RW_BASEADDR_LOW:
628
retval = rec.base_computer & 0xff;
631
case REU_REG_RW_BASEADDR_HIGH:
632
retval = (rec.base_computer >> 8) & 0xff;
635
case REU_REG_RW_RAMADDR_LOW:
636
retval = rec.base_reu & 0xff;
639
case REU_REG_RW_RAMADDR_HIGH:
640
retval = (rec.base_reu >> 8) & 0xff;
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;
647
case REU_REG_RW_BLOCKLEN_LOW:
648
retval = rec.transfer_length & 0xff;
651
case REU_REG_RW_BLOCKLEN_HIGH:
652
retval = (rec.transfer_length >> 8) & 0xff;
374
655
case REU_REG_RW_INTERRUPT:
375
io_source=IO_SOURCE_REU;
376
retval = reu[REU_REG_RW_INTERRUPT] | 0x1f;
379
case REU_REG_RW_ADDRCONTROL:
380
io_source=IO_SOURCE_REU;
381
retval = reu[REU_REG_RW_ADDRCONTROL] | 0x3f;
393
io_source=IO_SOURCE_REU;
656
assert( BITS_ARE_ALL_SET(rec.int_mask_reg, REU_REG_RW_INTERRUPT_UNUSED_MASK) );
657
retval = rec.int_mask_reg;
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;
398
log_message(reu_log, "read [$%02X] => $%02X.", addr, retval);
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.
675
The address of the REC register to write
678
The value to set the register to
681
address must be in the valid range 0..0x1f
683
static void reu_store_without_sideeffects(WORD addr, BYTE byte)
685
addr &= REU_REG_LAST_REG;
408
689
case REU_REG_R_STATUS:
409
690
/* REC status register is Read Only */
693
case REU_REG_RW_COMMAND:
412
697
case REU_REG_RW_BASEADDR_LOW:
413
/* update shadow register, too */
414
reu_baseaddr_low_shadow =
699
rec.base_computer_shadow = (rec.base_computer_shadow & 0xff00) | byte;
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;
704
rec.base_computer_shadow = (rec.base_computer_shadow & 0xff) | (byte << 8);
424
707
case REU_REG_RW_RAMADDR_LOW:
425
/* update shadow register, too */
426
reu_ramaddr_low_shadow =
709
rec.base_reu_shadow = (rec.base_reu_shadow & 0xff00) | byte;
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;
714
rec.base_reu_shadow = (rec.base_reu_shadow & 0xff) | (byte << 8);
717
case REU_REG_RW_BANK:
719
rec.bank_reu_shadow = byte & ~ rec_options.reg_bank_unused;
436
722
case REU_REG_RW_BLOCKLEN_LOW:
437
/* update shadow register, too */
438
reu_blocklen_low_shadow =
723
rec.transfer_length =
724
rec.transfer_length_shadow = (rec.transfer_length_shadow & 0xff00) | byte;
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;
728
rec.transfer_length =
729
rec.transfer_length_shadow = (rec.transfer_length_shadow & 0xff) | (byte << 8);
732
case REU_REG_RW_INTERRUPT:
733
rec.int_mask_reg = byte | REU_REG_RW_INTERRUPT_UNUSED_MASK;
736
case REU_REG_RW_ADDR_CONTROL:
737
rec.address_control_reg = byte | REU_REG_RW_ADDR_CONTROL_UNUSED_MASK;
453
log_message(reu_log, "store [$%02X] <= $%02X.", addr, (int)byte);
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);
462
/* ------------------------------------------------------------------------- */
745
/* ------------------------------------------------------------------------- */
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.
752
The address of the REC register to read
755
The value the register has
757
BYTE REGPARM1 reu_read(WORD addr)
763
if (addr < rec_options.first_unused_register_address) {
764
io_source = IO_SOURCE_REU;
766
retval = reu_read_without_sideeffects(addr);
769
case REU_REG_R_STATUS:
770
/* Bits 7-5 are cleared when register is read, and pending IRQs are
773
~(REU_REG_R_STATUS_VERIFY_ERROR
774
| REU_REG_R_STATUS_END_OF_BLOCK
775
| REU_REG_R_STATUS_INTERRUPT_PENDING
778
maincpu_set_irq(reu_int_num, 0);
784
DEBUG_LOG( DEBUG_LEVEL_REGISTER, (reu_log, "read [$%02X] => $%02X.", addr, retval) );
791
/*! \brief write the REU register values
792
This function is used to write the REU values from the computer.
795
The address of the REC register to write
798
The value to set the register to
800
void REGPARM2 reu_store(WORD addr, BYTE byte)
804
if (addr < rec_options.first_unused_register_address) {
805
reu_store_without_sideeffects(addr, byte);
807
DEBUG_LOG( DEBUG_LEVEL_REGISTER, (reu_log, "store [$%02X] <= $%02X.", addr, (int)byte) );
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);
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))
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);
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))
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);
845
/* ------------------------------------------------------------------------- */
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.
852
The address to be incremented
855
The increment. Must be either 0 or 1. If 0, reu_addr is not changed at all.
858
The incremented reu_addr, taking into account the wrap-around
861
unsigned int increment_reu_with_wrap_around(unsigned int reu_addr, unsigned int reu_step)
863
assert(((reu_step == 0) || (reu_step == 1)));
865
reu_addr += reu_step;
867
if ( (reu_addr == rec_options.special_wrap_around_1700)
868
|| (reu_addr == rec_options.wrap_around))
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.
881
The REU address where to store the value
884
The value to write into the REU.
887
If the location reu_addr is not backed up by DRAM, the store is simply
891
void store_to_reu(unsigned int reu_addr, BYTE value)
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;
899
DEBUG_LOG( DEBUG_LEVEL_NO_DRAM, (reu_log,
900
"--> writing to REU address %05X, but no DRAM!",
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.
910
The REU address where to read the value from
913
The value read from the REU.
916
If the location reu_addr is not backed up by DRAM, a dummy
920
Check the values a real 17xx returns.
923
BYTE read_from_reu(unsigned int reu_addr)
925
BYTE value = 0xff; /* dummy value to return if not DRAM is available */
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];
933
DEBUG_LOG( DEBUG_LEVEL_NO_DRAM, (reu_log,
934
"--> read from REU address %05X, but no DRAM!",
941
/* ------------------------------------------------------------------------- */
943
/*! \brief update the REU registers after a DMA operation
946
The host (computer) address the operation stopped at
949
The REU address the operation stopped at
952
The transfer length the operation stopped at
954
\param new_status_or_mask
955
A mask which is used to set bits in the status
958
if autoload is enabled, the shadow registers are written back
959
to the REU registers.
464
961
static void reu_dma_update_regs(WORD host_addr, unsigned int reu_addr,
962
int len, BYTE new_status_or_mask)
467
if (!(reu[REU_REG_W_COMMAND] & 0x20)) {
965
assert( new_status_or_mask != 0 );
967
reu_addr &= rec_options.wrap_around_mask_when_storing;
969
rec.status |= new_status_or_mask;
971
if (!(rec.command & REU_REG_RW_COMMAND_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
473
log_message(reu_log, "No autoload.");
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;
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);
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;
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;
986
rec.transfer_length = len & 0xFFFF;
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;
994
DEBUG_LOG( DEBUG_LEVEL_REGISTER, (reu_log, "Autoload.") );
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))
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);
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))
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);
1019
/*! \brief DMA operation writing from the host to the REU
1022
The host (computer) address where the operation starts
1025
The REU address where the operation starts
1028
The increment to use for the host address; must be either 0 or 1
1031
The increment to use for the REU address; must be either 0 or 1
1034
The transfer length of the operation
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)
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);
501
for (; len--; reu_addr += reu_step) {
1043
host_step ? "" : " (fixed)", len, len) );
1045
assert(((host_step == 0) || (host_step == 1)));
1046
assert(((reu_step == 0) || (reu_step == 1)));
503
1051
machine_handle_pending_alarms(0);
504
1052
value = mem_read(host_addr);
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);
1055
value, host_addr, reu_addr) );
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);
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);
1066
/*! \brief DMA operation writing from the REU to the host
1069
The host (computer) address where the operation starts
1072
The REU address where the operation starts
1075
The increment to use for the host address; must be either 0 or 1
1078
The increment to use for the REU address; must be either 0 or 1
1081
The transfer length of the operation
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)
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);
530
for (; len--; reu_addr += reu_step) {
1090
host_step ? "" : " (fixed)", len, len) );
1092
assert(((host_step == 0) || (host_step == 1)));
1093
assert(((reu_step == 0) || (reu_step == 1)));
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);
1099
reu_ram[reu_addr % reu_size], reu_addr, host_addr) );
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);
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);
1112
/*! \brief DMA operation swaping data between host and REU
1115
The host (computer) address where the operation starts
1118
The REU address where the operation starts
1121
The increment to use for the host address; must be either 0 or 1
1124
The increment to use for the REU address; must be either 0 or 1
1127
The transfer length of the operation
546
1129
static void reu_dma_swap(WORD host_addr, unsigned int reu_addr,
547
1130
int host_step, int reu_step, int len)
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);
557
for (; len--; reu_addr += reu_step ) {
558
c = reu_ram[reu_addr % reu_size];
1137
host_step ? "" : " (fixed)", len, len) );
1139
assert(((host_step == 0) || (host_step == 1)));
1140
assert(((reu_step == 0) || (reu_step == 1)));
1144
value_from_reu = read_from_reu(reu_addr);
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);
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);
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);
1163
/*! \brief DMA operation comparing data between host and REU
1166
The host (computer) address where the operation starts
1169
The REU address where the operation starts
1172
The increment to use for the host address; must be either 0 or 1
1175
The increment to use for the REU address; must be either 0 or 1
1178
The transfer length of the operation
572
1180
static void reu_dma_compare(WORD host_addr, unsigned int reu_addr,
573
1181
int host_step, int reu_step, int len)
1183
BYTE value_from_reu;
1184
BYTE value_from_c64;
1186
BYTE new_status_or_mask = 0;
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);
582
reu[REU_REG_R_STATUS] &= ~0x60;
1191
host_step ? "" : " (fixed)", len, len) );
1193
assert(((host_step == 0) || (host_step == 1)));
1194
assert(((reu_step == 0) || (reu_step == 1)));
1197
/* the real 17xx does not clear these bits on compare;
1198
* thus, we do not clear them, either! */
1200
/* rec.status &= ~ (REU_REG_R_STATUS_VERIFY_ERROR | REU_REG_R_STATUS_END_OF_BLOCK); */
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;
591
reu[REU_REG_R_STATUS] |= 0x20; /* FAULT */
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;
1213
if (value_from_reu != value_from_c64) {
1215
DEBUG_LOG( DEBUG_LEVEL_REGISTER, (reu_log, "VERIFY ERROR") );
1216
new_status_or_mask |= REU_REG_R_STATUS_VERIFY_ERROR;
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.
1224
machine_handle_pending_alarms(0);
601
host_addr = (host_addr + host_step) & 0xffff;;
602
reu_addr += reu_step;
1230
/* the length was decremented once too much, correct this */
1234
/* weird behaviour no. 2 of the 17xx:
1235
* If the last byte failed, the "end of block transfer" bit is set, too
606
1237
/* all bytes are equal, mark End Of Block */
607
reu[REU_REG_R_STATUS] |= 0x40;
611
reu_dma_update_regs(host_addr, reu_addr, len);
1238
new_status_or_mask |= REU_REG_R_STATUS_END_OF_BLOCK;
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
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;
1257
reu_dma_update_regs(host_addr, reu_addr, len, new_status_or_mask);
614
1260
/* ------------------------------------------------------------------------- */
616
/* This function is called when write to REC command register or memory
617
* location FF00 is detected.
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.
623
/* Added correct handling of fixed addresses with transfer length 1 - RH */
624
/* Added fixed address support - [EP] */
626
void reu_dma(int immed)
1262
/*! \brief perform REU DMA
1264
This function is called when a write to REC command register or memory
1265
location FF00 is detected.
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.
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
1284
void reu_dma(int immediate)
628
1286
static int delay = 0;
630
1288
int reu_step, host_step;
632
unsigned int reu_addr, reu6_mask;
1290
unsigned int reu_addr;
634
1292
if (!reu_enabled)
641
if (!delay && immed < 0)
1299
if (!delay && immediate < 0)
646
reu6_mask = (reu_size >> 16) - 1;
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));
655
len = (int)(reu[REU_REG_RW_BLOCKLEN_LOW])
656
| ((int)(reu[REU_REG_RW_BLOCKLEN_HIGH]) << 8);
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;
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;
665
switch (reu[REU_REG_W_COMMAND] & 0x03) {
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);
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);
1320
case REU_REG_RW_COMMAND_TRANSFER_TYPE_SWAP:
673
1321
reu_dma_swap(host_addr, reu_addr, host_step, reu_step, len);
1323
case REU_REG_RW_COMMAND_TRANSFER_TYPE_VERIFY:
676
1324
reu_dma_compare(host_addr, reu_addr, host_step, reu_step, len);
680
reu[REU_REG_W_COMMAND] &= 0x7f;
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);
1328
rec.command = (rec.command & ~ REU_REG_RW_COMMAND_EXECUTE)
1329
| REU_REG_RW_COMMAND_FF00_TRIGGER_DISABLED;
690
1332
/* ------------------------------------------------------------------------- */
692
static char snap_module_name[] = "REU1764";
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 */
1338
/*! \brief type for the REU data as being stored in the snapshot.
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.
1344
typedef BYTE reu_as_stored_in_snapshot_t[16];
1346
/*! \brief write the REU module data to the snapshot
1348
The snapshot data where to add the information for this module.
1351
0 on success, else -1.
696
1353
int reu_write_snapshot_module(snapshot_t *s)
698
1355
snapshot_module_t *m;
1357
reu_as_stored_in_snapshot_t reu;
1360
memset(reu, 0xff, sizeof reu);
1362
for (reu_address = 0; reu_address < sizeof(reu); reu_address++) {
1363
reu[reu_address] = reu_read_without_sideeffects(reu_address);
700
1366
m = snapshot_module_create(s, snap_module_name, SNAP_MAJOR, SNAP_MINOR);