Visualizzazione post con etichetta C64. Mostra tutti i post
Visualizzazione post con etichetta C64. Mostra tutti i post

sabato 29 gennaio 2022

Setpixel su C64 (2)

 In un precedente post  avevo gia' affrontato il problema ...leggendo su codebase64 viene proposta una variante che usa delle tabelle di lookup per velocizzare il programma ma non viene presentato il codice completo. Questa e' una implementazione


.macro ClearScreen(screen, clearByte) {
lda #clearByte
ldx #0
!loop:
sta screen, x
sta screen + $100, x
sta screen + $200, x
sta screen + $300, x
sta screen + $400, x
sta screen + $500, x
sta screen + $600, x
sta screen + $700, x
sta screen + $800, x
sta screen + $900, x
sta screen + $a00, x
sta screen + $b00, x
sta screen + $c00, x
sta screen + $d00, x
sta screen + $e00, x
sta screen + $f00, x
sta screen + $1000, x
sta screen + $1100, x
sta screen + $1200, x
sta screen + $1300, x
sta screen + $1400, x
sta screen + $1500, x
sta screen + $1600, x
sta screen + $1700, x
sta screen + $1800, x
sta screen + $1900, x
sta screen + $1a00, x
sta screen + $1b00, x
sta screen + $1c00, x
sta screen + $1d00, x
sta screen + $1e00, x
sta screen + $1f00, x
inx
bne !loop-
}

.macro ClearColorRam(clearByte) {
lda #clearByte
ldx #0
!loop:
sta $0400, x
sta $0400 + $100, x
sta $0400 + $200, x
sta $0400 + $300, x
inx
bne !loop-
}


.macro Hires (){
lda $D018
//ora #%1000
ora #8
sta $D018 // VIC_ADDR + 24
}

.macro BMM (){
lda $D011
//ora #%100000
ora #32
sta $D011 // VIC_ADDR + 17
}


// costanti per la generazioni delle tabelle
// di lookup per calcolare la posizione del pixel
.const GFX_MEM = $2000

.const BitMask = $0a00
.const X_Table = $0b00
.const Y_Table_Lo = $0c00
.const Y_Table_Hi = $0d00

*=$0801 "Loader"
BasicUpstart($0810)


*=$0810 "Main" // SYS 2064

// generazione delle tabelle di lookup
ldx #$00
lda #$80
Loop1:
sta BitMask,x
ror
bcc Skip1
ror
Skip1:
tay
txa
and #%11111000
sta X_Table,x
tya
inx
bne Loop1

lda #<GFX_MEM // Can be replaced with a TXA if GFX_MEM is page aligned
Loop2:
ldy #$07
Loop3:
sta Y_Table_Lo,x
pha
SMC1:
lda #>GFX_MEM
sta Y_Table_Hi,x
pla
inx
dey
bpl Loop3
inc SMC1+1
clc
adc #$40
bcc Skip2
inc SMC1+1
Skip2:
cpx #8*25
bne Loop2

// ********************************************************
jsr $e544 // kernal clear screen
//:SetBorderColor(BLACK)
//:SetBackgroundColor(BLACK)


:Hires()
:BMM()

:ClearScreen($2000,0)
:ClearColorRam($3)



ldx #100 //posizione X del pixel
ldy #100 //posizione Y del pixel
jsr Plott

looper:
jmp looper
rts

Plott:
lda Y_Table_Hi,y
sta $fc
lda Y_Table_Lo,y
sta $fb

ldy X_Table,x
lda BitMask,x
ora ($fb),y
sta ($fb),y
rts





giovedì 27 gennaio 2022

Visual Code Assembler C64

Qualche tempo fa avevo provato CBM Prg Studio ma aveva diverse limitazioni (la prima fra tutte girare solo su Windows)



Per una soluzione multi piattaforma si puo' usare Visual Studio con l'estensione Kick Assembler 8-bit Retro Studio, Kick Assembler, Vice e C64 Debugger

Una volta installata la estensione si devono impostare nei settaggi del plugin le path dei vari componenti

Su Debian ho avuto diversi problemi con C64Debugger...installando la versione binaria viene generato il seguente errore 


sudo ln -sf libxcb-util.so.0 libxcb-util.so.1

il problema e' che la libreria non e' disponibile in apt e fare un symlink semplicemente blocca X al riavvio successivo

Per installare C64debugger da sorgenti si devono seguire i passi seguenti


apt install upx-ucl

git clone git://git.code.sf.net/p/c64-debugger/code c64-debugger-code
cd MTEngine

modificare Makefile aggiungendo -fcommon alle CFlags

make

domenica 13 settembre 2020

Retrocomputing estremo - salvataggio dati

 Antefatto : correva l'anno 1990 e, dovendo fare l'esame di maturita' scientifica, mi ero scritto la tesina su un Commodore 64 (C1541 a prestito) stampata poi su modulo continuo perforato. Feci due copie in floppy e le lasciai in una valigetta. I file erano stati generati dall'editor Easy Script (che era in uso in piccoli uffici come word processor)

Oggi : salvare il fondamentale (ovviamente sto scherzando) lavoro su SD card per trasmetterlo ai posteri (peraltro la copia cartacea esiste ancora anche se non sono riuscita a ritrovarla)

Il mio computer originale non esiste piu' (lo prestai a meta' anni 90 e non lo ho piu' rivisto) e mi sono ricreato un set simile ( non avevo un televisore a colori) con l'aggiunta di un modulo SD2IEC (montato su device 9 mentre il C1541 e' su device 8)

Il Commodore non e' proprio in salute come si vede dal diagnostico ma per l'uso previsto va piu' che bene. Legge il floppy e mi basta

Per copiare i file da floppy a SD ho usato Dracopy  Per evitare di distruggere una copia unica il floppy e' stato prima protetto da copia mettendo un po' di nastro da elettricista sulla tacca di protezione disco.

Ho fatto qualche prova di Dracopy prima sull'emulatore VICE perche' il software non e' molto intuitiivo

Alla fine ho scoperto che che si devono selezionare i file con Space, si preme C per copy, con F3 si seleziona il dispositivo in cui devono essere salvati e si conferma


lunedì 6 luglio 2020

Ritorno al 1985 (Grafica C64)

Una simpatica applicazione web http://c64.superdefault.com/ riscala le foto attuali nella palette e nelle dimensioni della grafica del C64



domenica 15 dicembre 2019

Monitor Commodore 1702

Non so se sia funzionante (non ho ancora avuto modo di provarlo) ma trovare un monitor Commodore 1702 al cassonetto e' diciamo un caso piu' unico che raro





lunedì 11 novembre 2019

Mandelbrot in 67 secondi su C64

Riuscire a calcolare l'insieme di Mandelbrot su un C64 e' stata una dellle sfide (perse) di quando ero ragazzo e leggevo Dewdney su Le Scienze


Adesso dopo tanti anni sono arrivato a 67 secondi  e sotto al minuto usando ottimizzazioni un po' piu' spinta (si perde pero' la cuspide del cardioide). Ulteriori miglioramenti possono essere fatti abbassando il limite massimo della variable k e usando una lookup table dei quadrati gia' calcolata

Per il calsolo sono stati utilizzati i seguenti sistemi

1) Emulazione Vice 3.3 al 100% di velocita' per emulare un C64 reale
2) Uso della tabella di lookup dei quadrati
3) Matematica a numeri interi
4) Algoritmo di calcolo che non prevede moltiplicazioni ma solo somme e sottrazioni
5) Uso di eseguibile compilato con CC65
6) Uso della simmetria


Massima ottimizzaziona impiegata con perdita della cuspide del cardioide
L'algoritmo e' quello gia' visto qui . Ottimizzazione del controllo sul cardiode da Wikipedia


da compilare con

cl65 -O -o "mande.prg" - t c64 --static-locals fractint.c

in giallo l'ottimizzazione del controllo sul cardioide

per migliorare gli algoritmi si puo' fare riferimento al seguente link

===========fractint.c===============
#include <stdio.h>
#include <stdlib.h>
#include <cc65.h>
#include <conio.h>
#include <tgi.h>


static void Mand (void)
{

    static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_ORANGE };
    register unsigned s,k;
    register int zi,zr,jr,ji,a,test;
    int q[180];

    tgi_setpalette (Palette);
    tgi_setcolor (1);

    for (s=1; s<170;s++)
{
q[s] = (int) (s*s/32);
}

    for (jr=-63;jr<18;jr++)
{
for (ji=-63; ji<1;ji++)
{
zi = zr = 0;

test = q[abs(jr-8)] + q[abs(ji)];
if (test*(test+(jr-8)) >  (q[abs(ji)]/4))

{
for (k=0; k<=25;k++)
{
a = q[abs(zr)] - q[abs(zi)] + jr;
zi = q[abs(zr)]+q[abs(zi)]-q[abs(zr-zi)]+ji;
zr = a;
if (q[abs(zr)] + q[abs(zi)] >  128 )
{
tgi_setcolor(k%2);
tgi_setpixel(jr+64,ji+64);
tgi_setpixel(jr+64,128-abs(63+ji));
k=26;
}
}
}
}
}

    cgetc ();
    tgi_clear ();
}



int main (void)
{

    tgi_load_driver (tgi_stddrv);
    tgi_init ();
    tgi_clear ();

    Mand();

    tgi_unload ();
    return EXIT_SUCCESS;
}

CC65 Tgidemo su Vice x64

Il compilatore CC65 permette di scrivere programmi in modalita' grafica mediante TGI ma non ero mai riuscito a farli poi eseguire dall'emulatore/C64 perche' l'eseguibile non riusciva a trovare la libreria grafica...la soluzione e' quella di creare un disco virtuale in cui copiare la libreria virtuale ed il file PRG


Si puo' iniziare compilando la demo con il comando

../bin/cl65 -O -o "tgidemo.prg"  -t c64 tgidemo.c

A questo punto con il comando c1541 (incluso in Vice) si crea un nuovo disco e si copiano i file tgidemo.prg e c64-hi.tgi

c1541 -format diskname,id d64 my_diskimage.d64 -attach my_diskimage.d64 -write tgidemo.prg
c1541 -attach my_diskimage.d64 -write c64-hi.tgi

dall'emulatore si seleziona Autostart Image ..si vedra' un messaggio "This program needs...." si preme y e si attende qualche secondo
A questo punto apparira' la schermata dell'immagine soprastante

venerdì 25 ottobre 2019

Mandelbrot C64 con tabella dei quadrati

circa 40 minuti di esecuzione..usando l'algoritmo del post precedente 


per togliere un po- di bordo bianco si puo' modificare la riga 60 con

60 FOR JI = -35 TO 0

Si puo' migliorare leggermente









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

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



sabato 4 maggio 2019

Commodore 64 Multi Diagnostic Card

Per imparare un po' di hardware Commodore 64 mi sono comprato su Ebay u C64 biscottone dichiarato come non funzionante. Per rendermi la vita un po' piu' facile mi sono comprato una scheda di diagnostica con montate 5 ROM selezionabili via switch



Il C64 acquistato e' effettivamente rotto e mostra schermo nero...il problema e' che pur inserendo la scheda diagnostica lo schermo rimane nero.
Ho preso quindi il mio C64 funzionante ......ed ho avuto una pessima notizia...la scheda di diagnostica mostra una seria di problemi sui due CIA (U1 ed U2) e sul SID (U18)

I CIA servono all'IO del computer e quindi cio' giustifica problema sulla cassetta, sulle control port e sulla seriale (oltre che sull'interrupt perche' i CIA gestiscono l'interrupt)....il SID e' inutile che descriva a cio' che serve









Geologi

  E so anche espatriare senza praticamente toccare strada asfaltata