forum speccy.pl

ZX Spectrum => PROGRAMOWANIE => Wątek zaczęty przez: Dalthon w 2018.08.21, 02:46:31

Tytuł: Procedura DRAW w ROM z 3 parametrem
Wiadomość wysłana przez: Dalthon w 2018.08.21, 02:46:31
O ile rysowanie punktu procedurą z ROM jest banalne...

10 PLOT 80,80

ld b,80 ; y
ld c,80 ; x
call 8933

... linie też się bez problemu rysuje...

10 PLOT 8,80
20 DRAW 10,10

ld b,80 ; y
ld c,80 ; x
call 8933

ld b,10 ; Y
ld c,10 ; X
ld d,1 ; +Y
ld e,1 ; +X
call 9402

... tak nie mam pojęcia (a analizowałem sobie rom tutaj: http://skoolkid.github.io/rom/) jak zrobić rysowanie 'po łuku'...

10 PLOT 80,80
20 DRAW 10,10,.5

Ktoś, coś? ;)
Tytuł: Odp: Procedura DRAW w ROM z 3 parametrem
Wiadomość wysłana przez: matofesi w 2018.08.21, 08:05:39
Musiałbym pogrzebać, ale w związku z tym, że trzeci parametr jest ułamkowy więc prawie na pewno będzie trzeba go przekazywać przez stos kalkulatora. I pozostałe dwa raczej też.

Zajrzę do TCSRD i spróbuję coś "wywąchać" ;)

edit: Wywąchałem... Nie podejmuję się opisać na 100% jak się to robi ;)
A wydaje mi się, że robi się tak jak myślałem - najpierw ustawiamy współrzędne początku linii w COORDS, potem na stos kalkulatora wrzucamy X, Y i kąt (kąt leży na górze, Y, X poniżej) a następnie skaczemy w środek procedury DRAW - pod adres $2394. Tam zaczyna się program dla kalkulatora, który robi kontrolę kąta, kierunku itp. dzieli łuk na mniejsze kawałki i w pętli (cały czas napieprzając kalkulatorem ;)) wywołuje LINE-DRAW ($2477) rysując przybliżenie zadanego parametrami łuku. Z tej procedury widzę dwa wnioski - już wiem, czemu to jest takie cholernie wolne i już wiem skąd się bierze rysowanie "gwiazdek" jak się zada dziwny kąt jako parametr.
Tytuł: Odp: Procedura DRAW w ROM z 3 parametrem
Wiadomość wysłana przez: matofesi w 2018.08.21, 09:00:20
Ok. Zrobiłem w ASMie ;)

        org $8000

        ld a,100
        ld (23677),a            ; początkowe X
        ld a,50
        ld (23678),a            ; początkowe Y

        ld a,50
        call $2d28              ; wrzuć na stos kalkulatora A - X linii
        ld a,50
        call $2d28              ; j.w. - Y linii

        rst $28                         ; FP-CALC
        db $34                          ; stk-data - wrzuć na stos kalkulatora liczbę FP
        db $f1, $49, $0f, $da, $a2      ; PI/2
        db $38                          ; end-calc

        call $2394              ; rysowanie łuku wg parametrów ze stosu kalkulatora

        ld hl,$2758             ; wracamy do BASICa - kalkulator zmienia
                                ; HL' trzeba więc przywrócić właściwą
                                ; zawartość
        exx

        ret

        end $8000

Powyższy kod jest mniej więcej odpowiednikiem PLOT 100,50 : DRAW 50,50,PI/2

Tak jak pisałem - najpierw ładujemy do COORDS początkowe współrzędne (PLOT bez PLOTa ;)), potem wrzucamy na stos parametry w tym ułamkowy kąt a następnie skaczemy do rysowania łuku. Na koniec odtwarzamy HL' - to jeden z błędów w ROMie - HL' musi być na wyjściu procedur używających kalkulatora ustawiony na $2758, jeśli tak nie jest program się po prostu zawiesi po wykonaniu ostatniego RET.

Całość działa tak samo jak z BASICa i jedyny problem, to przygotowanie startowych parametrów jeśli chcemy rysować łuki oparte na jakichś konkretnych kątach. Albo trzeba te liczby wyliczać kalkulatorem albo np. wydłubywać ze zmiennoprzecinkowej reprezentacji w programie BASICowych albo zmiennej ;)
Tytuł: Odp: Procedura DRAW w ROM z 3 parametrem
Wiadomość wysłana przez: Dalthon w 2018.08.21, 11:52:19
Ooooooooooooooo...  rozpykałeś to bez mydła! Wielkie dzięki!!! Teraz tylko rozkminić jak zapisywane są ułamki i będzie z górki :)

Szkoda że już nie robisz nic na zx'ie - taki talent się marnuje...
Tytuł: Odp: Procedura DRAW w ROM z 3 parametrem
Wiadomość wysłana przez: steev w 2018.08.21, 12:13:44
Prosz... :>
http://www.worldofspectrum.org/z88forever/dn327/fpp.htm
Tytuł: Odp: Procedura DRAW w ROM z 3 parametrem
Wiadomość wysłana przez: matofesi w 2018.08.21, 12:20:02
Ooooooooooooooo...  rozpykałeś to bez mydła! Wielkie dzięki!!! Teraz tylko rozkminić jak zapisywane są ułamki i będzie z górki :)

Liczby zmiennoprzecinkowe co do zasady zapisywane są wykładniczo jako pięć bajtów, ale mogą też być 2 albo 4 o ile pamiętam. W kilku miejscach były opisy jak to jest przeliczane, ale jakoś nigdy nie miałem zacięcia, żeby się w to wgryzać. Najprostsza metoda przeliczenia wartości ułamkowej na odpowiedni zapis dla kalkulatora to użycie takiej liczby w programie w BASICu (ROM zamieni za ciebie cyferki na formę FP) a potem podejrzenie w pamięci co mu wyszło - liczba jest w linii BASICa zapisana najpierw tekstem potem jest $0e a potem pięć bajtów reprezentacji FP. Można też kazać ROMowi sparsować tekst i zamienić na postać FP albo "wyliczyć" sobie kalkulatorem jeśli dana wartość jest "wyliczalna".

Cytuj
Szkoda że już nie robisz nic na zx'ie - taki talent się marnuje...

Mój problem z robieniem na cokolwiek jest taki, że mam problemy z wymyśleniem tego, CO ewentualnie miałbym zrobić. Wolę się zajmować rozwiązywaniem zadanych przez kogoś problemów nić wymyślać sobie własne. Przynajmniej jeśli chodzi zabawę ;)
Tytuł: Odp: Procedura DRAW w ROM z 3 parametrem
Wiadomość wysłana przez: matofesi w 2018.08.21, 12:21:57
Prosz... :>
http://www.worldofspectrum.org/z88forever/dn327/fpp.htm

Hmmm... Czy z88 aby na pewno używa systemowego kalkulatora i zgodnego z nim formatu liczb?

Nie używałem to nie wiem :)
Tytuł: Odp: Procedura DRAW w ROM z 3 parametrem
Wiadomość wysłana przez: ZbyniuR w 2018.08.21, 13:08:09
A czy przypadkiem liczba w 5 bajtach nie jest tak że w każdej połówce bajta jest jedna cyfra dziesiętna?
Tylko nie wiem gdzie przecinek trzyma.
Tytuł: Odp: Procedura DRAW w ROM z 3 parametrem
Wiadomość wysłana przez: matofesi w 2018.08.21, 13:10:35
@ZbyniuR Przypadkiem nie. Celowo też nie.

W pierwszym bajcie jest wykładnik, w pozostałych czterech mantysa.
Tytuł: Odp: Procedura DRAW w ROM z 3 parametrem
Wiadomość wysłana przez: matofesi w 2018.08.21, 14:23:41
W dodatku do Komputera "Tajniki ZX Spectrum" Andrzej Kadlof wyjaśniał zapis liczb w taki sposób:

Cytuj
Sposoby kodowania liczb większych i zmiennoprzecinkowych
są w różnych komputerach rozmaite. W ZX-Basic wszystkie
liczby są przechowywane w pięciu kolejnych komórkach pamięci.
Dla programisty istnieją tylko liczby zmiennoprzecinkowe,
ale w pamięci liczby całkowite z przedziału - 65536...65535 są
kodowane w innej postaci niż pozostałe. Pierwszy i ostatni bajt
w ich przedstawieniu zawsze zawiera zero. Drugi bajt jest równy
0 dla liczb dodatnich i 255 dla ujemnych. W trzecim i czwartym
umieszcza się odpowiednio młodszy i starszy bajt danej liczby,
przy czym wartości ujemne są pamiętane w kodzie uzupełnień do
dwóch. Np. liczba 38 wygląda tak: 0 0 0 38 0, natomiast
743=2*256+231 ma postać 0 0 231 2 0. Z kolei - 1231 zapamiętane
jest jako 0 255 251 49 0, bo 256*251+49=65536-1231.

Z pozostałymi liczbami sprawa jest bardziej zawiła. Wykorzystuje
się fakt, że każdą liczbę można jednoznacznie przedstawić
w postaci 2 ^ n*m, gdzie m jest liczbą z przedziału [1/2,1]. W
pierwszym bajcie Spectrum przechowuje wartość n+128. W pozostałych
czterech umieszczona jest liczba m w postaci binarnej, a
dokładnie - m*2 ^ 32, z tym, że najstarszy bit, który powinien
zawsze być równy 1 służy do przechowywania znaku liczby. Jedynka
oznacza minus a zero plus.

Przypuśćmy, że pięć kolejnych komórek pamięci zawiera liczby
130 212 16 34 178. Są one interpretowane jako liczba

2 ^ (130-128)*(212/2 ^ 8+16/2 ^ 16+34/2 ^ 24+178/2 ^ 32),

natomiast bajty 106 112 4 231 78 przedstawiają liczbę

2 ^ (106-128)*((128+112)/2 ^ 8+4/2 ^ 16+231/2 ^ 24+78/2 ^ 32)

Nie przekonuje mnie ta matematyka, ale może komuś coś z tego wyniknie ;)
Tytuł: Odp: Procedura DRAW w ROM z 3 parametrem
Wiadomość wysłana przez: Tygrys w 2018.08.21, 15:10:38
Ciekawa lekturą. Póki co nie wykorzystywałem procedur rysujących z ROM.

Trochę więcej, wraz z przykładowym programem wylicząjacym IEEE 754, znajduje się na stronie https://eduinf.waw.pl/inf/alg/006_bin/0022.php, co jest dobrym uzupełnieniem wiedzy dotyczącej DRAW oraz parametrów dla niego.
Tytuł: Odp: Procedura DRAW w ROM z 3 parametrem
Wiadomość wysłana przez: matofesi w 2018.08.21, 15:52:10
To jeszcze na koniec to o czym pisałem czyli metoda na przekształcenie tekstowej reprezentacji liczby na liczbę FP na stosie kalkulatora:

        org $8000
ch_add  equ 23645

        ld a,2
        call $1601      ; chan-open

; === POCZĄTEK ===
        ld hl,(ch_add)
        push hl

        ld hl,number
        ld (ch_add),hl

        rst $20
        call $2c9b      ; dec-to-fp

        pop hl
        ld (ch_add),hl
; === KONIEC ===

        call $2de3      ; print-fp

        ld hl,$2758
        exx
        ret

number
        db 0
        db "12.345"
        db 0

Właściwy kod jest między POCZĄTEK a KONIEC - reszta to otoczka otwierająca kanał 2 i drukująca liczbę FP ze stosu kalkulatora na ekran.

A właściwy kod najpierw zachowuje na stosie (procesora) zawartość zmiennej ch_add a potem przestawia ją na adres tekstowej reprezentacji liczby, którą chcemy dostać w formacie FP. Następnie wywoływane jest RST $20 pobierające znak spod ch_add - nie analizowałem dlaczego, ale pierwszy znak przez procedurę jest pomijany stąd db 0 na początku. Po pobraniu znaku skaczemy do właściwej procedury dec-to-fp, która parsuje to, co dostała i przetwarza na formę FP - obsługuje wszystkie formy zapisu liczb, których można użyć w BASICu (.123, 1.234, 1.2E2 itp.) i kończy analizę po napotkaniu znaku, który nie jest dopuszczalną częścią liczby (tutaj ostatnie db 0). Po wyjściu mamy na stosie kalkulatora formę FP liczby, którą na zewnątrz drukujemy na ekran używając print-fp a w praktycznych zastosowaniach używamy jej np. jako parametru dla DRAW albo do innych obliczeń kalkulatorem.

Tytuł: Odp: Procedura DRAW w ROM z 3 parametrem
Wiadomość wysłana przez: Dalthon w 2018.08.21, 19:29:07
Zawsze można liczyć na forum - nawet taki niszowy temat rozpracowany na czynniki pierwsze :)

Szkoda że ten 3 parametr jest tak zapisywany - z racji długości, raczej ciężko będzie to wykorzystać w 256b produkcjach (bo taki był pierwotny zamysł) ale do 1kB i 4kB jak znalazł!

ps. muszę częściej wrzucać tutaj swoje rozterki, zamiast odpuszczać i wymyślać co innego :D
Tytuł: Odp: Procedura DRAW w ROM z 3 parametrem
Wiadomość wysłana przez: Dalthon w 2019.07.22, 00:02:13
Taaaa... jednak za głupi jestem :/

A jak ze znakami? Próbuję zrobić

10 PLOT 0,47
20 DRAW 255,0,-3.14

albo (bo efekt ten sam;)

10 PLOT 255,47
20 DRAW -255,0,3.14

i nic mi z tego nie wychodzi :(
Tytuł: Odp: Procedura DRAW w ROM z 3 parametrem
Wiadomość wysłana przez: steev w 2019.07.22, 01:36:49
Problem pewnie w tym, że  stk-data wymaga nie po prostu liczby, ale liczby w postaci 'skondensowanej'.
Więc -pi to nie $82, $c8, $f5, $c2, $8f ale  $f2, $c8, $f5, $c2, $8f.

        org $8000

        ld a,0
        ld (23677),a            ; początkowe X
        ld a,47
        ld (23678),a            ; początkowe Y

        ld a,255
        call $2d28              ; wrzuć na stos kalkulatora A - X linii
        ld a,0
        call $2d28              ; j.w. - Y linii

        rst $28                                 ; FP-CALC
        db $34                                  ; stk-data - wrzuć na stos kalkulatora liczbę FP
        db $f2, $c8, $f5, $c2, $8f              ; -PI
        db $38 

        call $2394         ; rysowanie łuku wg parametrów ze stosu kalkulatora

        ld hl,$2758        ; wracamy do BASICa - kalkulator zmienia
                           ; HL' trzeba więc przywrócić właściwą
                           ; zawartość
        exx

        ret
Tytuł: Odp: Procedura DRAW w ROM z 3 parametrem
Wiadomość wysłana przez: Dalthon w 2019.07.22, 03:31:14
Wow! A ja siedziałem i kombinowałem...

Pierwotnie mając PI $82, $48, $f5, $c2, $8f jasne dla mnie było że 2 bajt zmienia się przy -PI na $c8 ale co się dzieje z 1 bajtem to dla mnie zagadka (pewnie za dużo piwa dzisiaj;p)

Wielkie dzięki! Teraz wiem że dla PI (bez minusa) powinno być $f2, $48, $f5, $c2, $8f - tylko nie wiem dlaczego (te czary z 1 bajtem...).
Tytuł: Odp: Procedura DRAW w ROM z 3 parametrem
Wiadomość wysłana przez: steev w 2019.07.22, 07:49:30
Pierwsze dwa bity określają do ilu bajtów została liczba 'skompresowana' (https://skoolkid.github.io/rom/asm/33C6.html)
Czy takie czary były faktycznie potrzebne i czy dały jakiś realny zysk - nie mam pojęcia, ale zakładam że jednak tak (bo są :) )
Tytuł: Odp: Procedura DRAW w ROM z 3 parametrem
Wiadomość wysłana przez: steev w 2019.07.22, 08:14:46
Nb. można też bez kombinowania z kalkulatorem :
        org $8000

        ld a,0
        ld (23677),a            ; początkowe X
        ld a,47
        ld (23678),a            ; początkowe Y

        ld a,255
        call $2d28              ; wrzuć na stos kalkulatora A - X linii
        ld a,0
        call $2d28              ; j.w. - Y linii

        ld hl,par3
        ld de,($5c65)           ;Point DE to STKEND.
        call $33c0              ;Stack the 5 bytes.
        ex de,hl                ;Point HL to the new position of STKEND, and reset the system variable.
        ld ($5c65),hl

        call $2394         ; rysowanie łuku wg parametrów ze stosu kalkulatora

        ld hl,$2758        ; wracamy do BASICa - kalkulator zmienia
                           ; HL' trzeba więc przywrócić właściwą
                           ; zawartość
        exx
        ret

par3:   db $82, $c8, $f5, $c2, $8f
Tytuł: Odp: Procedura DRAW w ROM z 3 parametrem
Wiadomość wysłana przez: Dalthon w 2019.07.22, 18:50:53
Naprawdę wielkie dzięki! Efekt potrzebny osiągnięty - będzie w kolejnym 1kB wykorzystane ;)