Skip to content

Commit 5a9dc9e

Browse files
committed
MEGA65: implement DMA fractional initial addresses
First try to implement the enhanced mode DMA list options $91 and $92 as described here: MEGA65/mega65-core#903 [DEPLOYMENT]
1 parent daf7300 commit 5a9dc9e

File tree

1 file changed

+22
-2
lines changed

1 file changed

+22
-2
lines changed

targets/mega65/dma65.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ struct ldm_st {
8080
// source and target DMA "channels":
8181
static struct dma_channel_st {
8282
int addr; // address of the current operation, it's a fixed-point math value
83+
Uint8 addr_fract; // address fractional part, used during transition from DMA info fetch and starting the actual DMA, but not during the DMA (will be low byte of "addr", fixed point math!)
8384
int base; // base address for "addr", always a "pure" number! It also contains the "megabyte selection", pre-shifted by << 20
8485
int step; // step value, zero(HOLD)/negative/positive, this is a fixed point arithmetic value!!
8586
Uint8 step_fract; // step value during option read, fractional part only
@@ -345,6 +346,8 @@ void dma_write_reg ( int addr, Uint8 data )
345346
source.mbyte = 0; // source MB
346347
target.mbyte = 0; // target MB
347348
length_byte3 = 0; // length byte for >=64K DMA sessions
349+
source.addr_fract = 0;
350+
target.addr_fract = 0;
348351
// zero out LDM-specific options by default
349352
memset(&source.ldm, 0, sizeof source.ldm);
350353
memset(&target.ldm, 0, sizeof target.ldm);
@@ -466,6 +469,12 @@ int dma_update ( void )
466469
case 0x90: // extra high byte of DMA length (bits 23-16) to allow to have >64K DMA
467470
length_byte3 = optval;
468471
break;
472+
case 0x91: // set initial fractional part of the source
473+
source.addr_fract = optval;
474+
break;
475+
case 0x92: // set initial fractional part of the target
476+
target.addr_fract = optval;
477+
break;
469478
case 0x97: // DMA line drawing mode SOURCE - X col (LSB)
470479
source.ldm.x_col = (source.ldm.x_col & 0xFF0000U) + (optval << 8); // Xemu integer + 8 bit fractional part arithmetic!
471480
break;
@@ -609,13 +618,13 @@ int dma_update ( void )
609618
source.base = ((source.mbyte << 20) + (source.addr & 0x700000)) & 0xFF00000;
610619
else
611620
source.base = source.mbyte << 20;
612-
source.addr = (source.addr & 0x0FFFFF) << 8;// offset from base, for M65 this *IS* fixed point arithmetic!
621+
source.addr = ((source.addr & 0x0FFFFF) << 8) + source.addr_fract; // offset from base, for M65 this *IS* fixed point arithmetic!
613622
/* -- target selection -- see similar lines with comments above, for source ... */
614623
if (session_revision)
615624
target.base = ((target.mbyte << 20) + (target.addr & 0x700000)) & 0xFF00000;
616625
else
617626
target.base = target.mbyte << 20;
618-
target.addr = (target.addr & 0x0FFFFF) << 8;
627+
target.addr = ((target.addr & 0x0FFFFF) << 8) + target.addr_fract;
619628
/* other stuff */
620629
chained = (command & 4);
621630
// FIXME: this is a debug mesg, yeah, but with fractional step on M65, the step values needs to be interpreted with keep in mind the fixed point math ...
@@ -678,6 +687,17 @@ int dma_update ( void )
678687
if (chained) { // chained?
679688
DEBUGDMA("DMA: end of operation, but chained!" NL);
680689
in_dma = 0x81; // still busy then, with also bit0 set (chained)
690+
#if 0
691+
// In case of chained DMA, fractonal part is carried over from the last state
692+
// TODO: do we need this? As far as I can tell from the VHDL, we don't. So let's delete this part, if I am sure.
693+
source.addr_fract = source.addr & 0xFF;
694+
target.addr_fract = target.addr & 0xFF;
695+
#else
696+
source.addr_fract = 0;
697+
target.addr_fract = 0;
698+
#endif
699+
// TODO/FIXME: I should really overview if any param should be reset here, like fractional stepping, byte3 of length, etc ...
700+
// To put it into another way: enhanced mode options are "sticky" and always remaining for the chained sessions?
681701
} else {
682702
DEBUGDMA("DMA: end of operation, no chained next one." NL);
683703
in_dma = 0; // end of DMA command

0 commit comments

Comments
 (0)