46 # define DEBUGDMA(...) DEBUGPRINT(__VA_ARGS__)
48 # define DEBUGDMA(...) DEBUG(__VA_ARGS__)
71 static Uint8 minterms[4];
72 static int in_dma_update;
73 static int dma_self_write_warning;
75 static int filler_byte;
77 #define DMA_ADDRESSING(channel) ((channel.addr & channel.mask) | channel.base)
96 #define DMA_READ_SOURCE() (XEMU_UNLIKELY(source.is_io) ? DMA_SOURCE_IOREADER_FUNC(DMA_ADDRESSING(source)) : DMA_SOURCE_MEMREADER_FUNC(DMA_ADDRESSING(source)))
97 #define DMA_READ_TARGET() (XEMU_UNLIKELY(target.is_io) ? DMA_TARGET_IOREADER_FUNC(DMA_ADDRESSING(target)) : DMA_TARGET_MEMREADER_FUNC(DMA_ADDRESSING(target)))
98 #define DMA_WRITE_SOURCE(data) do { \
99 if (XEMU_UNLIKELY(source.is_io)) \
100 DMA_SOURCE_IOWRITER_FUNC(DMA_ADDRESSING(source), data); \
102 DMA_SOURCE_MEMWRITER_FUNC(DMA_ADDRESSING(source), data); \
104 #define DMA_WRITE_TARGET(data) do { \
105 if (XEMU_UNLIKELY(target.is_io)) \
106 DMA_TARGET_IOWRITER_FUNC(DMA_ADDRESSING(target), data); \
108 DMA_TARGET_MEMWRITER_FUNC(DMA_ADDRESSING(target), data); \
114 #define DMA_READ_LIST_NEXT_BYTE() DMA_LIST_READER_FUNC(((list_addr++) & 0xFFFF) | list_base)
116 static int dma_list_entry_pos = 0;
120 int addr = ((list_addr++) & 0xFFFF) | list_base;
131 source.addr += source.step;
132 target.addr += target.step;
138 target.addr += target.step;
147 source.addr += source.step;
148 target.addr += target.step;
161 (( sa) & ( da) & minterms[3]) |
162 (( sa) & (~da) & minterms[2]) |
163 ((~sa) & ( da) & minterms[1]) |
164 ((~sa) & (~da) & minterms[0]) ;
166 source.addr += source.step;
167 target.addr += target.step;
183 if (dma_self_write_warning) {
184 dma_self_write_warning = 0;
185 ERROR_WINDOW(
"DMA writes its own registers, ignoring!\nThere will be no more warning on this!");
187 DEBUG(
"DMA: WARNING: tries to write own register by DMA reg#%d with value of $%02X" NL,
addr,
data);
191 DEBUG(
"DMA: trying to write M65-specific DMA register (%d) with a C65 ..." NL,
addr);
198 FATAL(
"dma_write_reg(): new DMA op with dma_status != 0");
201 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);
204 cpu65.multi_step_stop_trigger = 1;
220 FATAL(
"dma_update() called with no dma_status set!");
226 dma_list_entry_pos = 0;
232 length = modulo.col_limit | (modulo.row_limit << 8);
248 source.step = (subcommand & 2) ? 0 : ((command & 16) ? -1 : 1);
249 target.step = (subcommand & 8) ? 0 : ((command & 32) ? -1 : 1);
250 source.is_modulo = (subcommand & 1);
251 target.is_modulo = (subcommand & 4);
254 minterms[0] = (subcommand & 16) ? 0xFF : 0x00;
255 minterms[1] = (subcommand & 32) ? 0xFF : 0x00;
256 minterms[2] = (subcommand & 64) ? 0xFF : 0x00;
257 minterms[3] = (subcommand & 128) ? 0xFF : 0x00;
262 source.step = (source.addr & 0x100000) ? 0 : ((source.addr & 0x400000) ? -1 : 1);
263 target.step = (target.addr & 0x100000) ? 0 : ((target.addr & 0x400000) ? -1 : 1);
264 source.is_modulo = (source.addr & 0x200000);
265 target.is_modulo = (target.addr & 0x200000);
267 minterms[0] = (command & 16) ? 0xFF : 0x00;
268 minterms[1] = (command & 32) ? 0xFF : 0x00;
269 minterms[2] = (command & 64) ? 0xFF : 0x00;
270 minterms[3] = (command & 128) ? 0xFF : 0x00;
278 if (modulo.enabled) {
280 modulo.col_counter = 0;
281 modulo.row_counter = 0;
283 if (!modulo.col_limit)
284 modulo.col_limit = 0x100;
285 if (!modulo.row_limit)
286 modulo.row_limit = 0x100;
289 DEBUGPRINT(
"DMA: warning, MODulo mode wanted to be used, but not enabled by you!" NL);
297 if (source.is_modulo || target.is_modulo)
298 DEBUG(
"DMA: denying using MODulo ..." NL);
299 source.is_modulo = 0;
300 target.is_modulo = 0;
304 source.is_io = (source.addr & 0x800000);
305 target.is_io = (target.addr & 0x800000);
310 source.addr = (source.addr & 0xFFF);
312 source.mask = 0xFFFF;
314 source.base = (source.addr & 0x7F0000);
316 source.base = (source.addr & 0x0F0000);
317 source.addr = (source.addr & 0x00FFFF);
323 target.addr = (target.addr & 0xFFF);
325 target.mask = 0xFFFF;
327 target.base = (target.addr & 0x7F0000);
329 target.base = (target.addr & 0x0F0000);
330 target.addr = (target.addr & 0x00FFFF);
333 chained = (command & 4);
334 DEBUG(
"DMA: READ COMMAND: $%07X[%s%s %d] -> $%07X[%s%s %d] (L=$%04X) CMD=%d (%s)" NL,
335 DMA_ADDRESSING(source), source.is_io ?
"I/O" :
"MEM", source.is_modulo ?
" MOD" :
"", source.step,
336 DMA_ADDRESSING(target), target.is_io ?
"I/O" :
"MEM", target.is_modulo ?
" MOD" :
"", target.step,
337 length, dma_op, chained ?
"CHAINED" :
"LAST"
369 if (modulo.col_counter == modulo.col_limit) {
370 if (modulo.row_counter == modulo.row_limit) {
375 modulo.col_counter = 0;
376 modulo.row_counter++;
377 if (source.is_modulo)
378 source.addr += modulo.value;
379 if (target.is_modulo)
380 target.addr += modulo.value;
383 modulo.col_counter++;
390 DEBUGDMA(
"DMA: end of operation, but chained!" NL);
394 DEBUGDMA(
"DMA: end of operation, no chained next one." NL);
410 }
while (cycles <= do_for_cycles &&
dma_status);
418 DEBUGPRINT(
"ROM: version check is disabled (NULL pointer), previous version info: %d" NL,
rom_date);
419 }
else if (p[0] == 0x56) {
421 for (
int a = 0; a < 6; a++) {
423 if (*p >=
'0' && *p <=
'9')
427 DEBUGPRINT(
"ROM: version check failed (num-numberic character)" NL);
433 DEBUGPRINT(
"ROM: version check failed (no leading 'V')" NL);
442 int rom_suggested_dma_revision = (rom_date < 900000 || rom_date > 910522);
443 DEBUGPRINT(
"ROM: version check suggests DMA revision %d" NL, rom_suggested_dma_revision);
446 FATAL(
"Unknown DMA revision value tried to be set (%d)!", revision);
447 }
else if (revision == 2) {
448 if (!rom_ver_signature)
449 FATAL(
"dma_ini_set_rev(): revision == 2 (auto-detect) but rom_ver_signature == NULL (cannot auto-detect)");
451 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);
460 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);
470 FATAL(
"DMA feature DMA_FEATRUE_DYNMODESET is not supported on C65!");
474 FATAL(
"Unknown DMA revision value tried to be set (%d)!", revision);
479 DEBUGPRINT(
"DMA: initializing DMA engine for chip revision %d (initially, may be modified later!), dyn_mode=%s, modulo_support=%s." NL,
482 modulo.enabled ?
"ENABLED" :
"DISABLED"
497 dma_self_write_warning = 1;
505 DEBUG(
"DMA: register reading at addr of %d" NL,
addr);
516 #ifdef XEMU_SNAPSHOT_SUPPORT
524 #define SNAPSHOT_DMA_BLOCK_VERSION 2
525 #define SNAPSHOT_DMA_BLOCK_SIZE 0x100
528 int dma_snapshot_load_state (
const struct xemu_snapshot_definition_st *def,
struct xemu_snapshot_block_st *
block )
530 Uint8 buffer[SNAPSHOT_DMA_BLOCK_SIZE];
532 if (
block->block_version != SNAPSHOT_DMA_BLOCK_VERSION ||
block->sub_counter ||
block->sub_size !=
sizeof buffer)
533 RETURN_XSNAPERR_USER(
"Bad C65 block syntax");
534 a = xemusnap_read_file(buffer,
sizeof buffer);
540 modulo.enabled = buffer[0x83];
542 in_dma_update = buffer[0x85];
547 int dma_snapshot_save_state (
const struct xemu_snapshot_definition_st *def )
549 Uint8 buffer[SNAPSHOT_DMA_BLOCK_SIZE];
550 int a = xemusnap_write_block_header(def->idstr, SNAPSHOT_DMA_BLOCK_VERSION);
552 memset(buffer, 0xFF,
sizeof buffer);
557 buffer[0x83] = modulo.enabled ? 1 : 0;
559 buffer[0x85] = in_dma_update ? 1 : 0;
561 WARNING_WINDOW(
"f018_core DMA snapshot save: snapshot with DMA pending! Snapshot WILL BE incorrect on loading! FIXME!");
562 return xemusnap_write_sub_block(buffer,
sizeof buffer);