From 27024323322b19e3fdb70b7b7c163df2370fba33 Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Thu, 1 Apr 2021 01:32:02 +0200 Subject: [PATCH] Working on mega65 DMA line drawer. Works for fixed x1, y1. --- .../mos6502-common/vdsm1=vdsc1_plus_vwsm2.asm | 19 ++ .../mos6502-common/vdsm1=vdsm1_plus_vwsm2.asm | 3 +- .../mos6502-common/vdsm1=vdsm2_plus_vbsaa.asm | 19 ++ .../mos6502-common/vdsm1=vdsm2_plus_vdsm3.asm | 13 + .../mos6502-common/vdsm1=vwsm2_plus_vwsm3.asm | 25 ++ .../mos6502-common/vwsm1=vwsm1_rol_8.asm | 4 + .../mos6502-common/vwsm1=vwsm1_ror_8.asm | 7 + .../mos6502-common/vwsm1=vwsm2_ror_8.asm | 6 +- .../mos6502-common/vwum1=_lo_vdsm2.asm | 4 + src/main/kc/lib/mega65-memorymapper.c | 2 +- src/test/kc/examples/mega65/linedrawing.c | 222 +++++++++++++++++- 11 files changed, 306 insertions(+), 18 deletions(-) create mode 100644 src/main/fragment/mos6502-common/vdsm1=vdsc1_plus_vwsm2.asm create mode 100644 src/main/fragment/mos6502-common/vdsm1=vdsm2_plus_vbsaa.asm create mode 100644 src/main/fragment/mos6502-common/vdsm1=vdsm2_plus_vdsm3.asm create mode 100644 src/main/fragment/mos6502-common/vdsm1=vwsm2_plus_vwsm3.asm create mode 100644 src/main/fragment/mos6502-common/vwsm1=vwsm1_rol_8.asm create mode 100644 src/main/fragment/mos6502-common/vwsm1=vwsm1_ror_8.asm create mode 100644 src/main/fragment/mos6502-common/vwum1=_lo_vdsm2.asm diff --git a/src/main/fragment/mos6502-common/vdsm1=vdsc1_plus_vwsm2.asm b/src/main/fragment/mos6502-common/vdsm1=vdsc1_plus_vwsm2.asm new file mode 100644 index 000000000..1ab7413fa --- /dev/null +++ b/src/main/fragment/mos6502-common/vdsm1=vdsc1_plus_vwsm2.asm @@ -0,0 +1,19 @@ +lda {m2}+1 +ora #$7f +bmi !+ +lda #0 +!: +sta $ff +lda {m2} +clc +adc #<{c1} +sta {m1} +lda {m2}+1 +adc #>{c1} +sta {m1}+1 +lda $ff +adc #<{c1}>>$10 +sta {m1}+2 +lda $ff +adc #>{c1}>>$10 +sta {m1}+3 \ No newline at end of file diff --git a/src/main/fragment/mos6502-common/vdsm1=vdsm1_plus_vwsm2.asm b/src/main/fragment/mos6502-common/vdsm1=vdsm1_plus_vwsm2.asm index 33a59347d..713457309 100644 --- a/src/main/fragment/mos6502-common/vdsm1=vdsm1_plus_vwsm2.asm +++ b/src/main/fragment/mos6502-common/vdsm1=vdsm1_plus_vwsm2.asm @@ -16,5 +16,4 @@ adc $ff sta {m1}+2 lda {m1}+3 adc $ff -sta {m1}+3 - +sta {m1}+3 \ No newline at end of file diff --git a/src/main/fragment/mos6502-common/vdsm1=vdsm2_plus_vbsaa.asm b/src/main/fragment/mos6502-common/vdsm1=vdsm2_plus_vbsaa.asm new file mode 100644 index 000000000..b35439cdd --- /dev/null +++ b/src/main/fragment/mos6502-common/vdsm1=vdsm2_plus_vbsaa.asm @@ -0,0 +1,19 @@ +pha +ora #$7f +bmi !+ +lda #0 +!: +sta $ff +clc +pla +adc {m2} +sta {m1} +lda {m2}+1 +adc $ff +sta {m1}+1 +lda {m2}+2 +adc $ff +sta {m1}+2 +lda {m2}+3 +adc $ff +sta {m1}+3 \ No newline at end of file diff --git a/src/main/fragment/mos6502-common/vdsm1=vdsm2_plus_vdsm3.asm b/src/main/fragment/mos6502-common/vdsm1=vdsm2_plus_vdsm3.asm new file mode 100644 index 000000000..00ee21606 --- /dev/null +++ b/src/main/fragment/mos6502-common/vdsm1=vdsm2_plus_vdsm3.asm @@ -0,0 +1,13 @@ +clc +lda {m2} +adc {m3} +sta {m1} +lda {m2}+1 +adc {m3}+1 +sta {m1}+1 +lda {m2}+2 +adc {m3}+2 +sta {m1}+2 +lda {m2}+3 +adc {m3}+3 +sta {m1}+3 \ No newline at end of file diff --git a/src/main/fragment/mos6502-common/vdsm1=vwsm2_plus_vwsm3.asm b/src/main/fragment/mos6502-common/vdsm1=vwsm2_plus_vwsm3.asm new file mode 100644 index 000000000..0c36eb050 --- /dev/null +++ b/src/main/fragment/mos6502-common/vdsm1=vwsm2_plus_vwsm3.asm @@ -0,0 +1,25 @@ +lda {m3}+1 +ora #$7f +bmi !+ +lda #0 +!: +sta $ff +lda {m2}+1 +ora #$7f +bmi !+ +lda #0 +!: +sta $fe +clc +lda {m2} +adc {m3} +sta {m1} +lda {m2}+1 +adc {m3}+1 +sta {m1}+1 +lda $fe +adc $ff +sta {m1}+2 +lda $fe +adc $ff +sta {m1}+3 \ No newline at end of file diff --git a/src/main/fragment/mos6502-common/vwsm1=vwsm1_rol_8.asm b/src/main/fragment/mos6502-common/vwsm1=vwsm1_rol_8.asm new file mode 100644 index 000000000..b8d7b9b4c --- /dev/null +++ b/src/main/fragment/mos6502-common/vwsm1=vwsm1_rol_8.asm @@ -0,0 +1,4 @@ +lda {m1} +sta {m1}+1 +lda #0 +sta {m1} \ No newline at end of file diff --git a/src/main/fragment/mos6502-common/vwsm1=vwsm1_ror_8.asm b/src/main/fragment/mos6502-common/vwsm1=vwsm1_ror_8.asm new file mode 100644 index 000000000..5b44e4408 --- /dev/null +++ b/src/main/fragment/mos6502-common/vwsm1=vwsm1_ror_8.asm @@ -0,0 +1,7 @@ +lda {m1}+1 +sta {m1} +ora #$7f +bmi !+ +lda #0 +!: +sta {m1}+1 \ No newline at end of file diff --git a/src/main/fragment/mos6502-common/vwsm1=vwsm2_ror_8.asm b/src/main/fragment/mos6502-common/vwsm1=vwsm2_ror_8.asm index d19ea44f6..9b34d0fb1 100644 --- a/src/main/fragment/mos6502-common/vwsm1=vwsm2_ror_8.asm +++ b/src/main/fragment/mos6502-common/vwsm1=vwsm2_ror_8.asm @@ -1,7 +1,7 @@ lda {m2}+1 sta {m1} -and #$80 -beq !+ -lda #$ff +ora #$7f +bmi !+ +lda #0 !: sta {m1}+1 \ No newline at end of file diff --git a/src/main/fragment/mos6502-common/vwum1=_lo_vdsm2.asm b/src/main/fragment/mos6502-common/vwum1=_lo_vdsm2.asm new file mode 100644 index 000000000..b25001a66 --- /dev/null +++ b/src/main/fragment/mos6502-common/vwum1=_lo_vdsm2.asm @@ -0,0 +1,4 @@ +lda {m2} +sta {m1} +lda {m2}+1 +sta {m1}+1 \ No newline at end of file diff --git a/src/main/kc/lib/mega65-memorymapper.c b/src/main/kc/lib/mega65-memorymapper.c index deed8c205..7915b36ec 100644 --- a/src/main/kc/lib/mega65-memorymapper.c +++ b/src/main/kc/lib/mega65-memorymapper.c @@ -106,7 +106,7 @@ void memoryRemap256M(unsigned char remapBlocks, unsigned long lowerPageOffset, u lda lMb // lower blocks offset megabytes ldx #$0f // lower signal for MB offset ldy uMb // upper blocks offset megabytes - ldz #$00 // upper signal for MB offset + ldz #$0f // upper signal for MB offset map lda aVal // lower blocks offset page low ldx xVal // lower blocks to map + lower blocks offset high nibble diff --git a/src/test/kc/examples/mega65/linedrawing.c b/src/test/kc/examples/mega65/linedrawing.c index f580896d4..1884e53ab 100644 --- a/src/test/kc/examples/mega65/linedrawing.c +++ b/src/test/kc/examples/mega65/linedrawing.c @@ -1,11 +1,13 @@ // Test hardware line drawing // Based on https://github.com/MEGA65/mega65-tools/blob/master/src/tests/test_290.c -#pragma target(mega65) +#pragma target(mega65_remote) #include +#include #include <6502.h> #define POKE(addr,val) *((char*)(addr)) = val +#define PEEK(addr) *((char*)addr) // Poke a value directly into memory // - addr: The 32bit address to poke to @@ -19,23 +21,60 @@ void lpoke(__zp unsigned long addr, char val) { } } +char line_dmalist[256]; +char slope_ofs, line_mode_ofs, cmd_ofs, count_ofs; +char src_ofs, dst_ofs; + void main() { - // Avoid interrupts - SEI(); - // Map memory to BANK 0 : 0x00XXXX - giving access to I/O - memoryRemap(0,0,0); + // Avoid interrupts + SEI(); - // Fast CPU, M65 IO - POKE(0, 65); - POKE(0xD02F, 0x47); - POKE(0xD02F, 0x53); - - graphics_mode(); + // Map memory to BANK 0 : 0x00XXXX - giving access to I/O + memoryRemap(0x00,0,0); + // Fast CPU, M65 IO + POKE(0, 65); + POKE(0xD02F, 0x47); + POKE(0xD02F, 0x53); + // No C65 ROMs are mapped + POKE(0xD030, 0x00); - for(;;) ; + graphics_mode(); + + // Set up common structure of the DMA list + char ofs = 0; + // Screen layout is in vertical stripes, so we need only to setup the + // X offset step. 64x25 = + line_dmalist[ofs++] = 0x87; + line_dmalist[ofs++] = (1600 - 8) & 0xff; + line_dmalist[ofs++] = 0x88; + line_dmalist[ofs++] = (1600 - 8) >> 8; + line_dmalist[ofs++] = 0x8b; + slope_ofs = ofs++; // remember where we have to put the slope in + line_dmalist[ofs++] = 0x8c; + ofs++; + line_dmalist[ofs++] = 0x8f; + line_mode_ofs = ofs++; + line_dmalist[ofs++] = 0x0a; // F018A list format + line_dmalist[ofs++] = 0x00; // end of options + cmd_ofs = ofs++; // command byte + count_ofs = ofs; + ofs += 2; + src_ofs = ofs; + ofs += 3; + dst_ofs = ofs; + ofs += 3; + line_dmalist[ofs++] = 0x00; // modulo + line_dmalist[ofs++] = 0x00; + + + int x1 = 160; + for(int x2=0;x2<320;x2+=11) { + draw_line(x1, 100, x2, 198, 1); + } + } @@ -76,5 +115,164 @@ void graphics_mode(void) { POKE(0xD020, 0); POKE(0xD021, 0); + // Fill the graphics + memset_dma256(0x0, 0x4, 0x0000, 0x00, 320*200); + memset_dma256(0x0, 0x4, 0x0000, 0x055, 8*200); + memset_dma256(0x0, 0x4, 0x0000+200*39*8, 0x055, 8*200); + + } + +void draw_line(int x1, int y1, int x2, int y2, unsigned char colour) +{ + long addr; + int temp, slope, dx, dy; + + // Ignore if we choose to draw a point + if (x2 == x1 && y2 == y1) + return; + + dx = x2 - x1; + dy = y2 - y1; + if (dx < 0) + dx = -dx; + if (dy < 0) + dy = -dy; + + // snprintf(msg,41,"(%d,%d) - (%d,%d) ",x1,y1,x2,y2); + // print_text(0,1,1,msg); + + // Draw line from x1,y1 to x2,y2 + if (dx < dy) { + // Y is major axis + + if (y2 < y1) { + temp = x1; + x1 = x2; + x2 = temp; + temp = y1; + y1 = y2; + y2 = temp; + } + + // Use hardware divider to get the slope + POKE(0xD770, (char)(dx & 0xff)); + POKE(0xD771, (char)(dx >> 8)); + POKE(0xD772, 0); + POKE(0xD773, 0); + POKE(0xD774, (char)(dy & 0xff)); + POKE(0xD775, (char)(dy >> 8)); + POKE(0xD776, 0); + POKE(0xD777, 0); + + // Wait 16 cycles + POKE(0xD020, 0); + POKE(0xD020, 0); + POKE(0xD020, 0); + POKE(0xD020, 0); + + // Slope is the most significant bytes of the fractional part + // of the division result + slope = (int)PEEK(0xD76A) + ((int)PEEK(0xD76B) << 8); + + // Put slope into DMA options + line_dmalist[slope_ofs] = (char)(slope & 0xff); + line_dmalist[slope_ofs + 2] = (char)(slope >> 8); + + // Load DMA dest address with the address of the first pixel + addr = 0x40000 + (y1 << 3) + (x1 & 7) + (x1 >> 3) * 64 * 25l; + line_dmalist[dst_ofs + 0] = <(<(addr)); + line_dmalist[dst_ofs + 1] = >(<(addr)); + line_dmalist[dst_ofs + 2] = <(>(addr)); + + // Source is the colour + line_dmalist[src_ofs] = colour & 0xf; + + // Count is number of pixels, i.e., dy. + line_dmalist[count_ofs] = (char)(dy & 0xff); + line_dmalist[count_ofs + 1] = (char)(dy >> 8); + + // Command is FILL + line_dmalist[cmd_ofs] = 0x03; + + // Line mode active, major axis is Y + line_dmalist[line_mode_ofs] = 0x80 + 0x40 + (((x2 - x1) < 0) ? 0x20 : 0x00); + + // snprintf(msg,41,"Y: (%d,%d) - (%d,%d) m=%04x",x1,y1,x2,y2,slope); + // print_text(0,2,1,msg); + + POKE(0xD020, 1); + + POKE(0xD701, (char)(((unsigned int)(line_dmalist)) >> 8)); + POKE(0xD705, (char)(((unsigned int)(line_dmalist)) >> 0)); + + POKE(0xD020, 0); + } + else { + // X is major axis + + if (x2 < x1) { + temp = x1; + x1 = x2; + x2 = temp; + temp = y1; + y1 = y2; + y2 = temp; + } + + // Use hardware divider to get the slope + POKE(0xD770, (char)(dy & 0xff)); + POKE(0xD771, (char)(dy >> 8)); + POKE(0xD772, 0); + POKE(0xD773, 0); + POKE(0xD774, (char)(dx & 0xff)); + POKE(0xD775, (char)(dx >> 8)); + POKE(0xD776, 0); + POKE(0xD777, 0); + + // Wait 16 cycles + POKE(0xD020, 0); + POKE(0xD020, 0); + POKE(0xD020, 0); + POKE(0xD020, 0); + + // Slope is the most significant bytes of the fractional part + // of the division result + slope = (int)PEEK(0xD76A) + ((int)PEEK(0xD76B) << 8); + + // Put slope into DMA options + line_dmalist[slope_ofs] = (char)(slope & 0xff); + line_dmalist[slope_ofs + 2] = (char)(slope >> 8); + + // Load DMA dest address with the address of the first pixel + addr = 0x40000 + (y1 << 3) + (x1 & 7) + (x1 >> 3) * 64 * 25; + line_dmalist[dst_ofs + 0] = <(<(addr)); + line_dmalist[dst_ofs + 1] = >(<(addr)); + line_dmalist[dst_ofs + 2] = <(>(addr)); + + // Source is the colour + line_dmalist[src_ofs] = colour & 0xf; + + // Count is number of pixels, i.e., dy. + line_dmalist[count_ofs] = (char)(dx & 0xff); + line_dmalist[count_ofs + 1] = (char)(dx >> 8); + + // Command is FILL + line_dmalist[cmd_ofs] = 0x03; + + // Line mode active, major axis is X + char line_mode = (((y2 - y1) < 0) ? 0x20 : 0x00); + line_dmalist[line_mode_ofs] = 0x80 + 0x00 + line_mode; + + // snprintf(msg,41,"X: (%d,%d) - (%d,%d) m=%04x",x1,y1,x2,y2,slope); + // print_text(0,2,1,msg); + + POKE(0xD020, 1); + + POKE(0xD701, (char)(((unsigned int)(line_dmalist)) >> 8)); + POKE(0xD705, (char)(((unsigned int)(line_dmalist)) >> 0)); + + POKE(0xD020, 0); + } +}