venerdì 24 maggio 2019

Mandelbrot testuale con CC65 su C64

Ero partito con l'idea ambiziosa di creare l'insieme di Mandelbrot in Assembly 6502 per Commodore 64 usando un po' l'esperienza di questo precedente post
In sintesi volevo un calcolo rapido utilizzando solo gli interi e la modalita' testo (un po' per riprendere Tequila Virus per DOS)


Alla fine ho barato....usando CC65, il crosscompilatore per 6502 e' possibile ottenere, oltre all'eseguibile. anche un listato Assembly....e tra gli esempi c'e' pure un calcolo di Mandelbrot che rispetto l'algoritmo che mi ero prefisso


Il tempo di esecuzione e' stato 1 minuto e 37 secondi

Versione in C
--------------------------------------------------------------------------------------------
include <stdlib.h>
#include <stdio.h>
#include <conio.h>

#define SCREEN_X        40
#define SCREEN_Y        22

#define maxiterations   30
#define fpshift         (10)
#define tofp(_x)        ((_x)<<fpshift)
#define fromfp(_x)      ((_x)>>fpshift)
#define fpabs(_x)       (abs(_x))

#define mulfp(_a,_b)    ((((signed long)_a)*(_b))>>fpshift)
#define divfp(_a,_b)    ((((signed long)_a)<<fpshift)/(_b))

#pragma static-locals (1);


int main (void)
{
    register unsigned char count;
    register signed short r, r1, i;
    register signed short xs, ys, xx, yy;
    register signed short x, y;
    register signed short x1,y1,x2,y2;

    x1 = -2048;
    y1 = -1024;
    x2 = 1024;
    y2 = 1024;
    

    xs = 77;
    ys = 93;

    yy = y1;
    for (y = 0; y < (SCREEN_Y); y++) {
        yy += ys;
        xx = x1;
        for (x = 0; x < (SCREEN_X); x++) {
            xx += xs;
            /* Do iterations */
            r = 0;
            i = 0;
            for (count = 0; (count < maxiterations) &&
                 (fpabs (r) < 2048) && (fpabs (i) < 2048);
                 ++count) {
                r1 = (mulfp (r, r) - mulfp (i, i)) + xx;
                i = (((signed long) r * i) >> 9) + yy;
                r = r1;
            }
    textcolor(count/2);
    printf("O");
        }
    }

    return EXIT_SUCCESS;
}
--------------------------------------------------------------------------------------------


Traduzione in Assembly
--------------------------------------------------------------------------------------------
;
; File generated by cc65 v 2.17 - Git N/A
;
.fopt compiler,"cc65 v 2.17 - Git N/A"
.setcpu "6502"
.smart on
.autoimport on
.case on
.debuginfo off
.importzp sp, sreg, regsave, regbank
.importzp tmp1, tmp2, tmp3, tmp4, ptr1, ptr2, ptr3, ptr4
.macpack longbranch
.forceimport __STARTUP__
.import _abs
.import _printf
.export _main

.segment "RODATA"

L0067:
.byte $25,$63,$00

; ---------------------------------------------------------------
; int __near__ main (void)
; ---------------------------------------------------------------

.segment "CODE"

.proc _main: near

.segment "BSS"

L0003:
.res 1,$00
L0004:
.res 2,$00
L0005:
.res 2,$00
L0006:
.res 2,$00
L0007:
.res 2,$00
L0008:
.res 2,$00
L0009:
.res 2,$00
L000A:
.res 2,$00
L000B:
.res 2,$00
L000C:
.res 2,$00
L000D:
.res 2,$00
L000E:
.res 2,$00
L000F:
.res 2,$00
L0010:
.res 2,$00

.segment "CODE"

;
; x1 = -2048;
;
ldx     #$F8
lda     #$00
sta     L000D
stx     L000D+1
;
; y1 = -1024;
;
ldx     #$FC
lda     #$00
sta     L000E
stx     L000E+1
;
; x2 = 1024;
;
ldx     #$04
lda     #$00
sta     L000F
stx     L000F+1
;
; y2 = 1024;
;
ldx     #$04
lda     #$00
sta     L0010
stx     L0010+1
;
; xs = 77;
;
ldx     #$00
lda     #$4D
sta     L0007
stx     L0007+1
;
; ys = 93;
;
ldx     #$00
lda     #$5D
sta     L0008
stx     L0008+1
;
; yy = y1;
;
lda     L000E
ldx     L000E+1
sta     L000A
stx     L000A+1
;
; for (y = 0; y < (SCREEN_Y); y++) {
;
ldx     #$00
lda     #$00
sta     L000C
stx     L000C+1
L001F: lda     L000C
ldx     L000C+1
cmp     #$16
txa
sbc     #$00
bvc     L0027
eor     #$80
L0027: asl     a
lda     #$00
ldx     #$00
rol     a
jne     L0022
jmp     L0020
;
; yy += ys;
;
L0022: lda     L0008
ldx     L0008+1
clc
adc     L000A
sta     L000A
txa
adc     L000A+1
sta     L000A+1
tax
lda     L000A
;
; xx = x1;
;
lda     L000D
ldx     L000D+1
sta     L0009
stx     L0009+1
;
; for (x = 0; x < (SCREEN_X); x++) {
;
ldx     #$00
lda     #$00
sta     L000B
stx     L000B+1
L002D: lda     L000B
ldx     L000B+1
cmp     #$28
txa
sbc     #$00
bvc     L0035
eor     #$80
L0035: asl     a
lda     #$00
ldx     #$00
rol     a
jne     L0030
jmp     L0021
;
; xx += xs;
;
L0030: lda     L0007
ldx     L0007+1
clc
adc     L0009
sta     L0009
txa
adc     L0009+1
sta     L0009+1
tax
lda     L0009
;
; r = 0;
;
ldx     #$00
lda     #$00
sta     L0004
stx     L0004+1
;
; i = 0;
;
ldx     #$00
lda     #$00
sta     L0006
stx     L0006+1
;
; for (count = 0; (count < maxiterations) &&
;
ldx     #$00
lda     #$00
sta     L0003
L003D: ldx     #$00
lda     L0003
cmp     #$1E
jsr     boolult
jeq     L0045
;
; (fpabs (r) < 2048) && (fpabs (i) < 2048);
;
lda     L0004
ldx     L0004+1
jsr     _abs
cmp     #$00
txa
sbc     #$08
bvc     L0049
eor     #$80
L0049: asl     a
lda     #$00
ldx     #$00
rol     a
jeq     L0045
lda     L0006
ldx     L0006+1
jsr     _abs
cmp     #$00
txa
sbc     #$08
bvc     L004D
eor     #$80
L004D: asl     a
lda     #$00
ldx     #$00
rol     a
jne     L0043
L0045: ldx     #$00
lda     #$00
jeq     L004E
L0043: ldx     #$00
lda     #$01
L004E: jne     L0040
jmp     L003E
;
; r1 = (mulfp (r, r) - mulfp (i, i)) + xx;
;
L0040: lda     L0004
ldx     L0004+1
jsr     axlong
jsr     pusheax
lda     L0004
ldx     L0004+1
jsr     axlong
jsr     tosmuleax
txa
ldx     sreg
ldy     sreg+1
sty     sreg
cpy     #$80
ldy     #$00
bcc     L0058
dey
L0058: sty     sreg+1
jsr     asreax2
jsr     pusheax
lda     L0006
ldx     L0006+1
jsr     axlong
jsr     pusheax
lda     L0006
ldx     L0006+1
jsr     axlong
jsr     tosmuleax
txa
ldx     sreg
ldy     sreg+1
sty     sreg
cpy     #$80
ldy     #$00
bcc     L005E
dey
L005E: sty     sreg+1
jsr     asreax2
jsr     tossubeax
jsr     pusheax
lda     L0009
ldx     L0009+1
jsr     axlong
jsr     tosaddeax
sta     L0005
stx     L0005+1
;
; i = (((signed long) r * i) >> 9) + yy;
;
lda     L0004
ldx     L0004+1
jsr     axlong
jsr     pusheax
lda     L0006
ldx     L0006+1
jsr     axlong
jsr     tosmuleax
txa
ldx     sreg
ldy     sreg+1
sty     sreg
cpy     #$80
ldy     #$00
bcc     L0063
dey
L0063: sty     sreg+1
jsr     asreax1
jsr     pusheax
lda     L000A
ldx     L000A+1
jsr     axlong
jsr     tosaddeax
sta     L0006
stx     L0006+1
;
; r = r1;
;
lda     L0005
ldx     L0005+1
sta     L0004
stx     L0004+1
;
; ++count) {
;
ldx     #$00
inc     L0003
lda     L0003
jmp     L003D
;
; printf("%c",count+50);
;
L003E: lda     #<(L0067)
ldx     #>(L0067)
jsr     pushax
ldx     #$00
lda     L0003
ldy     #$32
jsr     incaxy
jsr     pushax
ldy     #$04
jsr     _printf
;
; for (x = 0; x < (SCREEN_X); x++) {
;
lda     L000B
ldx     L000B+1
sta     regsave
stx     regsave+1
jsr     incax1
sta     L000B
stx     L000B+1
lda     regsave
ldx     regsave+1
jmp     L002D
;
; for (y = 0; y < (SCREEN_Y); y++) {
;
L0021: lda     L000C
ldx     L000C+1
sta     regsave
stx     regsave+1
jsr     incax1
sta     L000C
stx     L000C+1
lda     regsave
ldx     regsave+1
jmp     L001F
;
; return EXIT_SUCCESS;
;
L0020: ldx     #$00
lda     #$00
jmp     L0002
;
; }
;
L0002: rts

.endproc

--------------------------------------------------------------------------------------------



Nessun commento:

Posta un commento

Alpine Linux 2024 su IBM A31

Ho provato a far resuscitare un IBM A31 destinato alla discarica. La macchina ha processore P4, 256 Mb di RAM, la batteria CMOS morta ed e&#...