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.
    • 35:
       
      CommentAuthorplyr0
    • CommentTime30 Oct 2018
     
    Bocianu, czy ten pierwszy rozdział jest jeszcze dostępny? Bo jak pobieram załącznik to ma 0 bajtów.
    • 36: CommentAuthorPecet
    • CommentTime30 Oct 2018
     
    U mnie jest tak samo, na szczescie mialem jeszcze na dysku.
    • 37:
       
      CommentAuthorbocianu
    • CommentTime30 Oct 2018 zmieniony
     
    no coś nie tak jest z forum - obcięło załącznik :/
    spróbuje dodać jeszcze raz:
    • 38:
       
      CommentAuthorIRATA4
    • CommentTime30 Oct 2018
     
    @ Pecet
    Fajnie , widzę że chcesz coś wnieść , trzymam kciuki .
    Pobaw się edytorem znaków ...
    ->link<-

    Przydatna rzecz ;-).
    • 39: CommentAuthorPecet
    • CommentTime6 Nov 2018 zmieniony
     
    Mad Pascal problem z kodem w asm.

    Skopiowałem źródło starfield z tej strony: ->link<-

    dostałem błąd:

    stx @sp
    asm_test.a65 (717) ERROR: Undeclared label @SP (BANK=0)
    ldx @sp
    asm_test.a65 (855) ERROR: Undeclared label @SP (BANK=0)

    skopiowałem procedurkę DLI z tej strony ->link<-

    {
    Program : 3D Starfield by Thomas Havemeister (converted to Mad Pascal)
    Original date : 07 Mar 2002
    Source : ->link<-
    }
    uses crt, graph;

    procedure StarField;
    begin
    asm {
    PHA
    TXA
    PHA
    LDX $D1
    DEX
    LDA #0400,X
    STA $D40A ; WSYNC
    CPX #$00
    BNE $0612
    LDX #$04
    STA $D018 ; BGCLR
    STX $D1
    PLA
    TAX
    PLA
    RTI
    };
    end;

    begin
    InitGraph(0); CursorOff;
    gotoxy(4, 5); writeln('3D Starfield by Thomas Havemeister');
    gotoxy(4, 6); writeln('Original date: 07 Mar 2002');
    gotoxy(4, 7); writeln('Converted to Mad Pascal');
    StarField;
    end.


    na szybko wkleiłem to w pierwszy program i dostaję błąd:

    LDA #0400,X
    smallTest.a65 (722) ERROR: Extra characters on line

    Generalnie asma to ogarniam na tyle, że gotową procedurę mogę przerobić pod swoje potrzeby, ale te błędy mnie przerastają.

    Generalnie w obu przypadkach tworzone są pliki lst i a65, brak jest natomiast pliku xex.
    • 40: CommentAuthorVidol
    • CommentTime6 Nov 2018
     
    lda #0400,x

    powinno byc

    lda $0400,x

    # - oznacza liczbe 0-255
    $ - oznacza adres w pamieci

    Blad w listingu zwlaszcza ze na stronie jest:
    Load the accumulator with the X offset into the color table stored in memory location 1024 ($0400)

    CPX #$00
    BNE $0612
    LDX #$04
    STA $D018 ; BGCLR

    to bne $612 tez nie jest ok.Lepiej zrobic to tak:
    CPX #$00
    BNE L1
    LDX #$04
    L1 STA $D018 ; BGCLR
    • 41: CommentAuthorPecet
    • CommentTime7 Nov 2018
     
    Dzięki. A ja szukałem jakiś ekstra spacji i innych tabulacji:)
    • 42: CommentAuthorPecet
    • CommentTime4 dni temu
     
    Mam jeszcze takie pytanie. Prawdopodobnie proste, ale zasadnicze.
    Załóżmy, że początek pamięci ekranu to $600. Tworzę jakąś zmienną w mad pascalu. Pytanie, jak mogę sprawdzić (bądź ustawić) adres takiej zmiennej? I jaką mam pewność, że ta zmienna nie zacznie mi "mazać" po pamięci ekranu?
    Wiem, że np. jak się tworzyło pamięć dla duszków to obniżało się ramtop, atari myślało, że ma mniej pamięci dostępnej i duszki były bezpieczne.
    Generalnie w jaki sposób przydzielana jest pamięć pod zmienne w mad pascalu, czy można mieć na ten proces wpływ.
    • 43:
       
      CommentAuthorbocianu
    • CommentTime3 dni temu zmieniony
     
    @Pecet

    Hej! Domyślnie zmienne globalne ustawiane są na końcu kompilowanego kodu, i przy kompilacji masz informację gdzie znajduje się blok danych:

    Przykład:
    Mad Pascal Compiler version 1.5.8 [2018/10/27] for 6502
    Compiling hoppe.pas
    hoppe.pas (11) Note: Local const 'FRAME0' not used
    195 lines compiled, 1.03 sec, 7235 tokens, 713 idents, 208 blocks, 4 types
    1 note(s) issued
    ZPFREE: $0000..$007F
    ZPFREE: $00D8..$00FF
    SYSTEM: $2095..$2147
    CRT: $2148..$216C
    B_PMG: $216D..$224B
    B_DL: $224C..$2312
    JOYSTICK: $2313..$2316
    CODE: $2000..$281E
    DATA: $281F..$2859
    Writing listing file...
    Writing object file...
    8568 lines of source assembled in 5 pass
    2141 bytes written to the object file


    więc nasze zmienne lokowane są w obszarze:
    DATA: $281F..$2859

    Ale nic nie stoi na przeszkodzie, aby przy deklaracji zmiennej wskazać w którym miejscu ma się ona znajdować. Służy do tego dyrektywa absolute:
    var zmienna: byte absolute $6000;


    Możemy nawet deklarować całe tablice wskazując ich adres:
    pmg: array [0..0] of byte absolute $8000;


    i teraz zapisując wartość:
    pmg[5]:=12;


    wpisujemy wartość dwanaście pod komórkę $8005.

    Natomiast jeżeli chcemy znać dokładny adres zadeklarowanej wcześniej zmiennej, możemy użyć operatora @, który zwraca wskaźnik do dowolnej zmiennej.

    przykład:

    program test;
    uses crt;
    var
    i: byte;
    begin
    writeln('adres zmiennej i: ', word(@i));
    Readkey;
    end.


    Rzutowanie word(@i) jest potrzebne, gdyż procedura writeln nie potrafi drukować wartości wskaźników i musimy rzutować go na liczbę 16 bitową.

    Mam nadzieję, że pomogłem ;)
    • 44: CommentAuthorPecet
    • CommentTime3 dni temu
     
    Dzięki, teraz wiem już wszystko;)
    • 45: CommentAuthortebe
    • CommentTime3 dni temu
     
    tak na szybko, bez przerwań, tylko unit ATARI musiałem uzupełnić o kilka rejestrów

    uses crt, atari;

    var
    i: byte;
    tab, add: array [0..255] of byte;

    begin

    for i:=0 to 255 do begin
    tab[i]:=random(0);
    add[i]:=random(0) and 3 + 1;
    end;

    sizep0:=0;
    grafp0:=1;

    repeat

    i:=vcount;

    hposp0:=tab[i];

    inc(tab[i], add[i]);

    wsync:=0;

    until keypressed;

    end.