atarionline.pl Początki w c. Adres ekranu i podmiana. - Forum Atarum

Jeśli chcesz wziąć udział w dyskusjach na forum - zaloguj się. Jeżeli nie masz loginu - poproś o członkostwo.

  • :
  • :

Vanilla 1.1.4 jest produktem Lussumo. Więcej informacji: Dokumentacja, Forum.

    • 1: CommentAuthorPecet
    • CommentTime22 Jul 2018
     
    Cześć,
    zacząłem się uczyć c. Udało mi się narysować takie kolorowe bary od lewej do prawej w gr.15. Tylko, że zanim cały ekran sie wypełni mija trochę czasu. Pomysł jest taki, żeby podmienić adres pamięci ekranu, pamięć właściwą wypełnić czym trzeba i jak będzie gotowe, to podmienić adres ekranu z powrotem i wyświetlić.

    #include<atari.h>
    #include<stdio.h>
    #include<peekpoke.h>

    int main(void) {
    unsigned char loop;
    unsigned char loop2;
    unsigned char *video_ptr;
    unsigned *dli_ptr;
    unsigned row;

    _graphics(15);
    video_ptr=(unsigned char*)(PEEKW( PEEKW(560)+4));
    dli_ptr=(unsigned*)(PEEKW(560));
    POKEW(dli_ptr[4],0x3000);

    for (loop2=0;loop2<160;loop2+=1) {
    row = loop2*40;
    for(loop=0;loop<40;loop++)
    video_ptr[row+loop]=108;
    }

    POKEW(dli_ptr[4],video_ptr);
    //printf(", %d",video_ptr[0]);
    return 0;
    }


    I teraz tak, w komórkach 560 i 561 mamy mlodszy i starszy bajt adresu Display listy. Display Lista jest tak skonstruowana, że pierwsze 3 linie (czyli indeksy 0, 1, 2) to puste linie, potem mamy load memory scan (indeks 3) a następne dwa bajty (czyli indeks 4 i 5) to... no właśnie pierwsze pytanie co tam jest? Bo według mnie jest to wskażnik do adresu pamięci ekranu. A nie sam adres. Zgadza się?
    Co próbuję zrobić dalej, to wpisać pod ten wskaźnik nową wartość (0x3000), potem wypełniam "stary" ekran i na końcu poprzez POKEW zamieniam ponownie adresy.
    Oczywiście to nie dziala. Pomijam na razie co się znajduje w pamięci pod adresem 0x3000 (pewnie jakieś smieci). Chodzi o to, że nadal widać jak ekran się rysuje.
    Naprowadźcie mnie proszę, gdzie robię błąd. Bo już nie ogarniam.
    • 2: CommentAuthorantrykot
    • CommentTime22 Jul 2018 zmieniony
     
    Po pierwsze, display list w gr.15 ma w dwóch miejscach instrukcje ładujące adres danych do wyświetlenia. Jak zmienisz tylko w jednym miejscu, to zniknie tylko górna część obrazu.

    A po drugie, dli_ptr jest typu unsigned* więc dli_ptr[4] to nie jest piąty bajt display listy, ale bajty dziewiąty i dziesiąty. Zmień typ dli_ptr na unsigned char*, a poke rób tak: POKEW(dli_ptr + 4, 0x3000);
    • 3:
       
      CommentAuthorbocianu
    • CommentTime22 Jul 2018
     
    Na pierwszy rzut oka to dli_ptr powinien być wskaźnikiem na typ Word.
    Po drugie zamieniłbym mnożenie *40 na cykliczne dodawanie tej wartości do row. Powinno zauważalnie przyspieszyć.

    Ekran też da się wyłączyć prościej za pomocą rejestru sdmctl. Nie trzeba się bawić w modyfikacje dl ;)
    • 4: CommentAuthorPecet
    • CommentTime22 Jul 2018
     
    Ok, dzięki panowie. Zrobiłem tak i śmiga (zgodnie z tym co napisał antrykot, tylko górna połowa ekranu jest zamazana śmieciami spod adresu 0x3000, ale chodzi o sprawdzenie samego mechanizmu).
    #include<atari.h>
    #include<stdio.h>
    #include<peekpoke.h>

    int main(void) {
    unsigned row;
    unsigned char loop;
    unsigned char loop2;
    unsigned char *video_ptr;
    unsigned dl_addr;

    _graphics(15);
    video_ptr=(unsigned char*)(PEEKW( PEEKW(560)+4));
    //POKE(559,0); //turn ANTIC off, screen goes black
    dl_addr=(unsigned)(PEEKW(560));
    POKEW(dl_addr+4,0x3000);

    for (loop2=0;loop2<160;loop2++) {
    row = loop2*40;
    for(loop=0;loop<40;loop++){
    video_ptr[row+loop]=108;
    }
    }
    //POKE(559,34); //turn ANTIC ON, and display graphics
    POKEW(dl_addr+4,(unsigned)video_ptr);
    return 0;
    }


    porada bociana oczywiście też bardzo dobra (dwie zakomentowane linie z POKE, rozwiązuje to sprawę dla całego ekranu).
    Pytanie, gdzie mogę poczytać o podzielonej Display List dla gr.15.

    Druga sprawa, to linię:
    row = loop2*40;

    mogę zastąpić przez:
    row=loop2<<5;
    row+=loop2<<3;

    ale tak:
    row= loop2<<5 + loop2<<3;

    już nie zadziała - wartości robią zbyt duże. Dlaczego?
    • 5:
       
      CommentAuthorbocianu
    • CommentTime22 Jul 2018 zmieniony
     
    To że druga wersja nie działa, to może być wina kolejności działan w kompilatorze. Spróbuj dać nawiasy.

    A ja bym dał tak jak mówiłem:

    row += 40;

    To najszybsza opcja.

    ->link<-

    A tutaj znajdziesz informacje dlaczego liniowy obszar pamięci obrazy nie może mieć więcej niż 4kb (w opisie rozkazu LMS)
    • 6: CommentAuthorPecet
    • CommentTime22 Jul 2018
     
    Dzięki.
    Ogólnie rozjaśniło mi się parę rzeczy, szczególnie jeśli chodzi o wskaźniki.
  1.  

    bocianu:

    To że druga wersja nie działa, to może być wina kolejności działan w kompilatorze.

    A dokładniej to w języku, nie w kompilatorze :)

    row= loop2<<5 + loop2<<3;

    oznacza dokładnie to samo co:
    row= loop2<<(5 + loop2)<<3;


    + ma w C większy priorytet niż <<.
    O małą pipkę, ale jednak większy :)
    • 8:
       
      CommentAuthorbocianu
    • CommentTime22 Jul 2018
     
    @inż: masz rację - to cecha języka, z której wynika działanie kompilatora ;) poleciałem skrótem myślowym.

    Co ciekawe, już w Pascalu operacje przesunięć bitowych mają wyższy priorytet niż dodawanie. I też o pipkę.
    • 9: CommentAuthorPecet
    • CommentTime30 Jul 2018
     
    oki, mam kolejne pytanko.

    mam 3 pliki

    //plik: myLib.h
    #ifndef __MY_LIB_H
    #define __MY_LIB_H

    unsigned char var;
    unsigned char setVar(unsigned char v);
    #endif


    //plik: myLib.c
    #include "myLib.h"

    unsigned char setVar(unsigned char v) {
    var=v;
    return var;
    }


    //plik: main.c
    #include "myLib.h"
    #include <stdio.h>

    int main(void) {
    printf("value: %d",setVar(3));
    return 0;
    }


    i do tego mam batcha
    cl65 -t atari -c myLib.c
    cl65 -t atari -c main.c
    cl65 -O -t atari -o main.xex myLib.o main.o
    pause


    działa, ale dostaję taki komunikat:
    ld65.exe: Warning: Duplicate external identifier: `_var'


    pytanie, jak pozbyć się tego ostrzeżenia.
    • 10: CommentAuthorbob_er
    • CommentTime30 Jul 2018
     
    W pliku .h nie powinieneś instancjonować obiektów.
    Zatem z pliku myLib.h wywal linię "unsigned char var;" i dodaj ją do pliku .C.
    • 11: CommentAuthorbob_er
    • CommentTime30 Jul 2018
     
    Jeszcze dwie uwagi ogólne:
    1. Zgodnie ze standardem, guardy (#ifdefy w H) nie powinny się zaczynać od '_'.
    2. Na wypadek, gdybyś kiedyś kod chciał przenieść na inny kompilator/platformę, wygodnie jest zrobić sobie serię #typedefów definiujących podstawowe typy, np. uint8_t, uint16_t. Zwłaszcza dla 'int' który jest zdefiniowany bardzo ogólnie.
    • 12: CommentAuthorPecet
    • CommentTime30 Jul 2018
     
    dzięki za porady.
    poszedłem tym tropem (zmienne w nagłówkach) i przypomniałem sobie o extern.

    wygląda na to, że dodanie extern w nagłowku
    extern unsigned char var;


    oraz dodanie linii w pliku myLib.c
    unsigned char var;


    rozwiązuje problem.
    • 13: CommentAuthorilmenit
    • CommentTime1 Aug 2018
     
    Kiedyś napisałem krótki kurs pisania w C na Atari, może będzie przydatny:
    ->link<-
    • 14: CommentAuthorPecet
    • CommentTime16 Aug 2018
     
    Mam kolejny problem. Próbuje użyć TGI. Kod wygląda tak:
    #include <peekpoke.h>
    #include <stdio.h>
    #include <atari.h>
    #include <tgi.h>


    extern char atrx15;
    char c[30];

    int main(void) {
    unsigned char errCode;
    _graphics(15);
    tgi_install(&atrx15);
    errCode = tgi_geterror();
    printf("error code: %d, message: %s \n",errCode, tgi_geterrormsg(errCode));
    gets(c);
    tgi_init();
    errCode = tgi_geterror();
    printf("error code: %d, message: %s \n",errCode, tgi_geterrormsg(errCode));
    gets(c);
    tgi_setcolor(COLOR_BLACK);
    tgi_clear();
    tgi_outtext("Ala spirala");
    tgi_line (1, 1, 20, 20);
    printf("%u",tgi_getmaxx());
    return 0;
    }


    driver atrx15.tgi znajduje się w tym samym katalogu co źródło.

    kompilowane/linkowane jest tak:
    co65 --code-label _atrx15 atrx15.tgi
    ca65 atrx15.s
    cl65 -C atarixl.cfg -O -t atarixl tgi_test.c atrx15.s -o tgi_test.xex
    pause


    I teraz tak, z tego co widzę ataryna włącza gr.15, wypisuje brak błędów po tgi_install, potem wraca do gr.0 (?), brak błędów po tgi_init i potem czyści ekran i koniec.

    atarixl.cfg ma zmienioną jedną linie tzn.
    FEATURES {
    STARTADDRESS: default = $3000;
    }


    Jakieś pomysły? Fakt, że mam przeskok z gr.15 do gr.0 wg. mnie wskazuje, że coś źle skonfigurowałem.
    • 15: CommentAuthorbob_er
    • CommentTime16 Aug 2018
     
    Się nie znam na tgi nie wiem również jak dokładnie działa gets(), ale daj może gdzieś tam jakąś pętlę nieskonczoną.
    Może program po prostu szybko się kończy?
    • 16: CommentAuthorPecet
    • CommentTime17 Aug 2018
     
    nie, to nie to.
    Chyba szybciej zrobie swoj wlasny algorytm na linie, niz rozgryze o co jest kaman. Tylko pewnie i tak predzej, czy pozniej ten problem ugryzie mnie ponownie w tylek :\
    • 17:
       
      CommentAuthorbocianu
    • CommentTime17 Aug 2018
     
    A jesteś bardzo zafiksowany na C? Bo jak koniecznie chcesz pisać na Atari w czymś innym niż assembler, to Mad-Pascal nadaje się lepiej. Wiem o czym mówię, bo pisałem i w C65 i w assemblerze :D

    Pozdrawiam ;)
    • 18: CommentAuthorPecet
    • CommentTime17 Aug 2018
     
    a mozesz tak w skrocie powiedziec w czym mad-pascal jest lepszy od cc65? Ja generalnie bardzo lubie skladnie c.
    No i nie ukrywam, ze drazni mnie ten moj nierozwiazany problem z TGI w c65. Pewnie jakas drobna pierdola, ktorej nie widze:)
    • 19:
       
      CommentAuthormgr_inz_rafal
    • CommentTime17 Aug 2018 zmieniony
     
    Pa na to :)

    Najpierw install(), potem init() [który przywraca tryb 0], potem _graphics() i dopiero potem lecimy z koksem :)



    #include "peekpoke.h"
    #include "stdio.h"
    #include "atari.h"
    #include "tgi.h"


    extern char atrx15;
    char c[30];

    int main(void) {
    unsigned char errCode;
    tgi_install(&atrx15);
    tgi_init();
    _graphics(15);
    errCode = tgi_geterror();
    printf("error code: %d, message: %s \n",errCode, tgi_geterrormsg(errCode));
    gets(c);
    tgi_clear();
    tgi_gotoxy(40,40);
    tgi_outtext("Ala spirala");
    tgi_line (1, 1, 20, 20);
    printf("tgi_getmax()=%u",tgi_getmaxx());
    for(;;);
    return 0;
    }
    • 20: CommentAuthorPecet
    • CommentTime17 Aug 2018
     
    ja pier..., wiedzialem, ze to jakas pierdola.

    Dziekuje bardzo:)
    powiedz mi jeszcze, prosze, skad wiedziales, ze trzeba to zrobic wlasnie w takiej kolejnosci? Moze mi to oszczedzic troche siwych wlosow w przyszlosci:)
  2.  
    Educated guess :)
    • 22:
       
      CommentAuthorbocianu
    • CommentTime17 Aug 2018 zmieniony
     
    "a mozesz tak w skrocie powiedziec w czym mad-pascal jest lepszy od cc65?"

    - ma już sporo bibliotek sprofilowanych pod atari
    - potrafi korzystać z pamieci rozszezonej, VBXE, Sparta dos
    - jest juz sporo przykładów i kilka gier z udostepnionymi źródłami
    - ma więcej typów zmiennych (w tym 32 bitowy cardinal i float)
    - kod wynikowy jest lepiej zoptymalizowany (szybszy)
    - nie trzeba grzebać w konfiguracji linkera jak chcesz dołączać zewnętrzne zasoby
    - umożliwia łatwe mieszanie go z assemblerem (inline)
    - i przede wszystkim jest wciąż rozwijany.

    Ja tez wolę składnię C, do szału doprowadzaja mnie pascalowe przypisania ":=", ale powyższe argumenty powodują, że jednak lepiej i szybciej mi się w nim pisze.
    • 23: CommentAuthormav
    • CommentTime17 Aug 2018
     
    Istnieje jakaś paczka, którą po prostu wypakuję i będę mógł używać
    i po prostu jakieś wprowadzenie, które da się zrozumieć? :)
    • 24: CommentAuthorPecet
    • CommentTime17 Aug 2018
     
    dziekuje panowie za odpowiedzi:)
    zerkne przy okazji na pascala, moze rzeczywiscie to bedzie lepszy wybor.
    • 25:
       
      CommentAuthorbocianu
    • CommentTime17 Aug 2018
     
    Nie istnieje taka paczka z Mad-Pascale, ale może sie kiedyś pokuszę o spreparowanie ;)

    Tymczasem zrobiłem takie małe wprowadzenie:
  3.  
    Rozdział 1?
    • 27: CommentAuthorPecet
    • CommentTime17 Aug 2018
     
    o, swietny poradnik, nawet jezeli nie bede pisal w mad pascalu, to skorzystam ze wskazowek tworzenia plikow bat. Edytor tez zobacze, moze bedzie wygodniejszy niz notepad++.
    • 28:
       
      CommentAuthorbocianu
    • CommentTime17 Aug 2018
     
    @mgr. tak, zwykle numerację zaczyna się od 1 :D
    • 29: CommentAuthorPecet
    • CommentTime17 Aug 2018
     
    to pewnie bylo pytanie o to, czy poradnik bedzie kontynuowany:)
  4.  

    bocianu:

    tak, zwykle numerację zaczyna się od 1


    Chyba w Pascalu :>
    • 31:
       
      CommentAuthorbocianu
    • CommentTime17 Aug 2018
     
    @mgr: no dobra. Wygrałeś :D
    @pecet: tak, mam już kolejne 4 rozdziały i ambitny plan napisania następnych.
  5.  
    Cool!
    Zamawiam egzemplarz :)
  6.  
    A tak na marginesie... Pecet, mam nadzieję, że pociągniesz temat, bo "Ala spirala" świetnie nadaje się na tytuł oryginalnej gry :)
    • 34: CommentAuthorPecet
    • CommentTime17 Aug 2018
     
    Mówisz, że to dobry tytuł? No w sumie, można z tego zrobić jakiegoś klona Giany;)
    Generalnie jeśli chodzi o Atari, to mam traumę z dzieciństwa. Nic nie ujmując polskim twórcom gier z przełomu lat 80 i 90, to jednak sporo tytułów było dość miernych jeśli chodzi o kolorystykę. Wiecie, często w zasadzie 1 kolor w 4 odcieniach (albo coś w tym stylu) w głownym polu gry, pod tym przerwanie i jakieś pole z energią, przedmiotami itd. już z zupełnie inna paletą.
    W skrócie brakuje mi kolorowych gier na atarynę. Więc na początek zrobiłem taki mockup.
    No, a potem to zacząłem uczyć się programowania:) Ale jak widać jeszcze długa droga przede mną. Na razie myślę o czymś prostszym, jakiś tunel pseudo 3d animowany przez rotację palety, do tego powiększające się sprity, które trzeba by omijać. Taki endless runner tylko w czyde.