49 # define DEBUGDMA(...) DEBUGPRINT(__VA_ARGS__)
51 # define DEBUGDMA(...) DEBUG(__VA_ARGS__)
65 static unsigned int dma_transparency;
81 static Uint8 minterms[4];
82 static int in_dma_update;
83 static int dma_self_write_warning;
85 static int filler_byte;
110 #define DMA_ADDR_INTEGER_PART(p) ((p)>>8)
111 #define DMA_SOURCE_SKIP_RATE ((int)(dma_registers[0x08] | (dma_registers[0x09] << 8)))
112 #define DMA_TARGET_SKIP_RATE ((int)(dma_registers[0x0A] | (dma_registers[0x0B] << 8)))
113 #define DMA_ADDR_FRACT_PART(p) ((p) & 0xFF)
115 #define DMA_ADDRESSING(channel) ((DMA_ADDR_INTEGER_PART(channel.addr) & channel.mask) + channel.base)
136 #define MEM_LIST_MASK 0xFFFF
137 #define MEM_ADDR_MASK 0xFFFFF
140 #define DMA_READ_SOURCE() (XEMU_UNLIKELY(source.is_io) ? DMA_SOURCE_IOREADER_FUNC(DMA_ADDRESSING(source)) : DMA_SOURCE_MEMREADER_FUNC(DMA_ADDRESSING(source)))
141 #define DMA_READ_TARGET() (XEMU_UNLIKELY(target.is_io) ? DMA_TARGET_IOREADER_FUNC(DMA_ADDRESSING(target)) : DMA_TARGET_MEMREADER_FUNC(DMA_ADDRESSING(target)))
145 #define DMA_WRITE_SOURCE(data) do { \
146 if (XEMU_UNLIKELY(source.is_io)) \
147 DMA_SOURCE_IOWRITER_FUNC(DMA_ADDRESSING(source), data); \
149 DMA_SOURCE_MEMWRITER_FUNC(DMA_ADDRESSING(source), data); \
151 #define DMA_WRITE_TARGET(data) do { \
152 if (XEMU_UNLIKELY(target.is_io)) \
153 DMA_TARGET_IOWRITER_FUNC(DMA_ADDRESSING(target), data); \
155 DMA_TARGET_MEMWRITER_FUNC(DMA_ADDRESSING(target), data); \
183 #define DMA_READ_LIST_NEXT_BYTE() DMA_LIST_READER_FUNC(((list_addr++) & MEM_LIST_MASK) | list_base)
185 static int dma_list_entry_pos = 0;
200 source.addr += source.step;
201 target.addr += target.step;
207 target.addr += target.step;
216 source.addr += source.step;
217 target.addr += target.step;
230 (( sa) & ( da) & minterms[3]) |
231 (( sa) & (~da) & minterms[2]) |
232 ((~sa) & ( da) & minterms[1]) |
233 ((~sa) & (~da) & minterms[0]) ;
235 source.addr += source.step;
236 target.addr += target.step;
252 if (dma_self_write_warning) {
253 dma_self_write_warning = 0;
254 ERROR_WINDOW(
"DMA writes its own registers, ignoring!\nThere will be no more warning on this!");
256 DEBUG(
"DMA: WARNING: tries to write own register by DMA reg#%d with value of $%02X" NL,
addr,
data);
260 hack.enhanced_dma = 0;
271 hack.enhanced_dma = 1;
280 FATAL(
"dma_write_reg(): new DMA op with dma_status != 0");
282 if (hack.enhanced_dma) {
283 DEBUGDMA(
"DMA: initiation of ENCHANCED MODE DMA!!!!\n");
294 DEBUGDMA(
"DMA: initiation of normal mode DMA\n");
296 DEBUGDMA(
"DMA: list address is $%06X now, just written to register %d value $%02X @ PC=$%04X" NL, list_base | list_addr,
addr,
data, cpu65.pc);
299 cpu65.multi_step_stop_trigger = 1;
305 return in_dma_update;
320 FATAL(
"dma_update() called with no dma_status set!");
331 if (hack.enhanced_dma) {
337 DEBUGDMA(
"DMA: enhanced option byte $%02X read" NL, opt);
341 dma_transparency |= 0x100;
344 dma_transparency &= 0xFF;
385 DEBUGPRINT(
"DMA: *unknown* enhanced option: $%02X @ PC=$%04X" NL, opt, cpu65.pc);
405 DEBUG(
"DMA: WARNING: M65 software wants to change DMA revision, but you did not allow it!" NL);
410 dma_list_entry_pos = 0;
416 length = modulo.col_limit | (modulo.row_limit << 8);
435 source.is_modulo = (subcommand & 1);
436 target.is_modulo = (subcommand & 4);
439 minterms[0] = (subcommand & 16) ? 0xFF : 0x00;
440 minterms[1] = (subcommand & 32) ? 0xFF : 0x00;
441 minterms[2] = (subcommand & 64) ? 0xFF : 0x00;
442 minterms[3] = (subcommand & 128) ? 0xFF : 0x00;
449 source.is_modulo = (source.addr & 0x200000);
450 target.is_modulo = (target.addr & 0x200000);
452 minterms[0] = (command & 16) ? 0xFF : 0x00;
453 minterms[1] = (command & 32) ? 0xFF : 0x00;
454 minterms[2] = (command & 64) ? 0xFF : 0x00;
455 minterms[3] = (command & 128) ? 0xFF : 0x00;
463 if (modulo.enabled) {
465 modulo.col_counter = 0;
466 modulo.row_counter = 0;
468 if (!modulo.col_limit)
469 modulo.col_limit = 0x100;
470 if (!modulo.row_limit)
471 modulo.row_limit = 0x100;
474 DEBUGPRINT(
"DMA: warning, MODulo mode wanted to be used, but not enabled by you!" NL);
482 if (source.is_modulo || target.is_modulo)
483 DEBUG(
"DMA: denying using MODulo ..." NL);
484 source.is_modulo = 0;
485 target.is_modulo = 0;
489 source.is_io = (source.addr & 0x800000);
490 target.is_io = (target.addr & 0x800000);
495 source.addr = (source.addr & 0xFFF) << 8;
502 source.base = (source.addr & 0x0F0000) | (((
dma_registers[5] << 20) + (source.addr & 0x700000)) & 0xFF00000);
504 source.base = (source.addr & 0x0F0000) | (
dma_registers[5] << 20);
505 source.addr = (source.addr & 0x00FFFF) << 8;
511 target.addr = (target.addr & 0xFFF) << 8;
515 target.base = (target.addr & 0x0F0000) | (((
dma_registers[6] << 20) + (target.addr & 0x700000)) & 0xFF00000);
517 target.base = (target.addr & 0x0F0000) | (
dma_registers[6] << 20);
518 target.addr = (target.addr & 0x00FFFF) << 8;
521 chained = (command & 4);
523 DEBUG(
"DMA: READ COMMAND: $%07X[%s%s %d:%d] -> $%07X[%s%s %d:%d] (L=$%04X) CMD=%d (%s)" NL,
526 length, dma_op, chained ?
"CHAINED" :
"LAST"
558 if (modulo.col_counter == modulo.col_limit) {
559 if (modulo.row_counter == modulo.row_limit) {
564 modulo.col_counter = 0;
565 modulo.row_counter++;
566 if (source.is_modulo)
567 source.addr += modulo.value;
568 if (target.is_modulo)
569 target.addr += modulo.value;
572 modulo.col_counter++;
579 DEBUGDMA(
"DMA: end of operation, but chained!" NL);
583 DEBUGDMA(
"DMA: end of operation, no chained next one." NL);
586 if (hack.enhanced_dma) {
587 DEBUGDMA(
"DMA: enhanced-end-of-op, restoring context" NL);
590 hack.enhanced_dma = 0;
601 dma_transparency = 0x100;
615 }
while (cycles <= do_for_cycles &&
dma_status);
623 const int rom_suggested_dma_revision = (rom_date < 900000 || rom_date > 910522 ||
rom_is_openroms);
627 FATAL(
"Unknown DMA revision value tried to be set (%d)!", revision);
628 }
else if (revision == 2) {
630 FATAL(
"dma_ini_set_rev(): revision == 2 (auto-detect) but rom == NULL (cannot auto-detect)");
632 WARNING_WINDOW(
"ROM version cannot be detected, and DMA revision auto-detection was requested.\nDefaulting to revision %d.\nWarning, this may cause incorrect behaviour!", rom_suggested_dma_revision);
641 DEBUGPRINT(
"DMA: setting chip revision to #%d based on configuration/command line request (forced). Suggested revision by ROM date: #%d" NL,
dma_chip_initial_revision, rom_suggested_dma_revision);
651 hack.enhanced_dma = 0;
656 DEBUGPRINT(
"DMA: 'hack' (preliminary!! support for new-style M65 DMA) status: %s" NL, hack.enabled ?
"**ENABLED**" :
"disabled");
660 FATAL(
"Unknown DMA revision value tried to be set (%d)!", revision);
665 DEBUGPRINT(
"DMA: initializing DMA engine for chip revision %d (initially, may be modified later!), dyn_mode=%s, modulo_support=%s." NL,
668 modulo.enabled ?
"ENABLED" :
"DISABLED"
683 dma_self_write_warning = 1;
688 dma_transparency = 0x100;
696 DEBUG(
"DMA: register reading at addr of %d" NL,
addr);
707 #ifdef XEMU_SNAPSHOT_SUPPORT
715 #define SNAPSHOT_DMA_BLOCK_VERSION 2
716 #define SNAPSHOT_DMA_BLOCK_SIZE 0x100
719 int dma_snapshot_load_state (
const struct xemu_snapshot_definition_st *def,
struct xemu_snapshot_block_st *
block )
721 Uint8 buffer[SNAPSHOT_DMA_BLOCK_SIZE];
723 if (
block->block_version != SNAPSHOT_DMA_BLOCK_VERSION ||
block->sub_counter ||
block->sub_size !=
sizeof buffer)
724 RETURN_XSNAPERR_USER(
"Bad C65 block syntax");
725 a = xemusnap_read_file(buffer,
sizeof buffer);
732 modulo.enabled = buffer[0x83];
734 in_dma_update = buffer[0x85];
739 int dma_snapshot_save_state (
const struct xemu_snapshot_definition_st *def )
741 Uint8 buffer[SNAPSHOT_DMA_BLOCK_SIZE];
742 int a = xemusnap_write_block_header(def->idstr, SNAPSHOT_DMA_BLOCK_VERSION);
744 memset(buffer, 0xFF,
sizeof buffer);
750 buffer[0x83] = modulo.enabled ? 1 : 0;
752 buffer[0x85] = in_dma_update ? 1 : 0;
754 WARNING_WINDOW(
"f018_core DMA snapshot save: snapshot with DMA pending! Snapshot WILL BE incorrect on loading! FIXME!");
755 return xemusnap_write_sub_block(buffer,
sizeof buffer);