Czeźdź, cześć, tudzież joł!
Zacząłem coś czytać, nieco rozumieć i pisać w asm'ie. Ponieważ z programowaniem mam tylko teoretyczne doświadczenia, zwracam się o pomoc do ludzi dobrej woli. Chodzi o sprawdzenie pliku 3d_math do wektorówki - poprawę ewentualnych błędów i jakieś przykłady podprogramów dzielenia i mnożenia (8b*16b) - najlepiej wg pomysłu z tablicowaniem, tj.  a*b = f(a+b) - f(a-b)

pozdrawiam serdecznie

3d_math:

2

Nie bardzo mam czas dokładnie to analizować, ale zszokował mnie sposób mnożenia liczby przez 256, poprzez 8-krotne asl+ror... Jeśli już, to asl+rol. A poza tym, nie łatwiej przepisać bajtów całych? :)
Podobnie z dzieleniem przez 512...
To tak na pierwszy rzut, jak znajdę chwilę to poczytam więcej.

[ Dodano: Sob Sty 22, 2005 8:45 pm ]
Ojej. I czemu chcesz używać 360 stopni? Używaj 256, to znacząco ułatwia życie :)

[ Dodano: Sob Sty 22, 2005 8:53 pm ]
Poza tym, w Rotate na oko w X i Y wstawiasz to samo, zupełnie bez sensu, nic nie kumam już. Czemu indeksujesz (sinus)? Spróbuj tak (skoro juz musisz tak podchodzic do tematu):

  lda katx
  asl @
  tax 
  lda katx+1
  rol @
  tay
  lda sinus,x
  sta _sinx
  lda sinus+1,y
  sta _siny+1

Ogólnie, nie podoba mi się ten kod, zacznij uczyć się może assemblera od czegoś prostszego, poważnie :)

: 404. Stopka not found

3

Błąd w procedurce:

odj16:
    sec
    lda lsb1
    sbc lsb2
    sta lsb_3
    lda msb1
    lda msb
    sta msb_3

    rts

Zamiast lda msb powinno być sbc msb2.

4

hmm...
mnozenie przez 256 mozna latwiej i o wiele szybciej zrobic tak: powiedzmy ,ze chcesz pomnozyc liczbe 16bitowa przez 256 (wynik 24bit)

lda liczba
sta wynik+1
lda liczba+1
sta wynik+2
lda #$00
sta wynik

dzielenie liczby 16bitowej (ze znakiem) przez 512 mozna zrobic szybciej po przez pominiecie najmlodszego bajtu (czyli podzielenie przez 256) oraz podzielenie tego przez 2 (256*2=512):

    lda liczba+1 ; starszy bajt liczby do podzielenia
    bmi _ujemna
    lsr @
    sta wynik ; wynik 8bitowy
    jmp _dalej

_ujemna    eor #$ff
    clc
    adc #$01
    lsr @
    eor #$ff
    clc
    adc #$01
    sta wynik

_dalej    ...

jesli chodzi o szybkosc to dzielic przez 512 mozna tak :)

    ldx liczba+1
    lda div512tb,x

wystarczy miec teraz talibce 256 bajtowa, ktora tworzysz tak:

gendvtb    ldx #$00
    txa
    bpl _neg
    lsr @
    sta div512tb,x
    jmp _gendv
_neg    eor #$ff
    clc
    adc #$01
    lsr @
    eor #$ff
    clc
    adc #$01
    sta div512tb,x
_gendv    inx
    bne gendvtb+2

i masz dzielenie przez 512 liczby 16bitowej w 7-9cykli ;)


co do mnozenia liczby 8bitowej przez 8bitowa to jest bardzo dobry przyklad tutaj: http://www.6502.org/source/integers/fastmult.htm

korzysta on z zaleznosci, ze: a*b=f(a+b)-f(a-b), f(x)=x*x/4
chyba najlepszy i najszybszy sposob na mnozenie (pomijajac pamieciozerne tablice :>)

gorzej jesli chcesz pomnozyc WIEKSZE liczby ze znakiem, mialem ostatnio wlasnie taki problem...

ztablicowanie wynikow (8bit * 8bit) zajmie dokladnie cala pamiec atarynki, wiedz odpada...

mozna tak stworzyc tablice f(x) ,zeby dalo sie pomozyc liczby ze znakiem ale sa pewne ograniczenia:
jesli a+b>128 mamy przepelnienie
jesli a-b>128 mamy przepelnienie
wiedz np. nie pomnozymy liczby 124 razy 8 bo 124+8 daje nam -124 (w kodzie U2) wiedz mamy przepelnienie,

mozna zastosowac tutaj pewna wlasciwosc ,ze

a*b=(a_lo+256*a_hi)*b=(a_lo*b) + 256*(a_hi*b)

dzieki czemu mozna obliczyc mnozenie 16bit ze znakiem razy 8bit ze znakiem po przez 2 mnozenia 8bit*8bit ze znakiem, niestety takie cos zajmuje ~100cykli wiedz przy duzej ilosc mnozen to odpada...

ja ten problem rozwiazlem tak (mnozy 9bitowa liczbe ze znakiem razy 8bitowa liczbe ze znakiem):

; tmp,tmp+1 * Y
; bestcase: 10+mul+rts (unsigned by unsigned)
; worstcase: 37+mul+rts (unsigned by signed)
; worstcase: 35+mul+rts (signed by unsigned)
; worstcase: 26+mul+rts (signed by signed)
;
mul16    bmi neg0
    lda tmp+1
    bmi neg2
    lda tmp
    jsr mul
    rts
neg2    lda tmp
    eor #$ff
    clc
    adc #$01
    jsr mul
    tay
    lda res
    eor #$ff
    clc
    adc #$01
    sta res
    tya
    eor #$ff
    adc #$00
    rts

neg0    lda tmp+1
    bmi neg1
    lda negtab,y
    ldy tmp
    jsr mul
    tay
    lda res
    eor #$ff
    clc
    adc #$01
    sta res
    tya
    eor #$ff
    adc #$00
    rts

neg1    lda negtab,y
    sta tmp2
    ldy tmp
    lda negtab,y
    ldy tmp2
    jsr mul
    rts

majac szybkie mnozenie 8bit*8bit=16bit res (takie jak w przykladzie z 6502.org) da to nam wynik w przyzwoitym czasie (oczywiscie jsr mul nalzy zastapic cala procedura mnozenia ,zeby nie tracic 12cykli na jsr+rts)

ale jesli to ma byc prosta scena 3d najlepszym i najszybszym sposobem jest zrobienie sobie tablicy sin(a)*x, i bez zadnego mnozenia mozemy obracac punkty w bardzo szybkim tepie (niestety bardzo pamieciozerne ;>, poniwaz przy 128katach i "gridzie" -64..64 tablica sinosow zajmuje nam 16384bajty...)
oczywiscie da sie ta tablice skrocic kosztem kilku(nastu) cykli np. wiedzadz ,ze -64*-43 to to samo co -(64*-43), dzieki czemu mozemy ztablicowac tylko wartosci dodatnie i przed mnozeniem sprawdzac znaki (a potem je zmieniac).
majac taka fajna tablice obrot punktu to poprostu pare linijek, cos w stylu tego:

ldy X
lda (costab),y
sec
ldy Y
sbc (sintab),y
sta newX

ldy X
lda (sintab),y
clc
ldy Y
adc (costab),y
sta newY

oczywiscie przed obrotem nalzy ustawic wskazniki sintab i costab tak aby wskazywaly do wartosci wynikow odpowiedniego dla danego kata:

lda katalfa
clc
adc #>sintab
sta sintab+1
lda katalfa
clc
adc #>costab
sta costab+1
lda #$00
sta sintab
sta costab

i robimy to tylko RAZ przed obrotem punktow.

jesli chodzi ogolnie o programowaniu 6502 to najlepsza strona jaka znalazlem jest: http://www.ffd2.com/fridge/chacking/
na niej praktycznie nauczylem sie programowac w asemblerze, co prawda przyklady sa dla c64 ale procesor jest ten sam, wiedz nie ma zadnego problemu, polecam nr 9 gdzie jest bardzo spory artykul o programowaniu 3d na 6502 (mnozenie, dzielenie, perspektywa, obroty, macierze itp)

5

Spróbuj tak (skoro juz musisz tak podchodzic do tematu):

  lda katx
  asl @
  tax 
  lda katx+1
  rol @
  tay
  lda sinus,x
  sta _sinx
  lda sinus+1,y
  sta _siny+1

Tak się nie da. Tablica sinus ma 720 bajtów długości. Trzeba najpierw obliczyć offset, do niego dodać adres początku tablicy i dopiero wówczas wyciągnąć z niej dane.

6

Racja. Nie przeczytałem z uwagą. Chciałem poprawić to co on zamierzał, nie zastanawiając się za bardzo nad całością. Ech, wstyd.

: 404. Stopka not found

7

"Ogólnie, nie podoba mi się ten kod, zacznij uczyć się może assemblera od czegoś prostszego, poważnie"

Tak kiedyś myślałem że może lepiej scrolla na początek, ale potrzebowałem czegoś, co nie wymagało znajomości ANTICA, tylko czystego 6502. A że nic innego mi do głowy nie przyszło, to bierze się traktorzysta za ferrari. :) Postaram się dokładnie zanalizować wszystkie uwagi (dziękuję za odzew, dla mnie to ważne, bo sam sobie - jak eru dobrze zauważyłeś - nijak radzę) po rozłączeniu z TPSA.

pozdrawiam

[ Dodano: Pon Sty 24, 2005 10:10 ]
eru:

"Jeśli już, to asl+rol. A poza tym, nie łatwiej przepisać bajtów całych?"
Nie jestem kumaty w slangu. Możesz wyjaśnić na przykładzie?

"Ojej. I czemu chcesz używać 360 stopni? Używaj 256, to znacząco ułatwia życie"

Tzn. przy obrocie o 360 robimy najpierw 256 i później tak obrócone punkty dodatkowo ruszamy o 64 stopnie?

"Poza tym, w Rotate na oko w X i Y wstawiasz to samo, zupełnie bez sensu, nic nie kumam już."

Nie tylko w X i Y, ale także w Z :). Inne są jedynie zmienne kątów i sinusów (_sinx, _siny, _sinz...), a reszta rzeczywiście identyczna. Chciałem kiedyś zrobić pętlę na jednej procedurze, ale był problem ze zmianą adresu etykiety. Teraz dopiero się domyślam, jak to wykonać - czy poprawne będzie coś w stylu:

    ldy #2            ;przesunięcie
    lda katx,y        ;katx+2b = katy

"Czemu indeksujesz (sinus)?"
Myślałem, że (zmienna),y dodaje do adresu wartość z y. Robi to więc sinus,y?
BTW: rol katx+1 - tak się da, czy tylko w taki sposób jak u Ciebie?

pr0be:

Co do przykładu 1: chodzi więc poprostu o coś w stylu xchg ah, al, tzn. zamianę bajtów miejscami?

"ale jesli to ma byc prosta scena 3d najlepszym i najszybszym sposobem jest zrobienie sobie tablicy sin(a)*x"

Myślę że na początek rzeczywiście dobry sposób, a ja niepotrzebnie komplikuję sobie zabawę...

Zdaje sobie sprawę, że moja "pryczka" w obecnym stadium nie nadaje się do czegokolwiek poważniejszego (chyba, że nadrobiłoby się dizajnem, narazie jednak chodzi o samo zrozumienie kodowania), ale gdyby poprawić wytłuszczone przez Was błędy, to jest szansa na jakiś obrót (choćby 8 punktów w ramce ;)), czy pisać to od początku trzeci raz?

8

"Ojej. I czemu chcesz używać 360 stopni? Używaj 256, to znacząco ułatwia życie"

Tzn. przy obrocie o 360 robimy najpierw 256 i później tak obrócone punkty dodatkowo ruszamy o 64 stopnie?

Chodzi o taki mily trick, zeby wykorzystac fakt, ze 6502 bardzo lubi liczbe 256  ;). Jezeli wiec podzielimy sobie kat pelny nie na 360 jednostek, a na 256, to obliczenia trygonometryczne (uzywajac tablic sin cos i pochodnych) baaardzo nam sie uproszcza.

pozdrawiam

9

Takie buty...

A to nie ujmuje realizmu obrotowi (rotacja skokowa)? Jeśli nie stanowiłoby problemu, mógłbym Cię prosić o ciut szersze wyjaśnienie?

10

Różnica między 360 a 256 kątami obrotu jest zasadniczo niezauważalna.
Dzięki temu np. kąt zawsze się mieści w 1 bajcie co ułatwia i usprawnia obliczenia.
Myślę, że na 8 bitach, w rozdzielczościach jakie mamy, 256 kątów zupełnie wystarcza.

: 404. Stopka not found

11

Dokładnie. Różnica jest niezauważalna. Poza tym przy podziale na 360 stopni też masz rotacje skokową. By mieć płynną musiałbyś podzielić pełny obrót na 1/0 kawałków, czyli nieskończoność. ;)

256 "stopni" to po prostu inna skala podziału, a podział na 360 jet i tak umowny. Na upartego możesz zielić na radiany i bawić sie ułamkami. Nota bene, przy 256 i 360 też możesz.

[ Dodano: 25.01.2005 23:35:31 ]
A tak się ma +1 do statsów na AA i Mistrza offtopicu. :mrgreen:

Zawsze mam rację, tylko nikt mnie nie słucha.

12

Ja we wszystkich demach używałem tablic co 2 stopnie i tego też nie było widać więc nawet 180 stopni jest przy tych rozdzielczościach wystarczające. Po za tym skakanie bardziej jest spowodowane małą szybkością obliczeń i rysowania niż skokiem w tablicy sinusów.

Ważniejsze jest co ile ramek dany efekt chodzi (dokładnie co ile obrazów narysowanych na ekranie - max. 50 - tyle klatek oglądasz na sekundę)