From 2dec3250d04e25957aefc133fe7cb4c9f3f01fdd Mon Sep 17 00:00:00 2001 From: Jan Vos Date: Wed, 18 Mar 2026 23:17:37 +0100 Subject: [PATCH 1/9] process 128x16 as a 128x32 frame - first attempt --- src/dmdreader.cpp | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/dmdreader.cpp b/src/dmdreader.cpp index 2602357..a5848ea 100644 --- a/src/dmdreader.cpp +++ b/src/dmdreader.cpp @@ -609,8 +609,9 @@ void dmd_dma_handler() { detected_0_1_0_1 = false; detected_1_0_0_0 = false; - // Used for Data East 128x16 to correctly align 64x16 + 64x16 - int16_t diff = 0; + // Used for Data East 128x16 to correctly align 64x16 + 64x16. + // Also lets the frame start exactly in the middle of a 128x32 frame. + int16_t diff = 255; // Fix byte order within the buffer uint32_t *planebuf = (uint32_t *)currentPlaneBuffer; @@ -725,8 +726,7 @@ void dmd_dma_handler() { // work its way back to 0. This way we prepare framebuf for // oversampling if (px == ((source_dwordsperplane / 2) - 1)) { - diff -= - 8; // we immediately decrement once to select the correct row + diff -= 8; // immediately decrement once to select the correct row diff *= -1; } } @@ -744,11 +744,11 @@ void dmd_dma_handler() { if (dmd_type == DMD_DE_X16_V1 || dmd_type == DMD_DE_X16_V2) { // merge the rows and convert from 4bpp to 2bpp with a LUT uint32_t *dst, *src1, *src2; - dst = src1 = framebuf; + dst = src1 = framebuf + 255; // start in the middle of 128x32 frame src2 = src1 + source_dwordsperline; if (dmd_type == DMD_DE_X16_V1) { - for (int l = 0; l < source_height; l++) { + for (int l = 0; l < source_height / 2; l++) { for (int w = 0; w < source_dwordsperline; w++) { uint32_t out = w >> 1; // Shifting leads to 0, 0, 1, 1, etc uint16_t v16 = convert_4bit_to_2bit_de_x16((src1[w] * 3)); @@ -765,7 +765,7 @@ void dmd_dma_handler() { } } else { // DMD_DE_X16_V2 case - for (int l = 0; l < source_height; l++) { + for (int l = 0; l < source_height / 2; l++) { for (int w = 0; w < source_dwordsperline; w++) { uint32_t out = w >> 1; // Shifting leads to 0, 0, 1, 1, etc uint16_t v16 = convert_4bit_to_2bit_de_x16((src1[w] + src2[w] * 2)); @@ -1023,7 +1023,7 @@ bool dmdreader_init(bool return_on_no_detection) { // we need it to sample data on the rising edge source_width = 128; - source_height = 16; + source_height = 32; // is actually 16, but we process as 32 source_bitsperpixel = 4; // recorded as 4bpp in the pio target_bitsperpixel = 2; // max pixel value is 3 // in DE-Sega, there's only one plane, @@ -1061,7 +1061,7 @@ bool dmdreader_init(bool return_on_no_detection) { pio_sm_exec(frame_pio, frame_sm, pio_encode_pull(false, false)); source_width = 128; - source_height = 16; + source_height = 32; // is actually 16, but we process as 32 source_bitsperpixel = 4; // recorded as 4bpp in the pio target_bitsperpixel = 2; // max pixvalues are 0, 1, 2, 3 // in DE-Sega, there's only one plane, @@ -1301,6 +1301,13 @@ bool dmdreader_init(bool return_on_no_detection) { offset[i] = i * source_dwordsperplane; } + // Read a 128x16 frame but process as 128x32, so, change the number of + // transfers at this stage to trigger a dma transfer at the right time. + if (dmd_type == DMD_DE_X16_V1 || dmd_type == DMD_DE_X16_V2) { + source_dwordsperframe /= 2; + source_dwordsperplane /= 2; + } + // DMA for DMD reader dmd_dma_channel = dma_claim_unused_channel(true); dmd_dma_channel_cfg = dma_channel_get_default_config(dmd_dma_channel); From 6da66fc6a1b9cf4bdd87abf29b192987ee8be033 Mon Sep 17 00:00:00 2001 From: Jan Vos Date: Wed, 18 Mar 2026 23:23:00 +0100 Subject: [PATCH 2/9] force wpc to be x16 v2 --- src/dmdreader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dmdreader.cpp b/src/dmdreader.cpp index a5848ea..f2c8057 100644 --- a/src/dmdreader.cpp +++ b/src/dmdreader.cpp @@ -322,7 +322,7 @@ DmdType detect_dmd() { // WPC: DOTCLK: 500000 | RCLK: 3900 | RDATA: 120 else if ((dotclk > 450000) && (dotclk < 550000) && (rclk > 3800) && (rclk < 4000) && (rdata > 115) && (rdata < 130)) { - return DMD_WPC; + return DMD_DE_X16_V2; // Data East X16 V1: DOTCLK: 121000 or 60544 | RCLK: 3905 | RDATA: 120 } else if ((dotclk > 55000) && (dotclk < 125000) && (rclk > 3880) && From 1baf4fdb1a008071d172c3be3220794206a5efe5 Mon Sep 17 00:00:00 2001 From: Jan Vos Date: Thu, 19 Mar 2026 01:07:23 +0100 Subject: [PATCH 3/9] shift pixel data around correctly --- src/dmdreader.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/dmdreader.cpp b/src/dmdreader.cpp index f2c8057..92c647b 100644 --- a/src/dmdreader.cpp +++ b/src/dmdreader.cpp @@ -611,7 +611,7 @@ void dmd_dma_handler() { // Used for Data East 128x16 to correctly align 64x16 + 64x16. // Also lets the frame start exactly in the middle of a 128x32 frame. - int16_t diff = 255; + int16_t diff = 511; // Fix byte order within the buffer uint32_t *planebuf = (uint32_t *)currentPlaneBuffer; @@ -744,7 +744,8 @@ void dmd_dma_handler() { if (dmd_type == DMD_DE_X16_V1 || dmd_type == DMD_DE_X16_V2) { // merge the rows and convert from 4bpp to 2bpp with a LUT uint32_t *dst, *src1, *src2; - dst = src1 = framebuf + 255; // start in the middle of 128x32 frame + dst = framebuf + 127; // start in the middle of 128x32 frame + src1 = framebuf + 511; // everything is stored from here onwards src2 = src1 + source_dwordsperline; if (dmd_type == DMD_DE_X16_V1) { From 3a9e11b53b86e9dd8bd087d7d94a513933d26194 Mon Sep 17 00:00:00 2001 From: Jan Vos Date: Thu, 19 Mar 2026 01:21:55 +0100 Subject: [PATCH 4/9] comment and start at 2bpp dst value --- src/dmdreader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dmdreader.cpp b/src/dmdreader.cpp index 92c647b..8ab03b6 100644 --- a/src/dmdreader.cpp +++ b/src/dmdreader.cpp @@ -610,7 +610,7 @@ void dmd_dma_handler() { detected_1_0_0_0 = false; // Used for Data East 128x16 to correctly align 64x16 + 64x16. - // Also lets the frame start exactly in the middle of a 128x32 frame. + // Also stores initial data in the hidden part of framebuf. int16_t diff = 511; // Fix byte order within the buffer @@ -744,7 +744,7 @@ void dmd_dma_handler() { if (dmd_type == DMD_DE_X16_V1 || dmd_type == DMD_DE_X16_V2) { // merge the rows and convert from 4bpp to 2bpp with a LUT uint32_t *dst, *src1, *src2; - dst = framebuf + 127; // start in the middle of 128x32 frame + dst = framebuf + 63; // start in the middle of 128x32 frame src1 = framebuf + 511; // everything is stored from here onwards src2 = src1 + source_dwordsperline; From c6ea34fd303c54069ebf75fb6ef2ea104d4e1be7 Mon Sep 17 00:00:00 2001 From: Jan Vos Date: Thu, 19 Mar 2026 09:35:25 +0100 Subject: [PATCH 5/9] diff needs to be 0, extra offset added --- src/dmdreader.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/dmdreader.cpp b/src/dmdreader.cpp index 8ab03b6..a9038dc 100644 --- a/src/dmdreader.cpp +++ b/src/dmdreader.cpp @@ -611,7 +611,8 @@ void dmd_dma_handler() { // Used for Data East 128x16 to correctly align 64x16 + 64x16. // Also stores initial data in the hidden part of framebuf. - int16_t diff = 511; + int16_t diff = 0; + uint8_t offset_x16 = 255; // Fix byte order within the buffer uint32_t *planebuf = (uint32_t *)currentPlaneBuffer; @@ -716,7 +717,7 @@ void dmd_dma_handler() { framebuf[out] |= v16; } } else { // Data East 128x16 case - framebuf[px + diff] = pixval; + framebuf[px + diff + offset_x16] = pixval; // increase diff everytime we cross one MSB or LSB row (64 pixels wide) // px is based on 4bpp, so we increase every 8 px. if ((px & 7) == 7) { @@ -745,7 +746,7 @@ void dmd_dma_handler() { // merge the rows and convert from 4bpp to 2bpp with a LUT uint32_t *dst, *src1, *src2; dst = framebuf + 63; // start in the middle of 128x32 frame - src1 = framebuf + 511; // everything is stored from here onwards + src1 = framebuf + 255; // everything is stored from here onwards src2 = src1 + source_dwordsperline; if (dmd_type == DMD_DE_X16_V1) { From 4f7e35c1e03fd8aeae6566bcf21bfe3cb8fee2ba Mon Sep 17 00:00:00 2001 From: Jan Vos Date: Thu, 19 Mar 2026 09:36:35 +0100 Subject: [PATCH 6/9] adjust naming --- src/dmdreader.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/dmdreader.cpp b/src/dmdreader.cpp index a9038dc..ea2dfbc 100644 --- a/src/dmdreader.cpp +++ b/src/dmdreader.cpp @@ -611,7 +611,7 @@ void dmd_dma_handler() { // Used for Data East 128x16 to correctly align 64x16 + 64x16. // Also stores initial data in the hidden part of framebuf. - int16_t diff = 0; + int16_t diff_x16 = 0; uint8_t offset_x16 = 255; // Fix byte order within the buffer @@ -717,18 +717,18 @@ void dmd_dma_handler() { framebuf[out] |= v16; } } else { // Data East 128x16 case - framebuf[px + diff + offset_x16] = pixval; + framebuf[px + diff_x16 + offset_x16] = pixval; // increase diff everytime we cross one MSB or LSB row (64 pixels wide) // px is based on 4bpp, so we increase every 8 px. if ((px & 7) == 7) { - diff += 8; + diff_x16 += 8; // When we have processed half of the pixels in an entire frame, // turn the diff into a - value, it will start at the top again and // work its way back to 0. This way we prepare framebuf for // oversampling if (px == ((source_dwordsperplane / 2) - 1)) { - diff -= 8; // immediately decrement once to select the correct row - diff *= -1; + diff_x16 -= 8; // immediately decrement once -> select correct row + diff_x16 *= -1; } } } From b10cc4ce782083352808bdc2b940ce4e61cdabe6 Mon Sep 17 00:00:00 2001 From: Jan Vos Date: Thu, 19 Mar 2026 09:51:50 +0100 Subject: [PATCH 7/9] store in higher bits --- src/dmdreader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dmdreader.cpp b/src/dmdreader.cpp index ea2dfbc..e094954 100644 --- a/src/dmdreader.cpp +++ b/src/dmdreader.cpp @@ -612,7 +612,7 @@ void dmd_dma_handler() { // Used for Data East 128x16 to correctly align 64x16 + 64x16. // Also stores initial data in the hidden part of framebuf. int16_t diff_x16 = 0; - uint8_t offset_x16 = 255; + uint16_t offset_x16 = 511; // Fix byte order within the buffer uint32_t *planebuf = (uint32_t *)currentPlaneBuffer; @@ -746,7 +746,7 @@ void dmd_dma_handler() { // merge the rows and convert from 4bpp to 2bpp with a LUT uint32_t *dst, *src1, *src2; dst = framebuf + 63; // start in the middle of 128x32 frame - src1 = framebuf + 255; // everything is stored from here onwards + src1 = framebuf + 511; // everything is stored from here onwards src2 = src1 + source_dwordsperline; if (dmd_type == DMD_DE_X16_V1) { From 875ad0bdefc52a020deba689c950c8fac283ba15 Mon Sep 17 00:00:00 2001 From: Jan Vos Date: Thu, 19 Mar 2026 10:00:09 +0100 Subject: [PATCH 8/9] start counting at 64 --- src/dmdreader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dmdreader.cpp b/src/dmdreader.cpp index e094954..0fb73a2 100644 --- a/src/dmdreader.cpp +++ b/src/dmdreader.cpp @@ -745,7 +745,7 @@ void dmd_dma_handler() { if (dmd_type == DMD_DE_X16_V1 || dmd_type == DMD_DE_X16_V2) { // merge the rows and convert from 4bpp to 2bpp with a LUT uint32_t *dst, *src1, *src2; - dst = framebuf + 63; // start in the middle of 128x32 frame + dst = framebuf + 64; // start in the middle of 128x32 frame src1 = framebuf + 511; // everything is stored from here onwards src2 = src1 + source_dwordsperline; From e3cffb65ddadd22490c6af3baa47e521f9562080 Mon Sep 17 00:00:00 2001 From: Jan Vos Date: Thu, 19 Mar 2026 10:18:21 +0100 Subject: [PATCH 9/9] revert wpc, confirmed working --- src/dmdreader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dmdreader.cpp b/src/dmdreader.cpp index 0fb73a2..9c5a189 100644 --- a/src/dmdreader.cpp +++ b/src/dmdreader.cpp @@ -322,7 +322,7 @@ DmdType detect_dmd() { // WPC: DOTCLK: 500000 | RCLK: 3900 | RDATA: 120 else if ((dotclk > 450000) && (dotclk < 550000) && (rclk > 3800) && (rclk < 4000) && (rdata > 115) && (rdata < 130)) { - return DMD_DE_X16_V2; + return DMD_WPC; // Data East X16 V1: DOTCLK: 121000 or 60544 | RCLK: 3905 | RDATA: 120 } else if ((dotclk > 55000) && (dotclk < 125000) && (rclk > 3880) &&