diff --git a/src/main/fragment/cache/fragment-cache-mos6502x.asm b/src/main/fragment/cache/fragment-cache-mos6502x.asm index 2a9d4ce8c..9f1b5c2a1 100644 --- a/src/main/fragment/cache/fragment-cache-mos6502x.asm +++ b/src/main/fragment/cache/fragment-cache-mos6502x.asm @@ -19615,3 +19615,367 @@ ror {z1} dex bne !- !e: +//FRAGMENT vwuz1=vwuc1_plus_vbuz2 +lda {z2} +clc +adc #<{c1} +sta {z1} +lda #>{c1} +adc #0 +sta {z1}+1 +//FRAGMENT qbuz1_derefidx_vbuc1=pbuz2 +ldy #{c1} +lda {z2} +sta ({z1}),y +iny +lda {z2}+1 +sta ({z1}),y +//FRAGMENT qwuz1_derefidx_vbuc1=pwuz2 +ldy #{c1} +lda {z2} +sta ({z1}),y +iny +lda {z2}+1 +sta ({z1}),y +//FRAGMENT vwuz1=pwuz2_derefidx_vbuc1 +ldy #{c1} +lda ({z2}),y +sta {z1} +iny +lda ({z2}),y +sta {z1}+1 +//FRAGMENT vwuz1=vwuc1_plus_vbuaa +clc +adc #<{c1} +sta {z1} +lda #>{c1} +adc #0 +sta {z1}+1 +//FRAGMENT vwuz1=vwuc1_plus_vbuxx +txa +clc +adc #<{c1} +sta {z1} +lda #>{c1} +adc #0 +sta {z1}+1 +//FRAGMENT vwuz1=vwuc1_plus_vbuyy +tya +clc +adc #<{c1} +sta {z1} +lda #>{c1} +adc #0 +sta {z1}+1 +//FRAGMENT vbuz1_eq__deref_pbuc1_then_la1 +lda {c1} +cmp {z1} +beq {la1} +//FRAGMENT _deref_pbuc1_eq_0_then_la1 +lda {c1} +cmp #0 +beq {la1} +//FRAGMENT vbuz1=_deref_pbuc1_rol_4 +lda {c1} +asl +asl +asl +asl +sta {z1} +//FRAGMENT vbuz1=vbuz2_bor__deref_pbuc1 +lda {c1} +ora {z2} +sta {z1} +//FRAGMENT vduz1=vduz2_plus_vbuz3 +lda {z3} +clc +adc {z2} +sta {z1} +lda {z2}+1 +adc #0 +sta {z1}+1 +lda {z2}+2 +adc #0 +sta {z1}+2 +lda {z2}+3 +adc #0 +sta {z1}+3 +//FRAGMENT pbuc1_derefidx_vbuz1=_dec_pbuc1_derefidx_vbuz1 +ldx {z1} +dec {c1},x +//FRAGMENT _deref_pbuz1=pbuc1_derefidx_(pbuc2_derefidx_vbuz2) +ldx {z2} +ldy {c2},x +lda {c1},y +ldy #0 +sta ({z1}),y +//FRAGMENT pbuc1_derefidx_vbuz1_le_pbuc2_derefidx_vbuz1_then_la1 +ldy {z1} +lda {c2},y +cmp {c1},y +bcs {la1} +//FRAGMENT vbuz1=_deref_pbuz2_bor_vbuc1 +lda #{c1} +ldy #0 +ora ({z2}),y +sta {z1} +//FRAGMENT pbuc1_derefidx_vbuz1=pbuz2_derefidx_vbuz1 +ldy {z1} +lda ({z2}),y +sta {c1},y +//FRAGMENT vwuz1=vwuc1_plus_vwuz2 +clc +lda {z2} +adc #<{c1} +sta {z1} +lda {z2}+1 +adc #>{c1} +sta {z1}+1 +//FRAGMENT vbuxx_eq__deref_pbuc1_then_la1 +cpx {c1} +beq {la1} +//FRAGMENT vbuaa=_deref_pbuc1_rol_4 +lda {c1} +asl +asl +asl +asl +//FRAGMENT vbuxx=_deref_pbuc1_rol_4 +lda {c1} +asl +asl +asl +asl +tax +//FRAGMENT vbuyy=_deref_pbuc1_rol_4 +lda {c1} +asl +asl +asl +asl +tay +//FRAGMENT vbuaa=vbuz1_bor__deref_pbuc1 +lda {c1} +ora {z1} +//FRAGMENT vbuxx=vbuz1_bor__deref_pbuc1 +lda {c1} +ora {z1} +tax +//FRAGMENT vbuyy=vbuz1_bor__deref_pbuc1 +lda {c1} +ora {z1} +tay +//FRAGMENT vbuz1=vbuaa_bor__deref_pbuc1 +ora {c1} +sta {z1} +//FRAGMENT vbuaa=vbuaa_bor__deref_pbuc1 +ora {c1} +//FRAGMENT vbuxx=vbuaa_bor__deref_pbuc1 +ora {c1} +tax +//FRAGMENT vbuyy=vbuaa_bor__deref_pbuc1 +ora {c1} +tay +//FRAGMENT vbuz1=vbuxx_bor__deref_pbuc1 +txa +ora {c1} +sta {z1} +//FRAGMENT vbuaa=vbuxx_bor__deref_pbuc1 +txa +ora {c1} +//FRAGMENT vbuxx=vbuxx_bor__deref_pbuc1 +txa +ora {c1} +tax +//FRAGMENT vbuyy=vbuxx_bor__deref_pbuc1 +txa +ora {c1} +tay +//FRAGMENT vbuz1=vbuyy_bor__deref_pbuc1 +tya +ora {c1} +sta {z1} +//FRAGMENT vbuaa=vbuyy_bor__deref_pbuc1 +tya +ora {c1} +//FRAGMENT vbuxx=vbuyy_bor__deref_pbuc1 +tya +ora {c1} +tax +//FRAGMENT vbuyy=vbuyy_bor__deref_pbuc1 +tya +ora {c1} +tay +//FRAGMENT vduz1=vduz2_plus_vbuxx +txa +clc +adc {z2} +sta {z1} +lda {z2}+1 +adc #0 +sta {z1}+1 +lda {z2}+2 +adc #0 +sta {z1}+2 +lda {z2}+3 +adc #0 +sta {z1}+3 +//FRAGMENT vduz1=vduz2_plus_vbuyy +tya +clc +adc {z2} +sta {z1} +lda {z2}+1 +adc #0 +sta {z1}+1 +lda {z2}+2 +adc #0 +sta {z1}+2 +lda {z2}+3 +adc #0 +sta {z1}+3 +//FRAGMENT pbuz1_derefidx_vbuz2=pbuc1_derefidx_(pbuc2_derefidx_vbuaa) +tax +ldy {c2},x +lda {c1},y +ldy {z2} +sta ({z1}),y +//FRAGMENT pbuz1_derefidx_vbuz2=pbuc1_derefidx_(pbuc2_derefidx_vbuxx) +ldy {c2},x +lda {c1},y +ldy {z2} +sta ({z1}),y +//FRAGMENT pbuz1_derefidx_vbuz2=pbuc1_derefidx_(pbuc2_derefidx_vbuyy) +ldx {c2},y +lda {c1},x +ldy {z2} +sta ({z1}),y +//FRAGMENT pbuz1_derefidx_vbuaa=pbuc1_derefidx_(pbuc2_derefidx_vbuz2) +ldy {z2} +ldx {c2},y +tay +lda {c1},x +sta ({z1}),y +//FRAGMENT pbuz1_derefidx_vbuaa=pbuc1_derefidx_(pbuc2_derefidx_vbuaa) +tay +ldx {c2},y +lda {c1},x +sta ({z1}),y +//FRAGMENT pbuz1_derefidx_vbuaa=pbuc1_derefidx_(pbuc2_derefidx_vbuxx) +ldy {c2},x +ldx {c1},y +tay +txa +sta ({z1}),y +//FRAGMENT pbuz1_derefidx_vbuaa=pbuc1_derefidx_(pbuc2_derefidx_vbuyy) +ldx {c2},y +tay +lda {c1},x +sta ({z1}),y +//FRAGMENT pbuz1_derefidx_vbuxx=pbuc1_derefidx_(pbuc2_derefidx_vbuz2) +ldy {z2} +txa +ldx {c2},y +tay +lda {c1},x +sta ({z1}),y +//FRAGMENT pbuz1_derefidx_vbuxx=pbuc1_derefidx_(pbuc2_derefidx_vbuaa) +tay +txa +ldx {c2},y +tay +lda {c1},x +sta ({z1}),y +//FRAGMENT pbuz1_derefidx_vbuxx=pbuc1_derefidx_(pbuc2_derefidx_vbuxx) +txa +tay +ldx {c2},y +lda {c1},x +sta ({z1}),y +//FRAGMENT pbuz1_derefidx_vbuxx=pbuc1_derefidx_(pbuc2_derefidx_vbuyy) +txa +ldx {c2},y +tay +lda {c1},x +sta ({z1}),y +//FRAGMENT pbuz1_derefidx_vbuyy=pbuc1_derefidx_(pbuc2_derefidx_vbuz2) +ldx {z2} +lda {c2},x +tax +lda {c1},x +sta ({z1}),y +//FRAGMENT pbuz1_derefidx_vbuyy=pbuc1_derefidx_(pbuc2_derefidx_vbuaa) +tax +lda {c2},x +tax +lda {c1},x +sta ({z1}),y +//FRAGMENT pbuz1_derefidx_vbuyy=pbuc1_derefidx_(pbuc2_derefidx_vbuxx) +lda {c2},x +tax +lda {c1},x +sta ({z1}),y +//FRAGMENT pbuz1_derefidx_vbuyy=pbuc1_derefidx_(pbuc2_derefidx_vbuyy) +ldx {c2},y +lda {c1},x +sta ({z1}),y +//FRAGMENT pbuc1_derefidx_vbuxx=_dec_pbuc1_derefidx_vbuxx +dec {c1},x +//FRAGMENT _deref_pbuz1=pbuc1_derefidx_(pbuc2_derefidx_vbuxx) +ldy {c2},x +lda {c1},y +ldy #0 +sta ({z1}),y +//FRAGMENT pbuc1_derefidx_vbuxx_le_pbuc2_derefidx_vbuxx_then_la1 +txa +tay +lda {c2},x +cmp {c1},y +bcs {la1} +//FRAGMENT vbuaa=_deref_pbuz1_bor_vbuc1 +lda #{c1} +ldy #0 +ora ({z1}),y +//FRAGMENT vbuxx=_deref_pbuz1_bor_vbuc1 +lda #{c1} +ldy #0 +ora ({z1}),y +tax +//FRAGMENT vbuyy=_deref_pbuz1_bor_vbuc1 +lda #{c1} +ldy #0 +ora ({z1}),y +tay +//FRAGMENT pbuc1_derefidx_vbuaa=pbuz1_derefidx_vbuaa +tay +lda ({z1}),y +sta {c1},y +//FRAGMENT vduz1=vduz1_plus_vbuxx +txa +clc +adc {z1} +sta {z1} +lda {z1}+1 +adc #0 +sta {z1}+1 +lda {z1}+2 +adc #0 +sta {z1}+2 +lda {z1}+3 +adc #0 +sta {z1}+3 +//FRAGMENT vwuz1=vwuz1_band_vwuc1 +lda {z1} +and #<{c1} +sta {z1} +lda {z1}+1 +and #>{c1} +sta {z1}+1 +//FRAGMENT vwuz1=vwuc1_plus_vwuz1 +clc +lda {z1} +adc #<{c1} +sta {z1} +lda {z1}+1 +adc #>{c1} +sta {z1}+1 diff --git a/src/test/kc/complex/clearscreen/clearscreen.c b/src/test/kc/complex/clearscreen/clearscreen.c deleted file mode 100644 index e954e440a..000000000 --- a/src/test/kc/complex/clearscreen/clearscreen.c +++ /dev/null @@ -1,345 +0,0 @@ -// Clears start screen throwing around the letters (by turning them into sprites) -#include -#include -#include -#include -#include - -// Generate debug code (raster time usage etc.) -const bool DEBUG = false; - -// Address of the screen -byte* const SCREEN = 0x0400; -// Sprite data for the animating sprites -byte* const SPRITE_DATA = 0x2000; -// Values added to VX -const unsigned int VXSIN[40] = kickasm {{ - .for(var i=0; i<40; i++) { - .word -sin(toRadians([i*360]/40))*4 - } -}}; - -// Values added to VY -const unsigned int VYSIN[25] = kickasm {{ - .for(var i=0; i<25; i++) { - .word -sin(toRadians([i*360]/25))*4 - } -}}; - -// Copy of the screen used for finding chars to process -byte* SCREEN_COPY = malloc(1000); - -// Screen containing bytes representing the distance to the center -byte* SCREEN_DIST = malloc(1000); - -// Max number of chars processed at once -const byte NUM_PROCESSING = 8; - -// Struct holding char being processed -struct ProcessingChar { - // x-position (0-39) - char x; - // y-position (0-24) - char y; - // squared distance to center (0-569) - char dist; -}; - -// Distance value meaning not found -const byte NOT_FOUND = 0xff; - -// Struct holding sprite being processed -struct ProcessingSprite { - // sprite x-position. Fixed point [12.4]. Values (24-336) - unsigned int x; - // sprite y-position. Fixed point [12.4]. Values (30-228) - unsigned int y; - // sprite x velocity. Fixed point [12.4] - unsigned int vx; - // sprite y velocity. Fixed point [12.4] - unsigned int vy; - // sprite ID (0-7) - char id; - // sprite pointer (0-255) - char ptr; - // sprite color - char col; - // status of the processing - enum { STATUS_FREE, STATUS_NEW, STATUS_PROCESSING } status; - // Pointer to screen char being processed (used for deletion) - char* screenPtr; -}; - -// Sprites currently being processed in the interrupt -struct ProcessingSprite PROCESSING[NUM_PROCESSING]; - -void main() { - // Initialize the screen containing distance to the center - init_angle_screen(SCREEN_DIST); - // Copy screen to screen copy - for( char *src=SCREEN, *dst=SCREEN_COPY; src!=SCREEN+1000; src++, dst++) *dst = *src; - // Init processing array - for( char i: 0..NUM_PROCESSING-1 ) PROCESSING[i] = { 0, 0, 0, 0, 0, 0, 0, STATUS_FREE, 0}; - // Init sprites - initSprites(); - // Set-up raster interrupts - setupRasterIrq(RASTER_IRQ_TOP, &irqTop); - // Main loop - do { - // Look for the non-space closest to the screen center - struct ProcessingChar center = getCharToProcess(); - if(center.dist==NOT_FOUND) - break; - startProcessing(center); - } while(true); - (*(SCREEN+999)) = '.'; - do { - (*(COLS+999))++; - } while (true); -} - -// Find the non-space char closest to the center of the screen -// If no non-space char is found the distance will be 0xffff -struct ProcessingChar getCharToProcess() { - struct ProcessingChar closest = { 0, 0, NOT_FOUND }; - char* screen_line = SCREEN_COPY; - char* dist_line = SCREEN_DIST; - for( char y: 0..24) { - for( char x: 0..39) { - if(screen_line[x]!=' ') { - char dist = dist_line[x]; - if(distid; - if(processing->status!=STATUS_FREE) { - if(processing->status==STATUS_NEW) { - // Clear the char on the screen - *(processing->screenPtr) = ' '; - // Enable the sprite - *SPRITES_ENABLE |= bitmask; - // Set the sprite color - SPRITES_COLOR[processing->id] = processing->col; - // Set sprite pointer - *(SCREEN+OFFSET_SPRITE_PTRS+processing->id) = processing->ptr; - // Set status - processing->status = STATUS_PROCESSING; - } - unsigned int xpos = processing->x >> 4; - // Set sprite position - if(>xpos) { - *SPRITES_XMSB |= bitmask; - } else { - *SPRITES_XMSB &= 0xff ^ bitmask; - } - SPRITES_XPOS[i*2] = (char)xpos; - char ypos = (char)(processing->y>>4); - SPRITES_YPOS[i*2] = ypos; - - // Move sprite - if(processing->x < XPOS_LEFTMOST || processing->x > XPOS_RIGHTMOST || processing->y < YPOS_TOPMOST|| processing->y > YPOS_BOTTOMMOST ) { - // Set status to FREE - processing->status = STATUS_FREE; - // Disable the sprite - *SPRITES_ENABLE &= 0xff ^ bitmask; - } else { - char xchar = (char)(xpos/8) - BORDER_XPOS_LEFT/8; - processing->vx += VXSIN[xchar]; - processing->x += processing->vx; - char ychar = (char)(ypos/8) - BORDER_YPOS_TOP/8; - processing->vy += VYSIN[ychar]; - processing->y += processing->vy; - } - numActive++; - } - } - if(DEBUG) { - *(SCREEN+999) = '0'+numActive; - } -} - -// Populates 1000 chars (a screen) with values representing the distance to the center. -// The actual value stored is distance*2 to increase precision -void init_dist_screen(char* screen) { - NUM_SQUARES = 0x30; - init_squares(); - char* screen_topline = screen; - char *screen_bottomline = screen+40*24; - for(char y: 0..12) { - char y2 = y*2; - char yd = (y2>=24)?(y2-24):(24-y2); - unsigned int yds = sqr(yd); - for( char x=0,xb=39; x<=19; x++, xb--) { - char x2 = x*2; - char xd = (x2>=39)?(x2-39):(39-x2); - unsigned int xds = sqr(xd); - unsigned int ds = xds+yds; - char d = sqrt(ds); - screen_topline[x] = d; - screen_bottomline[x] = d; - screen_topline[xb] = d; - screen_bottomline[xb] = d; - } - screen_topline += 40; - screen_bottomline -= 40; - } -} - -// Populates 1000 chars (a screen) with values representing the angle to the center. -// Utilizes symmetry around the center -void init_angle_screen(char* screen) { - char* screen_topline = screen+40*12; - char *screen_bottomline = screen+40*12; - for(char y: 0..12) { - for( char x=0,xb=39; x<=19; x++, xb--) { - signed int xw = (signed int)(unsigned int){ 39-x*2, 0 }; - signed int yw = (signed int)(unsigned int){ y*2, 0 }; - unsigned int angle_w = atan2_16(xw, yw); - char ang_w = >(angle_w+0x0080); - screen_bottomline[xb] = ang_w; - screen_topline[xb] = -ang_w; - screen_topline[x] = 0x80+ang_w; - screen_bottomline[x] = 0x80-ang_w; - } - screen_topline -= 40; - screen_bottomline += 40; - } -} - -// Initialize sprites -void initSprites() { - // Clear sprite data - for( char* sp = SPRITE_DATA; spINTERRUPT = CIA_INTERRUPT_CLEAR; - if(raster<0x100) { - *VICII_CONTROL &=0x7f; - } else { - *VICII_CONTROL |=0x80; - } - *RASTER = -#include - -// The DYPPA charset containing the sloped offset characters -char __address(0x2000) DYPPA_CHARSET[0x0800] = kickasm(resource "dyppacharset.bin") {{ - .var dyppaFile = LoadBinary("dyppacharset.bin", "Charset=$000,Tables=$800") - .fill dyppaFile.getCharsetSize(), dyppaFile.getCharset(i) -}}; - -// The DYPPA tables mapping the slopes, offsets and pixels to the right character in the charset -// for(offset:0..7) for(slope:0..f) for(pixels: 0..f) glyph_id(offset,slope,pixels) -char __align(0x100) DYPPA_TABLE[0x0800] = kickasm(resource "dyppacharset.bin") {{ - .var dyppaFile2 = LoadBinary("dyppacharset.bin", "Charset=$000,Tables=$800") - .fill dyppaFile2.getTablesSize(), dyppaFile2.getTables(i) -}}; - -void main() { - VICII->MEMORY = toD018(DEFAULT_SCREEN, DYPPA_CHARSET); - memset(DEFAULT_SCREEN, DYPPA_TABLE[0], 1000); - - for(;;) { - (*(DEFAULT_SCREEN+999))++; - } - -} - - - diff --git a/src/test/kc/complex/dyppa2/dyppacharset.bin b/src/test/kc/complex/dyppa2/dyppacharset.bin deleted file mode 100644 index 98721d73f..000000000 Binary files a/src/test/kc/complex/dyppa2/dyppacharset.bin and /dev/null differ diff --git a/src/test/kc/complex/splines/splines.c b/src/test/kc/complex/splines/splines.c deleted file mode 100644 index f6fcc3aee..000000000 --- a/src/test/kc/complex/splines/splines.c +++ /dev/null @@ -1,136 +0,0 @@ - // Quadratic Spline Library - // Implements an iterative algorithm using only addition for calculating quadratic splines - // - // A quadratic spline is a curve defined by 3 points: P0, P1 and P2. - // The curve connects P0 to P2 through a smooth curve that moves towards P1, but does usually not touch it. - // - // The general formula for the quadratic spline is as follows: - // A = P2 - 2*P1 + P0 - // B = 2*P1 - 2*P0 - // C = P0 - // P(t) = A*t*t + B*t + C - // for 0 <= t <= 1 - // - // This library implements a iterative algorithm using multiplications in the initialization and only additions for calculating each point on the spline. - // The iterative algorithm is based on the following: - // P(t+Dt) = P(t) + A*Dt*Dt + 2*A*t*Dt + B*Dt - // - // init: - // N = 16 (number of plots) - // Dt = 1/N - // P = C - // I = A*Dt*Dt + B*Dt - // J = 2*A*Dt*Dt - // loop(N times): - // plot(P) - // P = P + I - // I = I + J - // When N=16 then Dt[0.16] = $0.1000 Dt^2[0.16] = $0.0100 - // When N=8 then Dt[0.16] = $0.2000 Dt^2[0.16] = $0.0400 - -// Vector with 16-coordinates that is part of a spline -struct SplineVector16 { - // x-position s[16.0] - signed int x; - // y-position s[16.0] - signed int y; -}; - -// Vector with 32-bit coordinates that is part of a spline -struct SplineVector32 { - // x-position s[16.16] - signed long x; - // y-position s[16.16] - signed long y; -}; - -// Array filled with spline segment points by splinePlot_16() -struct SplineVector16 SPLINE_16SEG[17]; - -// Generate a 16-segment quadratic spline using 32-bit fixed point 1/$10000-format math 16 decimal bits). -// This function can handle all signed int values in the points. -// The resulting spline segment points are returned in SPLINE_16SEG[] -// A quadratic spline is a curve defined by 3 points: P0, P1 and P2. -// The curve connects P0 to P2 through a smooth curve that moves towards P1, but does usually not touch it. -void spline_16seg(struct SplineVector16 p0, struct SplineVector16 p1, struct SplineVector16 p2) { - // A = P2 - 2*P1 + P0 - struct SplineVector16 a = { p2.x - p1.x*2 + p0.x, p2.y - p1.y*2 + p0.y}; - // B = 2*P1 - 2*P0 - struct SplineVector16 b = { (p1.x - p0.x)*2, (p1.y - p0.y)*2 }; - // I = A*Dt*Dt + B*Dt - Fixed point s[16.16] - // Dt = 1/16 and Dt*Dt=1/256 - we can multiply using only bitshifts - struct SplineVector32 i = { (signed long)a.x*0x100 + (signed long)b.x*0x100*0x10, (signed long)a.y*0x100 + (signed long)b.y*0x100*0x10 }; - // J = 2*A*Dt*Dt - Fixed point s[16.16] - // Dt = 1/16 and Dt*Dt=1/256 - we can multiply using only bitshifts - struct SplineVector32 j = { (signed long)a.x*0x100*2, (signed long)a.y*0x100*2 }; - // P = P0 - Fixed point s[16.16] - struct SplineVector32 p = { (signed long)p0.x*0x10000, (signed long)p0.y*0x10000 }; - for( char n: 0..15) { - SPLINE_16SEG[n] = { (signed word)>(p.x+0x8000), (signed word)>(p.y+0x8000) }; - // P = P + I; - p = { p.x+i.x, p.y+i.y }; - // I = I + J; - i = { i.x+j.x, i.y+j.y }; - } - SPLINE_16SEG[16] = { (signed word)>(p.x+0x8000), (signed word)>(p.y+0x8000) }; -} - -// Array filled with spline segment points by splinePlot_8() -struct SplineVector16 SPLINE_8SEG[9]; - -// Generate a 8-segment quadratic spline using 32-bit fixed point 1/$10000-format math 16 decimal bits). -// The resulting spline segment points are returned in SPLINE_8SEG[] -// This function can handle all signed int values in the points. -// A quadratic spline is a curve defined by 3 points: P0, P1 and P2. -// The curve connects P0 to P2 through a smooth curve that moves towards P1, but does usually not touch it. -void spline_8seg(struct SplineVector16 p0, struct SplineVector16 p1, struct SplineVector16 p2) { - // A = P2 - 2*P1 + P0 - struct SplineVector16 a = { p2.x - p1.x*2 + p0.x, p2.y - p1.y*2 + p0.y}; - // B = 2*P1 - 2*P0 - struct SplineVector16 b = { (p1.x - p0.x)*2, (p1.y - p0.y)*2 }; - // I = A*Dt*Dt + B*Dt - Fixed point s[16.16] - // Dt = 1/8 and Dt*Dt=1/64 - we can multiply using only bitshifts - struct SplineVector32 i = { (signed long)a.x*0x100*0x4 + (signed long)b.x*0x100*0x20, (signed long)a.y*0x100*0x4 + (signed long)b.y*0x100*0x20 }; - // J = 2*A*Dt*Dt - Fixed point s[16.16] - // Dt = 1/8 and Dt*Dt=1/64 - we can multiply using only bitshifts - struct SplineVector32 j = { (signed long)a.x*0x100*0x8, (signed long)a.y*0x100*0x8 }; - // P = P0 - Fixed point s[16.16] - struct SplineVector32 p = { (signed long)p0.x*0x10000, (signed long)p0.y*0x10000 }; - for( char n: 0..7) { - SPLINE_8SEG[n] = { (signed word)>(p.x+0x8000), (signed word)>(p.y+0x8000) }; - // P = P + I; - p = { p.x+i.x, p.y+i.y }; - // I = I + J; - i = { i.x+j.x, i.y+j.y }; - } - SPLINE_8SEG[8] = { (signed word)>(p.x+0x8000), (signed word)>(p.y+0x8000) }; -} - -// Generate a 8-segment quadratic spline using 16-bit fixed point 1/64-format math (6 decimal bits). -// The resulting spline segment points are returned in SPLINE_8SEG[] -// Point values must be within [-200 ; 1ff] for the calculation to not overflow. -// A quadratic spline is a curve defined by 3 points: P0, P1 and P2. -// The curve connects P0 to P2 through a smooth curve that moves towards P1, but does usually not touch it. -void spline_8segB(struct SplineVector16 p0, struct SplineVector16 p1, struct SplineVector16 p2) { - // A = P2 - 2*P1 + P0 - struct SplineVector16 a = { p2.x - p1.x*2 + p0.x, p2.y - p1.y*2 + p0.y}; - // B = 2*P1 - 2*P0 - struct SplineVector16 b = { (p1.x - p0.x)*2, (p1.y - p0.y)*2 }; - // I = A*Dt*Dt + B*Dt - I is in fixed point 1/64-format (6 decimal bits) [-200 ; 1ff] - // Dt = 1/8 and Dt*Dt=1/64 - we can multiply using only bitshifts. Dt*Dt is exactly==1 in the fixed point format. - struct SplineVector16 i = { a.x + b.x*8, a.y + b.y*8}; - // J = 2*A*Dt*Dt - J is in fixed point 1/64-format (6 decimal bits) [-200 ; 1ff] - // Dt = 1/8 and Dt*Dt=1/64 - we can multiply using only bitshifts. Dt*Dt is exactly==1 in the fixed point format. - struct SplineVector16 j = { a.x*2, a.y*2 }; - // P = P0 - P is in fixed point 1/64-format (6 decimal bits) [-200 ; 1ff] - struct SplineVector16 p = { p0.x*0x40, p0.y*0x40 }; - for( char n: 0..7) { - // Get the rounded result - SPLINE_8SEG[n] = { (p.x+0x20)/0x40, (p.y+0x20)/0x40 }; - // P = P + I; - p = { p.x+i.x, p.y+i.y }; - // I = I + J; - i = { i.x+j.x, i.y+j.y }; - } - SPLINE_8SEG[8] = { (p.x+0x20)/0x40, (p.y+0x20)/0x40 }; -} diff --git a/src/test/kc/complex/splines/truetype-splines.c b/src/test/kc/complex/splines/truetype-splines.c deleted file mode 100644 index 7359b729b..000000000 --- a/src/test/kc/complex/splines/truetype-splines.c +++ /dev/null @@ -1,128 +0,0 @@ -// Show a few simple splines using the splines library - -#include "splines.c" -#include -#include -#include -#include -#include - -char* const PRINT_SCREEN = 0x0400; -char* const BITMAP_SCREEN = 0x5c00; -char* const BITMAP_GRAPHICS = 0x6000; - -// A segment of a spline -struct Segment { - enum SegmentType { MOVE_TO, SPLINE_TO, LINE_TO} type; - struct SplineVector16 to; - struct SplineVector16 via; -}; - -// True type letter c -struct Segment letter_c[22] = { - { MOVE_TO, {108,146}, {0,0} }, - { SPLINE_TO, {89,182}, {103,169} }, - { SPLINE_TO, {59,195}, {75,195} }, - { SPLINE_TO, {23,178}, {38,195} }, - { SPLINE_TO, {9,132}, {9,161} }, - { SPLINE_TO, {25,87}, {9,104} }, - { SPLINE_TO, {65,69}, {42,69} }, - { SPLINE_TO, {93,79}, {82,69} }, - { SPLINE_TO, {105,98}, {105,88} }, - { SPLINE_TO, {102,106}, {105,103} }, - { SPLINE_TO, {93,109}, {98,109} }, - { SPLINE_TO, {81,104}, {85,109} }, - { SPLINE_TO, {78,93}, {79,101} }, - { SPLINE_TO, {73,82}, {78,86} }, - { SPLINE_TO, {61,78}, {69,78} }, - { SPLINE_TO, {40,88}, {48,78} }, - { SPLINE_TO, {29,121}, {29,100} }, - { SPLINE_TO, {40,158}, {29,142} }, - { SPLINE_TO, {68,174}, {50,174} }, - { SPLINE_TO, {91,166}, {80,174} }, - { SPLINE_TO, {104,144}, {98,160} }, - { LINE_TO, {108,146}, {0,0} } -}; - -void main() { - mulf_init(); - bitmap_init(BITMAP_GRAPHICS, BITMAP_SCREEN); - bitmap_clear(BLACK, WHITE); - vicSelectGfxBank(BITMAP_SCREEN); - *D018 = toD018(BITMAP_SCREEN, BITMAP_GRAPHICS); - *D011 = VICII_BMM|VICII_DEN|VICII_RSEL|3; - - char angle = 0; - while(true) { - bitmap_clear(BLACK, WHITE); - show_letter(angle); - for ( byte w: 0..60) { - do {} while(*RASTER!=0xfe); - do {} while(*RASTER!=0xff); - } - angle += 9; - } - - while(true) { (*(PRINT_SCREEN+999))++; } -} - -void show_letter(char angle) { - struct SplineVector16 current = {0,0}; - for( byte i: 0..21) { - struct SplineVector16 to = letter_c[i].to; - to = { to.x - 50, to.y - 150}; - to = rotate(to, angle); - to = { to.x + 100, to.y + 100}; - struct SplineVector16 via = letter_c[i].via; - via = { via.x - 50, via.y - 150}; - via = rotate(via, angle); - via = { via.x + 100, via.y + 100}; - struct Segment segment = { letter_c[i].type, to, via}; - if(segment.type==MOVE_TO) { - //bitmap_plot((unsigned int)segment.to.x, (unsigned char)segment.to.y); - current = segment.to; - } else if(segment.type==SPLINE_TO) { - spline_8segB(current, segment.via, segment.to); - bitmap_plot_spline_8seg(); - //bitmap_plot((unsigned int)segment.to.x, (unsigned char)segment.to.y); - //bitmap_plot((unsigned int)segment.via.x, (unsigned char)segment.via.y); - current = segment.to; - } else { - bitmap_line((unsigned int)current.x, (unsigned int)current.y, (unsigned int)segment.to.x, (unsigned int)segment.to.y); - current = segment.to; - } - } -} - - -// Plot the spline in the SPLINE_8SEG array -void bitmap_plot_spline_8seg() { - struct SplineVector16 current = SPLINE_8SEG[0]; - for(char n:1..8) { - bitmap_line((unsigned int)current.x, (unsigned int)current.y, (unsigned int)SPLINE_8SEG[n].x, (unsigned int)SPLINE_8SEG[n].y); - //bitmap_plot((unsigned int)current.x, (unsigned char)current.y); - current = SPLINE_8SEG[n]; - } -} - -// Sine and Cosine tables -// Angles: $00=0, $80=PI,$100=2*PI -// Sine/Cosine: signed fixed [-$7f,$7f] -signed char __align(0x40) SIN[0x140] = kickasm {{ - .for(var i=0;i<$140;i++) - .byte >round($7fff*sin(i*2*PI/256)) -}}; - -signed char* COS = SIN+$40; // sin(x) = cos(x+PI/2) - -// 2D-rotate a vector by an angle -struct SplineVector16 rotate(struct SplineVector16 vector, char angle) { - signed int cos_a = (signed int) COS[angle]; // signed fixed[0.7] - signed int xr = (signed int )mulf16s(cos_a, vector.x)*2; // signed fixed[8.8] - signed int yr = (signed int )mulf16s(cos_a, vector.y)*2; // signed fixed[8.8] - signed int sin_a = (signed int) SIN[angle]; // signed fixed[0.7] - xr -= (signed int)mulf16s(sin_a, vector.y)*2; // signed fixed[8.8] - yr += (signed int)mulf16s(sin_a, vector.x)*2; // signed fixed[8.8] - struct SplineVector16 rotated = { (signed int)(signed char)>xr, (signed int)(signed char)>yr }; - return rotated; -}