26

drac030: Zrobiłem dużo testów, ale niewiele to pomogło.. Od samego początku staram się maksymalnie zoptymalizować grę, przez kilka tygodni robiłem tylko pomiary, testy, przyspieszenia i nie wiem co to wszystko.. :D

16-bit A: cały silnik = max 6,1 % klatki (0,35 fps przy 5,7) - para rep/sep kosztuje 6 cykli, tyle samo, ile oszczędza jedno 16-bitowe dodawanie; przerobiony blok w paint_col dał netto 1 cykl, drugi wywalił boot. clc/adc #1 = 0,1 %.

mvn/mvp: w klatce nie ma czego przenosić - te lda/sta to próbkowanie tekstur, nie kopiowanie bloku. Jedyna pętla kopiująca (spr_fcopy) chodzi przy ładowaniu, a jej cel to 4 KB okno VBXE, które trzeba przebankowywać co 4 KB, więc mvn musiałby iść bank po banku: 341 ms na wczytanie poziomu, zero fps.

27

Zależy ile się gra i ile jest założone :-)

Pamięć studenta ma charakter kwantowy - student wie wszystko, ale jednocześnie nic nie pamięta.
- Kilka(naście?) pudełek z klawiszami i światełkami. I jeden Vectrex, żeby nimi wszystkimi rządzić.

28

w1k napisał/a:

16-bit A: cały silnik = max 6,1 % klatki (0,35 fps przy 5,7) - para rep/sep kosztuje 6 cykli, tyle samo, ile oszczędza jedno 16-bitowe dodawanie; przerobiony blok w paint_col dał netto 1 cykl, drugi wywalił boot. clc/adc #1 = 0,1 %.

Tak, ja wiem, ile zajmuje rep/sep, i oczywiście, przy całkowicie ośmiobitowym kodzie, nie zawsze się opłaca przełączenie (dla pojedynczej operacji - prawie nigdy). Ale tam są takie oto na przykład ciągi rozkazów 8-bitowych:

https://www.atari.org.pl/forum/misc.php?action=pun_attachment&item=13796

Nie patrzę całościowo, więc nie wiem, czy ten kawałek ma jakikolwiek wpływ na renderowanie klatek, ale wygląda, jakby danie rep #$20 na początku, a sep #$20 gdzieś na końcu pozwoliło go skrócić o połowę.

Widziałem podobny kawałek kopiujący w podobny sposób z miejsca na miejsce bodaj 12 bajtów przy użyciu 24 rozkazów - 72 bajty, 96 cykli, przy przełączeniu na 16-bitowy akumulator zeszłoby to do 40 bajtów i 14 rozkazów na sumę 66 cykli.

Jakieś ciągi lsr/ror/lsr/ror na dwóch kolejnych bajtach, w pętlach i bez - to wszystko jest do optymalizacji.

Post's attachments

ciag_rozkazow.png 51.65 kb, nikt jeszcze nie pobierał tego pliku. 

Tylko zalogowani mogą pobierać załączniki.
KMK
? HEX$(6670358)

29

drac030 zapomniał że w1k nie jest programistą, co już w1k wyjaśniał

*- TeBe/Madteam
3x Atari 130XE, SDX, CPU 65816, 2x VBXE, 2x IDE Plus rev. C

30

Dzięki za troskę, ale o niczym nie zapomniałem - w1k może to wkleić Claudowi tak samo, jak wkleja tu jego odpowiedzi.

KMK
? HEX$(6670358)

31

drac030, dzięki, wprowadziłem zmiany, zmiana prędkości jest rzeczywiście tylko kosmetyczna. dziś/jutro opublikuję ostatnią wersję z poprawkami, zanim opuszczę słowację na 10 dni.

32

w1k napisał/a:

drac030, dzięki, wprowadziłem zmiany, zmiana prędkości jest rzeczywiście tylko kosmetyczna. dziś/jutro opublikuję ostatnią wersję z poprawkami, zanim opuszczę słowację na 10 dni.

Nie ma pośpiechu, dzięki.

Popatrzyłem sobie jeszcze tu i tam i nadal mi się wydaje, że coś można osiągnąć mikrooptymalizacjami niekoniecznie nawet polegającymi na zastosowaniu 16-bitowego akumulatora, bo i kod czysto ośmiobitowy można ulepszyć, np.

https://www.atari.org.pl/forum/misc.php?action=pun_attachment&item=13797

Zakładając, że nie ma odwołań z zewnątrz pod $4d60 (a nie widzę, żeby były), reforma da 8 cykli zysku (a ten kawałek kodu jest wywoływany bardzo często).

Co więcej, zawartość akumulatora jest potem (po odgałęzieniu bcc pod $4d66 do rts w $4d76) tracona, więc można zastąpić cmp $1353 przez sec/sbc $1353, a sec i sbc stojące poniżej odgałęzienia zlikwidować całkowicie. To da razem 10 cykli zysku - a cały kawałek od adresu $4d5a do $4d6d ma ich, o ile dobrze liczę, 28.

No, i tak dalej, i tym podobnie, usque ad mortem.

Post's attachments

doom_procedurka.png 9.8 kb, nikt jeszcze nie pobierał tego pliku. 

Tylko zalogowani mogą pobierać załączniki.
KMK
? HEX$(6670358)

33

Altirra ma świetną opcję "Performance Analyzer". Można tam zobaczyć która część kodu zajmuje najwięcej cykli w ramce.

ATW800/2 / Atari V4sa / Lynx I / Mega ST 1 / 7800 / Portfolio / Lynx II / Jaguar / TT030 / Mega STe / 800 XL / 1040 STe / Falcon030 / 65 XE / 520 STm / SM124 / SC1435
SUB/AVGcart / FujiNet / DDD HDD / AT Speed C16 / TF536 / SDrive / PAK68/3 / Lynx Multi Card / LDW Super 2000 / XCA12 / SkunkBoard / CosmosEx / SatanDisk / UltraSatan / USB Floppy Drive Emulator / Eiffel / SIO2PC / Crazy Dots / PAM Net
http://260ste.atari.org

34 Ostatnio edytowany przez w1k (2026-08-30 18:38:42)

benche.. + SPEEDUP_LOG.md (jest napisane po słowacku)

Post's attachments

bench.zip 10.2 kb, liczba pobrań: 2 (od 2026-08-30) 

Tylko zalogowani mogą pobierać załączniki.

35 Ostatnio edytowany przez drac030 (2026-08-31 08:59:10)

w1k napisał/a:

benche.. + SPEEDUP_LOG.md (jest napisane po słowacku)

Nie no, statystyki fajne.

Co nie zmienia faktu, że procedura, która zajmuje połowę czasu CPU (draw_twall_clip wraz z przyległościami) jest, jak napisałem powyżej, pełna nieporadnego kodu, ze zbędnymi rozkazami (jak powyżej, albo np. zamiast STZ nagminnie jest LDA #$00 / STA), z seriami 32-bitowych operacji (move'ów, dodawań, odejmowań) rozbitymi bez sensu na serie rozkazów ośmiobitowych itp.

A potem konkluzja brzmi np., że "brzdou je CPU" - przy takim kodzie to nie jest wcale dziwne.

EDIT: przykład tego, o czym mowa (z pliku renderer.asm)

a) oryginał

.proc calc_nodeptr
        lda zp_nid
        sta m_a
        lda zp_nid+1
        and #$7F
        sta m_a+1
        jsr m_x4                     ; m_prod = nid*28 via shifts (= *32 - *4).
        lda m_prod        ;3
        sta m_ma          ;3
        lda m_prod+1    ;3
        sta m_ma+1      ;3           ; m_ma = nid*4
        asl m_prod        ;5
        rol m_prod+1    ;5           ; nid*8
        asl m_prod        ;5
        rol m_prod+1    ;5           ; nid*16
        asl m_prod        ;5
        rol m_prod+1    ;5           ; nid*32
        sec                    ;2
        lda m_prod        ;3
        sbc m_ma          ;3
        sta m_prod        ;3
        lda m_prod+1    ;3
        sbc m_ma+1      ;3
        sta m_prod+1    ;3           ; nid*28
        clc                      ;2
        lda m_prod        ;3
        adc #<MAP_NODES    ;2           ; MAP_NODES = offset inside the EXT bank; the
        sta zp_nodeptr   ;3           ;   readers go [zp_nodeptr],y (long indirect)
        lda m_prod+1     ;3           ;   with zp_nodeptr+2 = MAP_EXT_BANK, set ONCE
        adc #>MAP_NODES ;2           ;   by init_level -- nothing else writes +2
        sta zp_nodeptr+1 ;3 - suma: 80 cykli CPU, 46 bajtów
        rts
.endp

b) ja bym spróbował tak

.proc calc_nodeptr
        lda zp_nid
        sta m_a
        lda zp_nid+1
        and #$7F
        sta m_a+1
        jsr m_x4
        rep #$20        ;3
        lda m_prod      ;4
        sta m_ma        ;4
        asl             ;2
        asl             ;2
        asl             ;2
        sec             ;2
        sbc m_ma        ;4
        clc             ;2
        adc.w #MAP_NODES ;3 
        sta zp_nodeptr    ;4 
        sep #$20        ;3 - suma: 35 cykli CPU, 20 bajtów
        rts
.endp

PS. to m_x4 zapewne też można przyśpieszyć.

KMK
? HEX$(6670358)

36

drac030, tak, pozwoliłem AI na to spojrzeć i przyznać, że niektóre rzeczy są tam zbędne. w rzeczywistości takie zmiany w kodzie dają około −302 µs/f = +0,18% fps. jutro wydam nową wersję, a potem będę miał 10-dniową przerwę.

37

w1k napisał/a:

drac030, tak, pozwoliłem AI na to spojrzeć i przyznać, że niektóre rzeczy są tam zbędne. w rzeczywistości takie zmiany w kodzie dają około −302 µs/f = +0,18% fps.

No, cóż, pokazałem trzy miejsca, w których sekwencje rozkazów dają się skrócić aż o połowę albo o 1/3. Tylko trzy, chociaż takich miejsc jest multum, gdzie nie spojrzeć, aż się prosi, żeby to zrobić. Myślę, że, zwłaszcza w krytycznych procedurach, dałoby to mierzalny efekt. Szkoda, że nie chcesz spróbować (skłonić do tego AI).

KMK
? HEX$(6670358)

38 Ostatnio edytowany przez w1k (2026-08-31 09:17:30)

Zdecydowanie nie o to chodzi. Próbuję oszukać AI, żeby pomyślała, co piszesz, a konkretnie skopiowała i wkleiła Twoją reakcję. Pracuję nad tym, tak :)

fps 2.94 - 3.12

http://turiecfoto.sk/atari/doom-test/doom.zip

39

może wydzielisz to do osobnych plików i podasz AI z zadaniem optymalizacji, jako oddzielny projekt, albo innemu modelowi AI

*- TeBe/Madteam
3x Atari 130XE, SDX, CPU 65816, 2x VBXE, 2x IDE Plus rev. C

40

tak, robię to dokładnie tak samo. zwracam też szczególną uwagę na same pliki, używam też gemini pro i przesyłam wyniki do rozpatrzenia w opus 5, fable 5.

41 Ostatnio edytowany przez drac030 (2026-08-31 11:07:41)

w1k: wrzuć na github bieżące źródła, zanim wyjedziesz.

PS. Ten kawałek jest przecudny:

00:7408: 18        CLC
00:7409: A5 F8     LDA $F8
00:740B: 69 04     ADC #$04
00:740D: 8D B8 0E  STA $0EB8
00:7410: A5 F9     LDA $F9
00:7412: 69 00     ADC #$00
00:7414: 8D B9 0E  STA $0EB9
00:7417: 4E B9 0E  LSR $0EB9
00:741A: 6E B8 0E  ROR $0EB8
00:741D: 4E B9 0E  LSR $0EB9
00:7420: 6E B8 0E  ROR $0EB8
00:7423: 4E B9 0E  LSR $0EB9
00:7426: 6E B8 0E  ROR $0EB8
00:7429: AD B8 0E  LDA $0EB8
00:742C: 0D B9 0E  ORA $0EB9
00:742F: D0 03     BNE $7434
00:7431: EE B8 0E  INC $0EB8
00:7434: A9 08     LDA #$08
00:7436: 8D B7 0E  STA $0EB7
00:7439: AD A7 0E  LDA $0EA7
00:743C: D0 26     BNE $7464
00:743E: AD A6 0E  LDA $0EA6
00:7441: C9 41     CMP #$41
00:7443: B0 1F     BCS $7464
00:7445: A9 01     LDA #$01
00:7447: 8D B7 0E  STA $0EB7
00:744A: 4E B9 0E  LSR $0EB9
00:744D: 6E B8 0E  ROR $0EB8
00:7450: 4E B9 0E  LSR $0EB9
00:7453: 6E B8 0E  ROR $0EB8
00:7456: 4E B9 0E  LSR $0EB9
00:7459: 6E B8 0E  ROR $0EB8
00:745C: AD B8 0E  LDA $0EB8
00:745F: D0 03     BNE $7464
00:7461: EE B8 0E  INC $0EB8
00:7464: A9 00     LDA #$00
00:7466: 85 EF     STA $EF
00:7468: 85 F0     STA $F0
00:746A: A9 01     LDA #$01
00:746C: 85 F1     STA $F1
00:746E: AD A8 0E  LDA $0EA8
00:7471: 85 F6     STA $F6
00:7473: AD A9 0E  LDA $0EA9
00:7476: 85 F7     STA $F7

Tak poza wszystkim, ten model AI jest chyba przekonany, że zapisanie akumulatora do pamięci przez STA powoduje utratę jego zawartości. Stąd numery typu LDA $1361 / STA $1354 / LDA $1354, albo STA $0EB9 / LSR $0EB9 itp.

Jest też odporny na zwiększanie akumulatora przez INC (zamiast CLC / ADC #$01), zmniejszanie go przez DEC (zamiast SEC / SBC #$01) i przeważnie na zerowanie komórek pamięci przez STZ (prawie wszędzie wali LDA #$00 / STA).

KMK
? HEX$(6670358)

42

a nie możesz tych wytycznych które podał ci drac030 wprowadzić jako skill? Bo to przecież normalne żeby go uczyć tego jak ma pisać. i dokładnie opus czy fable radzi sobie z tym idealnie.

kupię Atari 815 i 820 :)

43 Ostatnio edytowany przez w1k (2026-08-31 13:09:23)

ok, tu: http://turiecfoto.sk/atari/doom-test/doom31-08-2026.zip

github aktualny

F - FPS count

44 Ostatnio edytowany przez drac030 (2026-08-31 13:23:27)

Jeszcze się przyczepię, bo to trochę pokazuje, jak u tego całego Claude'a jest z myśleniem, a tym samym, z jakością kodu. Mamy takie coś:

00:E9EA:    REP #$20
            LDA $D1
            AND #$7FFF
            ASL
            ASL
            CLC
            ADC #$2C74
            STA $84
            SEP #$20
            LDY #$00
            LDA [$84],Y
            STA $E7
            INY
            LDA [$84],Y
            STA $E8

Jak widać, wersja testowa w końcu używa 16-bitowego akumulatora (i robi to dużo częściej niż poprzednia, naliczyłem 47 wystąpień rozkazu rep #$20). I bardzo dobrze. Ale byłoby lepiej, gdyby to było robione z głową:

1) rozkaz AND #$7FFF jest w ogóle niepotrzebny, a zajmuje 3 bajty i 3 cykle
2) dalej mamy przełączenie na 8-bitowy akumulator (SEP #$20), po czym kod radośnie pobiera z pamięci 16-bitowe słowo bajt po bajcie i takoż bajt po bajcie odkłada je do dwóch kolejnych komórek pamięci.

Powinno być tedy:

00:E9EA:    REP #$20
            LDA $D1
            ASL
            ASL
            CLC
            ADC #$2C74
            STA $84
            LDA [$84]
            STA $E7
            SEP #$20

Oszczędza się 10 bajtów i 15 cykli, głównie dzięki przestawieniu jednego rozkazu w inne miejsce.

Dalej idzie wywołanie podprogramu, który: a) kopiuje owo $E7-$E8 do $EF-$F0, oczywiście znowu bajt po bajcie, robiąc jednocześnie mnożenie przez 8 przez trzykrotne przesunięcie w lewo, oczywiście też bajt po bajcie (tym razem przynajmniej pierwsze przesunięcie robi razem z kopiowaniem, brawo; ale resztę już na pamięci, niebrawo). Chociaż można to zrobić tak:

00:E9EA:    REP #$20
            LDA $D1
            ASL
            ASL
            CLC
            ADC #$2C74
            STA $84
            LDA [$84]
            STA $E7
            ASL
            ASL
            ASL
            STA $EF           
            SEP #$20

W następnym kroku do obliczonej wartości trzeba dodać 256 i zapisać ją pod $BF-$C0. Kod:

            CLC
            LDA $EF
            ADC #$00
            STA $BF
            LDA $F0
            ADC #$01
            STA $C0

Chociaż wystarczyłoby tak:

00:E9EA:    REP #$20
            LDA $D1
            ASL
            ASL
            CLC
            ADC #$2C74
            STA $84
            LDA [$84]
            STA $E7
            ASL
            ASL
            ASL
            STA $EF
            CLC
            ADC #$0100
            STA $BF          
            SEP #$20

Oryginał: 36 rozkazów (w tym dwie pary JSR/RTS), 67 bajtów, 130 cykli CPU.

Modyfikacja: 17 rozkazów, 29 bajtów, 53 cykle CPU. Przy czym STA $E7 może być w ogóle niepotrzebne, jeśli tak, to 16 rozkazów, 27 bajtów, 49 cykli.

KMK
? HEX$(6670358)

45 Ostatnio edytowany przez w1k (2026-08-31 14:47:48)

wielkie dzięki

http://turiecfoto.sk/atari/doom-test/doom31-8-2026b.zip
http://turiecfoto.sk/atari/doom-test/doom31-8-2026c.zip

46 Ostatnio edytowany przez drac030 (2026-08-31 21:55:31)

Ostatnia dzisiejsza wersja ma błąd. Krok po kroku:

1) ładujemy całość
2) przechodzimy do menu
3) wybieramy New game
4) wybieramy którykolwiek z epizodów, np. nr 3, wciskamy Return
5) robimy parę kroków
6) wciskamy Esc, żeby wrócić do menu
7) wybieramy New game - już w tym momencie panel na dole zamienia się w kaszkę
8) wybieramy inny epizod, np. nr 2, wciskamy Return (panel się odtwarza)
9) robimy parę kroków
10) wciskamy Esc, żeby wrócić do menu
11) wybieramy New game (panel = kaszka)
12) wybieramy epizod nr 1, wciskamy Return - w tym mniej więcej momencie następuje zwis, program przestaje reagować na klawiaturę i joystick

https://www.atari.org.pl/forum/misc.php?action=pun_attachment&amp;item=13802

Post's attachments

doom_zwis.png 39.37 kb, nikt jeszcze nie pobierał tego pliku. 

Tylko zalogowani mogą pobierać załączniki.
KMK
? HEX$(6670358)

47 Ostatnio edytowany przez w1k (2026-08-31 22:53:04)

Już czekam na samolot ..

48

pamiętaj żeby przy odprawie zażartować że masz bombę w plecaku... wtedy widzimy się wkrótce

*- TeBe/Madteam
3x Atari 130XE, SDX, CPU 65816, 2x VBXE, 2x IDE Plus rev. C

49 Ostatnio edytowany przez Jacques (2026-09-01 10:32:27)

Przed żartem może wklepać IDDQD i go nie ruszą ;-)
Swoją drogą to kody mogłyby działać, choćby te podstawowe:  IDDQD oraz IDKFA