Skip to content

Commit daf7300

Browse files
committed
MEGA65: line-DMA fixes #404
Suggested by @MirageBD Thanks! Later, I've realized that these changes were already mentioned by @bjotos and I've even dropped a like on that post: #404 (comment) Shamefully I have forgotten about that soon, and just now I realized this, sorry about that. And thanks!!
1 parent 8fb7aef commit daf7300

File tree

1 file changed

+13
-9
lines changed

1 file changed

+13
-9
lines changed

targets/mega65/dma65.c

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* F018 DMA core emulation for MEGA65
22
Part of the Xemu project. https://github.com/lgblgblgb/xemu
3-
Copyright (C)2016-2024 LGB (Gábor Lénárt) <[email protected]>
3+
Copyright (C)2016-2025 LGB (Gábor Lénárt) <[email protected]>
44
55
This program is free software; you can redistribute it and/or modify
66
it under the terms of the GNU General Public License as published by
@@ -195,18 +195,21 @@ static XEMU_INLINE void address_stepping ( struct dma_channel_st *const channel
195195
// otherwise, we must deal with LDM. The following code is based
196196
// on ideas found in a sample C implementation written by btoschi. THANKS!!
197197
// WARNING: in Xemu, I use a single variable for "addr" and lower 8 bit is the fractional part!!
198+
channel->ldm.slope_accu += channel->ldm.slope;
198199
if (channel->ldm.slope_type & 0x40) {
199200
channel->addr += 0x800U; // +8 -> we always step in Y
201+
// Not sure it's correct at all. TODO: need some test material using this
202+
if ((channel->addr & (7 << (3 + 8))) == (7 << (3 + 8)))
203+
channel->addr += channel->ldm.y_col;
200204
if (channel->ldm.slope_accu > 0xFFFFU) {
201205
channel->ldm.slope_accu &= 0xFFFFU;
202206
if (channel->ldm.slope_type & 0x20)
203207
channel->addr -= ((channel->addr & 0x700) == 0) ? channel->ldm.x_col + 0x100 : 0x100;
204208
else
205-
channel->addr += ((channel->addr & 0x700) == 0) ? channel->ldm.x_col + 0x100 : 0x100;
209+
channel->addr += ((channel->addr & 0x700) == 0x700) ? channel->ldm.x_col + 0x100 : 0x100;
206210
}
207211
} else {
208212
channel->addr += ((channel->addr & 0x700) == 0x700) ? channel->ldm.x_col + 0x100 : 0x100;
209-
channel->ldm.slope_accu += channel->ldm.slope;
210213
if (channel->ldm.slope_accu > 0xFFFFU) {
211214
channel->ldm.slope_accu &= 0xFFFFU;
212215
channel->addr += (channel->ldm.slope_type & 0x20) ? -0x800 : 0x800;
@@ -342,8 +345,9 @@ void dma_write_reg ( int addr, Uint8 data )
342345
source.mbyte = 0; // source MB
343346
target.mbyte = 0; // target MB
344347
length_byte3 = 0; // length byte for >=64K DMA sessions
345-
source.ldm.slope_type = 0; // source: line drawing mode, slope type, do not enable line drawing mode by default
346-
target.ldm.slope_type = 0; // target: -- "" --
348+
// zero out LDM-specific options by default
349+
memset(&source.ldm, 0, sizeof source.ldm);
350+
memset(&target.ldm, 0, sizeof target.ldm);
347351
mb_cross = mb_cross_global; // allow to cross megabyte boundaries
348352
if (enhanced_mode)
349353
DEBUGDMA("DMA: initiation of ENCHANCED MODE DMA!!!!\n");
@@ -439,10 +443,10 @@ int dma_update ( void )
439443
target.ldm.x_col = (target.ldm.x_col & 0x00FF00U) + (optval << 16); // Xemu integer + 8 bit fractional part arithmetic!
440444
break;
441445
case 0x89: // DMA line drawing mode TARGET - Row Y col (LSB)
442-
target.ldm.y_col = (target.ldm.y_col & 0xFF00U) + optval;
446+
target.ldm.y_col = (target.ldm.y_col & 0xFF0000U) + (optval << 8); // Xemu integer + 8 bit fractional part arithmetic!
443447
break;
444448
case 0x8A: // DMA line drawing mode TARGET - Row Y col (MSB)
445-
target.ldm.y_col = (target.ldm.y_col & 0x00FFU) + (optval << 8);
449+
target.ldm.y_col = (target.ldm.y_col & 0x00FF00U) + (optval << 16); // Xemu integer + 8 bit fractional part arithmetic!
446450
break;
447451
case 0x8B: // DMA line drawing mode TARGET - Slope (LSB)
448452
target.ldm.slope = (target.ldm.slope & 0xFF00U) + optval;
@@ -469,10 +473,10 @@ int dma_update ( void )
469473
source.ldm.x_col = (source.ldm.x_col & 0x00FF00U) + (optval << 16); // Xemu integer + 8 bit fractional part arithmetic!
470474
break;
471475
case 0x99: // DMA line drawing mode SOURCE - Row Y col (LSB)
472-
source.ldm.y_col = (source.ldm.y_col & 0xFF00U) + optval;
476+
source.ldm.y_col = (source.ldm.y_col & 0xFF0000U) + (optval << 8); // Xemu integer + 8 bit fractional part arithmetic!
473477
break;
474478
case 0x9A: // DMA line drawing mode SOURCE - Row Y col (MSB)
475-
source.ldm.y_col = (source.ldm.y_col & 0x00FFU) + (optval << 8);
479+
source.ldm.y_col = (source.ldm.y_col & 0x00FF00U) + (optval << 16); // Xemu integer + 8 bit fractional part arithmetic!
476480
break;
477481
case 0x9B: // DMA line drawing mode SOURCE - Slope (LSB)
478482
source.ldm.slope = (source.ldm.slope & 0xFF00U) + optval;

0 commit comments

Comments
 (0)