atarionline.pl MAD-Pascal - Początki - 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: CommentAuthortebe
    • CommentTime12 Nov 2019
     
    możesz stworzyć ekran w G2F (Graph2Font), figury białe/czarne umieścić na polu białym/czarnym aby wszystkie kombinacje uwzględnić

    wybrać odpowiednią kompresję znaków Options -> JGP+ > Charset 2-3-4-5-6-7-8

    i zapisać jako plik PAS (Save As)
    • 2: CommentAuthorzbyti
    • CommentTime12 Nov 2019 zmieniony
     
    @tebe dzięki za rekomendację, dość często na tym forum przewijały się wzmianki o tym narzędziu i wydaje się, że prędzej czy później będę musiał go użyć ;)

    Nie sądzę, że zabraknie mi pamięci, zważywszy, że za całą grafikę robi procedura rysująca szachownicę i 12 krótkich stringów, spakowanych tym pakerem co napisałem przy okazji zabawy z QR codami. Nie mam na ten moment skilla by napisać już za pierwszym podejściem jakiś wybombisty engine i walczyć o każdy bit pamięci :D

    Grafika zerżnięta z Colossus 3, tylko pionka i wieżę narysowałem samodzielnie.

    Packer info:
    6-bit word; dicFirstChar = 40; offset = packedString[1]
    chessman matrix: 24x19

    chessmanPawnW : string = '@((((((((((((((((((((()H((+X((+X(()H((+X((/`((/`((+X(()H(()H((+X((+X((Gf((Gf(';
    chessmanPawnB : string = '@((((((((((((((((()H((*8((,0((,0((*8((,0((0,((0,((,0((*8((*8((,0((D6((H)((H)(';
    chessmanRookW : string = '@(((((((((((((((((aO((aO((aO((gg((Gf((7d((7d((7d((7d((7d((7d((Gf((Gf()ggH)ggH';
    chessmanRookB : string = '@(((((((((((()c_H)2<H)2<H)6DH)H)H(X+((8*((8*((8*((8*((8*((X+((H)(+H)X*((8*((8';
    chessmanKnightB : string = '@(((((((((,H((38((10((8,((L2((H-()(-(*(-(*:-(*L-()0-((`,H(8*H(8*H(H*8)((8)((8';
    chessmanKnightW : string = '@(((((((((((((,H((.X((7`((C\((Gb((gb()gb()Ub()Cb((_b((/c((7e((7e((GeH(ggH(ggH';
    chessmanBishopW : string = '@(((((((((+X((,0((0,((1L((9J((II())HH)6DH))HH(II((9J((9J((0,((1L(+`/X,1L01J9L';
    chessmanBishopB : string = '@(((((((((((((+X((/`((.@((6D((FF((fG((YK((fG((FF((6D((6D((/`((.@((/`(+^CX.EV@';
    chessmanQueenW : string = '@(((((((((0,(*<28-J9P0\3,-<2P-::P,II0,II0,((0,((0,((0,gg0*((8*Gf8)((H)7dH(H)(';
    chessmanQueenB : string = '@(((((((((((((0,(*D68/0,`*P-8*T58+FFX+FFX+ggX+ggX+ggX+((X)ggH)H)H(gg((X+((Gf(';
    chessmanKingW : string = '@((((((((()H(()H(()H((/`((/`()IIH+YKX/eW`/d7`/We`+?bX)WeH)ggH(H)((gg((8*((Gf(';
    chessmanKingB : string = '@((((()H((*8((*8((.@((0,()P-H*::8,6D00*8,0+X,08*,,P-0*8*8*((8)GfH)((H(We((H)(';


    Mój stół rysuje się na oko 2x wolniej od stołu CC 3.0 ale akceptowalne szybko, z resztą na partię jest to jednorazowa czynność a po za tym można uznać to za efekt układania bierek na stole ;)

    Także do póki życie mnie nie zmusi kontynuuję dalej na grafice.

    Jak dojrzeję podmienię GUI.

    Dla porównani zamieszczam wygląd mojego stołu i CC 3.0 oraz chessboard.xex.
    • 3: CommentAuthorzbyti
    • CommentTime12 Nov 2019 zmieniony
     
    OK. Myślę, że jak na MAD-Pascal - Początki to już dość wpisów.

    Następny post będzie już w dedykowanym wątku :)

    Tak nawiasem, nie wiedziałem, że z gedit taki fajny edytor graficzny :D Wykonałem w nim wszystkie powyższe figury.
    • 4: CommentAuthorzbyti
    • CommentTime13 Nov 2019 zmieniony
     
    A... No i jeszcze kod samego renderowania stołu. Zamieszczam jako podsumowanie wysiłków ;)

    110 ticks i pomimo prób nie udało mi nic więcej z tego kodu wycisnąć pod względem prędkości.

    program chessboard;

    //---------------------- LIBRARES ----------------------------

    uses crt, fastgraph;

    //---------------------- GLOBAL DATA -------------------------

    const
    chessmanPawnS = '@((((((((((((((((((((()H((+X((+X(()H((+X((/`((/`((+X(()H(()H((+X((+X((Gf((Gf(';
    chessmanPawnE = '@((((((((((((((((()H((*8((,0((,0((*8((,0((0,((0,((,0((*8((*8((,0((D6((H)((H)(';
    chessmanRookS = '@(((((((((((((((((aO((aO((aO((gg((Gf((7d((7d((7d((7d((7d((7d((Gf((Gf()ggH)ggH';
    chessmanRookE = '@(((((((((((()c_H)2<H)2<H)6DH)H)H(X+((8*((8*((8*((8*((8*((X+((H)(+H)X*((8*((8';
    chessmanKnightS = '@(((((((((((((,H((.X((7`((C\((Gb((gb()gb()Ub()Cb((_b((/c((7e((7e((GeH(ggH(ggH';
    chessmanKnightE = '@(((((((((,H((38((10((8,((L2((H-()(-(*(-(*:-(*L-()0-((`,H(8*H(8*H(H*8)((8)((8';
    chessmanBishopS = '@(((((((((((((+X((/`((.@((6D((FF((fG((YK((fG((FF((6D((6D((/`((.@((/`(+^CX.EV@';
    chessmanBishopE = '@(((((((((+X((,0((0,((1L((9J((II())HH)6DH))HH(II((9J((9J((0,((1L(+`/X,1L01J9L';
    chessmanQueenS = '@(((((((((((((0,(*D68/0,`*P-8*T58+FFX+FFX+ggX+ggX+ggX+((X)ggH)H)H(gg((X+((Gf(';
    chessmanQueenE = '@(((((((((0,(*<28-J9P0\3,-<2P-::P,II0,II0,((0,((0,((0,gg0*((8*Gf8)((H)7dH(H)(';
    chessmanKingS = '@((((((((()H(()H(()H((/`((/`()IIH+YKX/eW`/d7`/We`+?bX)WeH)ggH(H)((gg((8*((Gf(';
    chessmanKingE = '@((((()H((*8((*8((.@((0,()P-H*::8,6D00*8,0+X,08*,,P-0*8*8*((8)GfH)((H(We((H)(';

    //---------------------- GLOBAL VARIABLES --------------------

    var
    bmpAdr : word;
    color : byte;

    //---------------------- PROCEDURES --------------------------

    procedure renderChessman(chessman: string; x, y, color: byte);
    var i0b, i1b : byte;
    x1b, loopEnd : byte;
    offset, error : byte;
    chessmanBlock : byte = %00000000;
    dicFirstChar : byte = 40;
    begin
    x1b := x;
    loopEnd := ord(chessman[0]);
    offset := ord(chessman[1]) - dicFirstChar;
    SetColor(color);
    for i0b := 2 to loopEnd do begin
    chessmanBlock := ord(chessman[i0b]) - dicFirstChar;
    for i1b := 1 to 6 do begin
    if (chessmanBlock and %100000 <> 0) then PutPixel(x1b,y);
    chessmanBlock := chessmanBlock shl 1;
    x1b := x1b + 1;
    if (x1b = offset + x) then begin
    x1b := x;
    y := y + 1;
    end;
    end;
    end;
    end;

    {* chessboard - square 24x19 *}
    procedure drawBoard;
    var i1b, i2b, i3b : byte;
    color, modLine : byte;
    x, y : word;
    begin
    modLine := 0;
    y := 0;
    for i3b := 1 to 8 do begin
    for i2b := 1 to 19 do begin
    x := 0;
    for i1b := 1 to 8 do begin
    color := 0;
    if (i1b and %1 <> modLine) then color := $ff;
    dpoke(bmpAdr + y + x, color);
    dpoke(bmpAdr + y + x + 1, color);
    dpoke(bmpAdr + y + x + 2, color);
    x := x + 3;
    end;
    y := y + 40;
    end;
    if (i3b and %1 = 0) then modLine := 0
    else modLine := 1;
    end;
    rectangle(0, 0, 192, 152);
    end;

    {* pieces matrix 24x19 *}
    procedure drawPieces;
    var x1w : word;
    i1b : byte;
    begin
    x1w := 0;
    for i1b := 0 to 7 do begin
    if (i1b and %1 = 0) then begin
    renderChessman(chessmanPawnE, x1w, 19, 1);
    renderChessman(chessmanPawnE, x1w, 114, 0);
    end else begin
    renderChessman(chessmanPawnS, x1w, 19, 0);
    renderChessman(chessmanPawnS, x1w, 114, 1);
    end;
    x1w := x1w + 24;
    end;

    renderChessman(chessmanRookS, 0, 0, 0);
    renderChessman(chessmanRookS, 0, 133, 1);
    renderChessman(chessmanRookE, 168, 0, 1);
    renderChessman(chessmanRookE, 168, 133, 0);

    renderChessman(chessmanKnightE, 24, 0, 1);
    renderChessman(chessmanKnightE, 24, 133, 0);
    renderChessman(chessmanKnightS, 144, 0, 0);
    renderChessman(chessmanKnightS, 144, 133, 1);

    renderChessman(chessmanBishopS, 48, 133, 1);
    renderChessman(chessmanBishopS, 48, 0, 0);
    renderChessman(chessmanBishopE, 120, 133, 0);
    renderChessman(chessmanBishopE, 120, 0, 1);

    renderChessman(chessmanQueenE, 72, 133, 0);
    renderChessman(chessmanQueenE, 72, 0, 1);

    renderChessman(chessmanKingS, 96, 133, 1);
    renderChessman(chessmanKingS, 96, 0, 0);
    end;

    //---------------------- MAIN PROGRAM ------------------------

    begin
    // There are 192 rows of 320 dots in the full screen mode.
    InitGraph(8);
    bmpAdr := dpeek(88);

    SetColor(1);
    // colors: 2, 4, 80, 82, 96, 98, 112, 130, 132, 144, 146, 148, 150
    color := 2;
    SetBKColor(color);
    TextBackground(color);

    drawBoard;
    drawPieces;

    ReadKey;
    end.

    Dalszy podstęp tak jak pisałem będę meldował co 3-5 dni w osobnym wątku.
    • 5: CommentAuthorMADRAFi
    • CommentTime13 Nov 2019
     
    Moze sie okazac ze zabraknie ci pamieci. Wiem ze to nie intuicyjne ale lekarstwem bedzie pozbycie sie tylu zmiennych oraz parametrow funkcji.
    Roznica jest dosyc spora :)
    • 6: CommentAuthortebe
    • CommentTime13 Nov 2019 zmieniony
     
    zaoszczędzić pamięć można jeśli jakiś większy parametr jak np. string przekazujemy przez wskaźnik, a nie przez wartość

    procedure renderChessman(var chessman: string; x, y, color: byte);


    innym tańszym sposobem oszczędzania na STRING-ach jest ograniczenie ich rozmiaru

    type TChessman = string[77];
    ...
    procedure renderChessman(chessman: TChessman; x, y, color: byte);

    teraz nie zostanie skopiowanych 256 bajtów stringu do lokalnej zmiennej tylko 78

    p.s.
    dla 6 bitowych próbek można zastąpić PutPixel przez wstawianie 3 bajtów, 6*4 = 24 / 8 = 3 bajty

    bierzemy 4 próbki 6 bitowe, przesuwamy bity, OR-ujemy i "wypluwamy" 24 bity w postaci trzech bajtów, najlepiej rozpisać to na kartce i sprawdzić gdzie przesunąć w prawo, gdzie w lewo, a gdzie nie trzeba wcale
    • 7: CommentAuthorzbyti
    • CommentTime13 Nov 2019 zmieniony
     
    @MADRAFi & @tebe - dzięki za praktyczne wskazówki!

    Zacznę zapisywać sobie sobie te uwagi pod postacią "dobrych praktyk" i dam Wam później do recenzji.

    Wciąż jak widać zapominam, że kompilator wszystkiego za mnie nie zrobi (pomijając, że nie wiem jak działa) a docelowo piszę na komputer który ma 64K, z czego i tak nie wszystko jest dla mnie dostępne.

    Spróbuję wyłączyć system, bo rozumiem, że zwolni mi się trochę pamięci.

    No i wprowadzę ww rady.

    Jr. dzięki za uwagi, bez nich utknął bym już na samym początku :)
    • 8: CommentAuthorzbyti
    • CommentTime13 Nov 2019 zmieniony
     
    To jeszcze te poprawki wrzucę tutaj w postaci kodu, mój wątek zacznę od stołu na którym można przesuwać figury.

    Zaczynamy od takich wyników:

    150 lines compiled, 1.45 sec, 11753 tokens, 1098 idents, 309 blocks, 6 types
    2 warning(s) issued
    3 note(s) issued
    ZPFREE: $0000..$007F ; $00D8..$00FF
    SYSTEM: $23E0..$241F
    CRT: $2420..$2443
    FASTGRAPH: $2444..$2C28
    CODE: $2000..$3281
    DATA: $3282..$3AF4
    Writing listing file...
    Writing object file...
    9655 lines of source assembled in 7 pass
    6897 bytes written to the object file

    Zobaczymy ile zejdzie pamięci po poprawkach. I ile szybkości zyskam po rezygnacji z PutPixel.
    • 9: CommentAuthortebe
    • CommentTime13 Nov 2019
     
    wyłączenie OS-a będzie oznaczać większą integrację z ASM, własne programy przerwań itp.

    potrafisz oszacować ile zajmie silnik takiego programu szachowego ?
    • 10: CommentAuthorxxl
    • CommentTime13 Nov 2019
     
    a czy sa silniki onlineowe, do ktorch mozna wysylac i odbierac ruchy?
    • 11: CommentAuthorzbyti
    • CommentTime13 Nov 2019 zmieniony
     
    @tebe nie umiem bo nie wiem jaki ma narzut kompilator MP. Do tego nigdy żadnego engine nie pisałem, to moja pierwsza próba. Mam taką zajawkę ostatnio i cóż poradzić? :) Do tego zawsze chciałem napisać coś co się uruchamia na komputerze 8-bitowym i nie jest scrollem. Jakimś trafem padło na A8 ;)

    Ale pospekulujmy...

    Ile zajmie GUI to już mniej więcej widać. Jeszcze tylko reprezentacja stołu dla GUI i procedura animująca wpisane ruchy.

    Sam silnik w czystym ASM nie powinien być większy od tego co jest w załączniku a jest kodem Sargona (jako, że już zamieszczałem plik to serwer dopisał "2" do nazwy). A ile to wyjdzie w MP?

    Pierwsza implementacja będzie naiwna, ma wykonywać legalne ruchy, rozpoznać szacha i mata.

    Zakładając, że nie napiszę optymalnego kody tylko 2x większy niż w załączniku (mówię o ekwiwalentnym kodzie w MP) to i tak będzie to nieduże.

    Co prawda uświadomiliście mi, że deklarując beztrosko zmienne mogę i z krótkiego kodu zrobić potwora :D

    Jak to mi się uda zacznę kombinować nad ewaluacją pozycji etc. Ale wtedy powinienem mieć już więcej doświadczenia w kodowaniu, więc ew problemy z pamięcią będę umiał jakoś ogarnąć, z resztą jak widzę można liczyć na Waszą pomoc :)
    • 12: CommentAuthorzbyti
    • CommentTime13 Nov 2019 zmieniony
     
    @xxl nie wiem, ale na pewno na github-ie znajdziesz sporo napisanych w JS więc przerobienie tego na to o co pytasz powinno być banalne.

    "zwykłe" silniki komunikują się po ->link<- ->link<- więc możesz napisać nadbudowę w np. node.js.
    • 13:
       
      CommentAuthorarchieil
    • CommentTime13 Nov 2019
     
    @xxl
    gnuchess da się uruchomić jako oddzielny silnik.

    Musiałbym sprawdzić dokładniej ale xboard bodajże obsługuje komputer poprzez podłączenie silnika np. gnuchess albo crafty.

    Tak jak pisałem jeśli zrobić obsługę sieci i wyjście do FICS-a to i silnik można zewnętrzny używać acz czy są jakieś udostępnione w sieci dla innych nie sprawdzałem.

    FICS ma wiele grających komputerów i można poprzez jego system takie rozgrywki zorganizować.

    [edit] pomyliłem wątki.
    • 14: CommentAuthorzbyti
    • CommentTime13 Nov 2019 zmieniony
     
    @tebe

    Najprościej jakbym mógł pakować 8-bit słowem, wtedy od razu mógłbym rozpakowany znak wrzucać jako 1 bajt w trybie 8.

    Chyba tak zrobię kosztem długości stringa. Zamiast znaku ze słownika przekażę sobie bajt w postaci szesnastkowej.

    24*19 = 456
    456 / 4 = 114 --> 0a, ff , 01 itd.

    Czyli z 78 (77 + wartość offsetu) znaków obecnie będę miał 114 w stringu ale odpadną mi wszelkie kombinacje.

    Na szybko zmienię paker na 4-bit słowo i będę łączył po dwa.

    Albo nie, od razy wypluję tablicę bajtów i po sprawie :)

    kingE : array[0..56] of byte = (
    $0,$0,$0,$0,$24,$0,$0,$36,$0,$0,$36,$0,$0,$102,$0,$0,$129,$0,$6,$129,$96,$9,$36,$144,$16,$231,$8,$32,$36,$4,$32,$60,$4,$33,$0,$132,$18,$129,$72,$9,$0,$144,$8,$0,$16,$5,$255,$160,$4,$0,$32,$2,$255,$64,$2,$0,$64
    );
    • 15: CommentAuthorMADRAFi
    • CommentTime13 Nov 2019
     
    Tak z ciekawosci na czym polegaja enginy szachowe ?
    Czy maja jakos zaszyte w sobie mozliwosci ustawienia pionkow?
    CZy to jest na zasadzie glupiego - podaje mu reguly i wage ruchow i jezeli z wieksza waga ruch jest mozliwy do wykonania to go wykonuje?
    Jak potem sie wywaza stopien trudnosci? :)
    • 16: CommentAuthorzbyti
    • CommentTime13 Nov 2019 zmieniony
     
    @MADRAFi jak chcesz mogę Ci odpowiedzieć teraz na zasadzie co o tym czytałem i jak sobie to wyobrażam. Albo poczekaj chwilę to jak jakiś napiszę wypowiem się z większą precyzją ;)
    • 17: CommentAuthorzbyti
    • CommentTime13 Nov 2019 zmieniony
     
    @tebe dzięki za inspirację!!!

    W poprzedniej wersji było tak jeżeli chodzi o czas renderu, w krokach:

    1. sam stół           : 16 ticks
    2. ramka : 9 ticks
    3. 16 pionków : 39 ticks
    4. pozostałe 16 figur : 45 ticks

    Czyli stół z ramką 25 ticks, a 32 figury 84 ticks. Razm 109 ticks a wykonane ciągiem 110 ticks.

    Dzięki Twojej podpowiedzi, 64 figury narysowały się w 22 ticks!

    Czyli jak skończę docelowo będę miał cały stół z bierkami w 22 + 9 = 31 ticks! No może jeszcze parę ticks pójdzie na ze 2-3 if-y ale nie więcej.

    Więc wydaje się, że zszedłem ze 110 na 40! WoW :D

    procedure renderChessman(chessman: array[0..56] of byte; x, y, color: byte);
    var i0b : byte;
    gfxByte : byte;
    chessmanBlock : byte;
    x1w, y1w : word;

    begin
    y1w := y * 760;
    x1w := x * 3;
    gfxByte := 0;
    SetColor(color);
    for i0b := 0 to 18 do begin
    dpoke(bmpAdr + x1w + y1w, chessman[gfxByte]);
    dpoke(bmpAdr + x1w + y1w + 1, chessman[gfxByte + 1]);
    dpoke(bmpAdr + x1w + y1w + 2, chessman[gfxByte + 2]);
    gfxByte := gfxByte + 3;
    y1w := y1w + 40;
    end;
    end;
    • 18: CommentAuthorurborg
    • CommentTime13 Nov 2019
     
    Wygląda jak Colossus Chess, tylko piony inne :) trzymam kciuki za powodzenie
    • 19: CommentAuthorzbyti
    • CommentTime13 Nov 2019 zmieniony
     
    @urborg może i wygląda ;) ale czy będzie tak grało?! :D Szczerze wątpię ;)

    Zmieniłem wieże i piony - wygląda lepiej? Według mnie tak :)
    • 20: CommentAuthorurborg
    • CommentTime13 Nov 2019 zmieniony
     
    Na pierwszy rzut oka wyglądają po prostu nieco dziwnie, bo za bardzo jestem przyzwyczajony do figur z Colossusa. Aczkolwiek przyjrzałem się im uważniej i uważam że wieże po przeróbce są faktycznie znacznie lepsze - jak w klasycznym zestawie Stauntona. Piony zaś wydaja mi się za chude jeśli chodzi o bazę - kojarzą mi się trochę z zestawami w stylu Regency, albo angielskimi Barleycornami.


    • 21: CommentAuthorzbyti
    • CommentTime13 Nov 2019 zmieniony
     
    @urborg dzięki za uwagę. Może kogoś poproszę na finiszu kto potrafi rysować by mi pomógł, na ten moment zostawię jak jest. Zmieniłem bo mi się dla odmiany "grubasy" z CC3 nie podobają, no i chciałem zaznaczyć, że to nie jest bierka wielkości i wagi figury ;)
    • 22: CommentAuthorzbyti
    • CommentTime13 Nov 2019 zmieniony
     
    O kurza twarz!

    Cała szachownica w 30 ticks!

    Zamiana binarnego ciągu na hex to de facto kompresja 1/4 więc wychodzi niewiele więcej niż przy kompresji słownikiem 1/6 a odpada jakakolwiek miniplantacji na danych. Po prostu wrzuca się to w trybie 8 bajt po bajcie.

    Rewelacja, że też nie przyszło mi to wcześniej do głowy?

    Myślałem, że już nie zejdę z tych 110 a tu proszę, mam 30!

    No trochę będzie finalnie więcej bo muszę wskazywać bierki do rysowania inne niż król ale 40 ticks będzie max :)

    EDIT: no i dzięki pomocy @tebe finalnie stanęło na 30 tikach z kompletem bierek.
    • 23: CommentAuthortebe
    • CommentTime13 Nov 2019
     
    ten DPoke to celowo użyłeś ? zapisujesz na ekran po 2-bajty ?
    DPoke to 'Double Poke', jeden bajt zapisuje się przez Poke

    nazwy tych procedur zostały zaczerpnięte z BASIC-a/Turbo BASIC-a

    dpoke(bmpAdr + x1w + y1w, chessman[gfxByte]);
    dpoke(bmpAdr + x1w + y1w + 1, chessman[gfxByte + 1]);
    dpoke(bmpAdr + x1w + y1w + 2, chessman[gfxByte + 2]);


    dpoke(bmpAdr + x1w + y1w, chessman[gfxByte]);

    zapisałeś dwa bajty chessman[gfxByte], chessman[gfxByte+1] pod adresami (bmpAdr + x1w + y1w), (bmpAdr + x1w + y1w + 1)

    teraz w następnej linii
    dpoke(bmpAdr + x1w + y1w + 1, chessman[gfxByte + 1]);

    ponownie zapisujesz chessman[gfxByte + 1] pod adresem bmpAdr + x1w + y1w + 1

    co drugi bajt obrazu zapisujesz ponownie :) tą samą wartością
    • 24: CommentAuthorzbyti
    • CommentTime13 Nov 2019 zmieniony
     
    @tebe przed implementacją przetestowałem to tak:

    program test;

    uses crt, fastgraph;

    var
    bmpAdr : word;
    i0b : byte;

    begin
    // There are 192 rows of 320 dots in the full screen mode.
    InitGraph(8);
    bmpAdr := dpeek(88);
    SetColor(1);

    for i0b := 0 to 255 do begin
    dpoke(bmpAdr, i0b);
    dpoke(bmpAdr + 1, i0b);
    dpoke(bmpAdr + 2, i0b);
    writeln(HexStr(i0b, 2));
    Readkey;
    end;
    end.

    I mi się zgadzało. Czytałem cześniej w dokumentacji o poke i dpoke ale jak widać to do mnie nie przemówiło, nie zapamiętałem istotniej, narzucającej się różnicy :D

    No tak, masz rację powinienem użyć poke :D

    Ale ze mnie lamer :D
    • 25: CommentAuthorzbyti
    • CommentTime13 Nov 2019 zmieniony
     
    @tebe dzięki temu, że zauważyłeś, że nie wiem co robię ;) to pozyskany czas CPU poświecę na xor i będzie banglało przy dwóch wersjach kolorystycznych na bierkę w tym samym czasie co uprzednio :D Zaoszczędzę na pamięci :)
    • 26: CommentAuthorzbyti
    • CommentTime13 Nov 2019 zmieniony
     
    program chessboard;

    //---------------------- LIBRARES ----------------------------------

    uses crt, fastgraph;

    //---------------------- GLOBAL VARIABLES --------------------------

    var
    bmpAdr : word;
    color : byte;

    {* White square, invert Black square *}
    wSquare : array[0..56] of byte = (...);
    {* White pawn on black, invert Black pawn on white *}
    pawnSe : array[0..56] of byte = (...);
    {* Black pawn on black, invert White pawn on white *}
    pawnEe : array[0..56] of byte = (...);
    {* White king on black, invert Black king on white *}
    kingSe : array[0..56] of byte = (...);
    {* Black king on black, invert White king on white *}
    kingEe : array[0..56] of byte = (...);
    {* White queen on black, invert Black queen on white *}
    queenSe : array[0..56] of byte = (...);
    {* Black queen on black, invert White queen on white *}
    queenEe : array[0..56] of byte = (...);
    {* White rook on black, invert Black rook on white *}
    rookSe : array[0..56] of byte = (...);
    {* Black rook on black, invert White rook on withe *}
    rookEe : array[0..56] of byte = (...);
    {* White knight on black, invert Black knight on white *}
    knightSe : array[0..56] of byte = (...);
    {* Black knight on black, invert White knight on withe *}
    knightEe : array[0..56] of byte = (...);
    {* White bishop on black, invert Black bishop on white *}
    bishopSe : array[0..56] of byte = (...);
    {* Black bishop on black, invert White bishop on withe *}
    bishopEe : array[0..56] of byte = (...);

    //---------------------- PROCEDURES --------------------------------

    procedure renderChessman(var chessman: array[0..56] of byte; x, y, invert: byte);
    var i0b : byte;
    gfxByte : byte;
    x1w, y1w : word;
    begin
    y1w := y * 760;
    x1w := x * 3;
    gfxByte := 0;
    for i0b := 0 to 18 do begin
    poke(bmpAdr + x1w + y1w, chessman[gfxByte] xor invert);
    poke(bmpAdr + x1w + y1w + 1, chessman[gfxByte + 1] xor invert);
    poke(bmpAdr + x1w + y1w + 2, chessman[gfxByte + 2] xor invert);
    gfxByte := gfxByte + 3;
    y1w := y1w + 40;
    end;
    end;

    procedure drawBoard;
    var i0b, i1b, coordinate: byte;
    begin
    renderChessman(rookSe, 0, 0, $ff);
    renderChessman(rookEe, 7, 0, 0);
    renderChessman(rookSe, 0, 7, 0);
    renderChessman(rookEe, 7, 7, $ff);
    renderChessman(knightEe, 1, 0, 0);
    renderChessman(knightSe, 6, 0, $ff);
    renderChessman(knightEe, 1, 7, $ff);
    renderChessman(knightSe, 6, 7, 0);
    renderChessman(bishopSe, 2, 0, $ff);
    renderChessman(bishopEe, 5, 0, 0);
    renderChessman(bishopSe, 2, 7, 0);
    renderChessman(bishopEe, 5, 7, $ff);
    renderChessman(queenEe, 3, 0, 0);
    renderChessman(queenEe, 3, 7, $ff);
    renderChessman(kingSe, 4, 7, 0);
    renderChessman(kingSe, 4, 0, $ff);

    coordinate := 0;
    for i0b := 0 to 7 do begin
    if (i0b and %1 = 0) then begin
    renderChessman(pawnEe, coordinate, 1, 0);
    renderChessman(pawnEe, coordinate, 6, $ff);
    end else begin
    renderChessman(pawnSe, coordinate, 1, $ff);
    renderChessman(pawnSe, coordinate, 6, 0);
    end;
    coordinate := coordinate + 1;
    end;

    for i1b := 0 to 1 do begin
    coordinate := 0;
    for i0b := 0 to 7 do begin
    if (i0b and %1 = i1b) then begin
    renderChessman(wSquare, coordinate, 2 + i1b, 0);
    renderChessman(wSquare, coordinate, 5 - i1b, $ff);
    end else begin
    renderChessman(wSquare, coordinate, 2 + i1b, $ff);
    renderChessman(wSquare, coordinate, 5 - i1b, 0);
    end;
    coordinate := coordinate + 1;
    end;
    end;

    SetColor(1);
    rectangle(0, 0, 192, 152);
    end;

    //---------------------- MAIN PROGRAM ------------------------------

    begin
    // There are 192 rows of 320 dots in the full screen mode.
    InitGraph(8);
    bmpAdr := dpeek(88);

    SetColor(1);
    // colors: 2, 4, 80, 82, 96, 98, 112, 130, 132, 144, 146, 148, 150
    color := 2;
    SetBKColor(color);
    TextBackground(color);

    drawBoard;

    ReadKey;
    end.
    • 27: CommentAuthorzbyti
    • CommentTime13 Nov 2019 zmieniony
     
    Tak to szło, historia obrazkowa :) @tebe wiszę Ci DUŻE craftowe piwo! :D

    Wersja posta edytowana wraz z postępami.
    • 28: CommentAuthortebe
    • CommentTime13 Nov 2019
     
    teraz skoro szybki PutPixel nie jest już potrzebny, możesz przejść z FASTGRAPH na GRAPH i odzyskasz sporo pamięci
    • 29: CommentAuthorzbyti
    • CommentTime13 Nov 2019 zmieniony
     
    @tebe dobra myśl, ale wtedy muszę narysować własny prostokąt bo graph dokłada 9 tików więcej w stosunku to fastgraph by go narysować. Jak zrobię własny prostokąt to w ogóle mogę zrezygnować z tej biblioteki :)

    No to jeszcze to zrobię :)

    Aaaa... ale to mi InitGraph wyłączy i SetColor etc. Muszę to przemyśleć. Tak się cieszyłem z 29 tików, że jak teraz zobaczyłem 38 to ... ;)

    18 tików na samą ramkę, ramka za pomocą graph rysuje mi się prawie tyle co sam stół z figurami :D

    Dobra, zrobię własną procedurę, rysującą prostokąt, powinno być szybciej niż 18 tików które potrzebuje graph :D
    • 30:
       
      CommentAuthorbocianu
    • CommentTime14 Nov 2019 zmieniony
     
    SetColor mozesz zastąpić zapisując wartości prosto do rejestrów:
    color1 := kolor_pixeli;
    color2 := kolor_tła;
    pod warunkiem, że do uses dodasz 'atari'
    ściąga: ->link<-
    albo tak:
    poke(709, kolor_pixeli);
    poke(710, kolor_tła);


    InitGraph to musiałbyś już zastąpić swoją listą displejową.
    Ale to już trzeba trochę poznać Antica :D Nie wiem czy czujesz się już gotów na wyższy stopień wtajemniczenia.
    Można sobie pomóc biblioteką 'b_dl' z blibsów.
    ściąga: ->link<-

    Są też przykłady w examples z blibsów.
    • 31: CommentAuthorzbyti
    • CommentTime14 Nov 2019 zmieniony
     
    @bocianu dziękuję :) No to z tego co piszesz wynika, że nie zrezygnuję z graph, display listy to może po tym projekcie zacznę ogarniać ;)

    No to mam nowy rekord! Całość z ramką renderuje się w 20 tików!


    Jestem zadowolony! Dziękuję Panom za współpracę na tym etapie :)

    procedure drawRectangle;
    var i0b : byte;
    tmpBmpAdr : word;
    y : word = 0;
    begin
    tmpBmpAdr := bmpAdr + 23;
    for i0b := 0 to 152 do begin
    poke(bmpAdr + y, peek(bmpAdr + y) or %10000000);
    poke(tmpBmpAdr + y, peek(tmpBmpAdr + y) or %00000001);
    y := y + 40;
    end;
    tmpBmpAdr := bmpAdr + 6080; // 19*8*40
    for i0b := 0 to 23 do begin
    poke(bmpAdr + i0b, $ff);
    poke(tmpBmpAdr + i0b, $ff);
    end;
    end;
    • 32:
       
      CommentAuthorbocianu
    • CommentTime14 Nov 2019
     
    Nie żebym się czepiał, ale tak ma być? :)
    • 33: CommentAuthorzbyti
    • CommentTime14 Nov 2019 zmieniony
     
    @bocianu ależ czepiaj się ;)

    Pewnie jak sobie generowałem tablicę hexów to nie przykleiłem czegoś, dzięki, zaraz obadam. Ja tyle razy dziś widziałem tę szachownicę, że już nie dostrzegam detali :D

    EDIT: faktycznie pawnSe w tablicy na ostatnim miejscu zamiast $80 miał $800 :D

    Już poprawiłem, dzięki za dostrzeżenie tego detalu :)

    No to już finalna (mam nadzieję) wersja kodu w załączniku.

    Jak już będę robił poruszanie się figurami to będę musiał ramkę zrobić na zewnątrz stołu bo inaczej figury zamalują ramkę. Ale to już w wersji w wątku dedykowanym temu projektowi ;)
    • 34: CommentAuthormav
    • CommentTime14 Nov 2019
     
    Super :)
    Szacuneczek.
    Co teraz? ;)

    Zaszyjesz tam jakiś AI?
    • 35: CommentAuthorzbyti
    • CommentTime14 Nov 2019 zmieniony
     
    @mav AI zaczynam od poniedziałku ;)

    Haha! 17 ticks!

    mp-build chessboard.pas run
    Mad Pascal Compiler version 1.6.2 [2019/11/05] for 6502
    Compiling chessboard.pas
    /home/zbyti/Programs/MadPascal/lib/graph.inc (672) Warning: lo/hi(dword/qword) returns the upper/lower word/dword
    /home/zbyti/Programs/MadPascal/lib/graph.inc (673) Warning: lo/hi(dword/qword) returns the upper/lower word/dword
    chessboard.pas (39) Note: Local variable 'KINGEE' not used
    chessboard.pas (45) Note: Local variable 'QUEENSE' not used
    198 lines compiled, 1.18 sec, 12919 tokens, 1074 idents, 306 blocks, 6 types
    2 warning(s) issued
    2 note(s) issued
    ZPFREE: $0000..$007F ; $00D8..$00FF
    SYSTEM: $202C..$2062
    CRT: $2063..$2086
    GRAPH: $2087..$20F1
    CODE: $2000..$278A
    DATA: $278B..$2AB4
    Writing listing file...
    Writing object file...
    8169 lines of source assembled in 6 pass
    2732 bytes written to the object file
    • 36: CommentAuthortebe
    • CommentTime14 Nov 2019
     
    procedure drawRectangle;
    var i0b : byte;
    tmpBmpAdr : word;
    y : word = 0;


    ta procedura zadziała dobrze tylko raz, na początku, jeśli drugi raz ją uruchomisz zacznie rysować poza polem szachownicy

    wszystko przez zmienną Y, która jest zaincjowana wartością 0, ale ta inicjalizacja dotyczy tylko pierwszego uruchomienia zaraz po wczytaniu programu do pamięci
    • 37: CommentAuthorzbyti
    • CommentTime14 Nov 2019 zmieniony
     
    @tebe dziękuję, to cenna uwaga! Nie wiem dlaczego wyobrażałem sobie, że zmienne deklarowane i zainicjalizowane w ciele procedury są jeszcze raz ustawiane przy jej wywołaniu?

    Teraz jak mi na to zwróciłeś uwagę to ma to sens.

    Niestety ja zacząłem programowanie z "łapanki" 12 lat temu od Javy 1.4, potem pisałem w PHP, trochę w Scali i Angularze. Nigdzie (pisząc w tych językach) nie musiałem dbać o pamięć.

    Wskaźniki mnie ominęły i inne rzeczy które można spotkać w C, za to przywykłem do garbage collectora i innych wynalazków.

    Mam w planach w roku 2020 nauczyć się GO langa to może zacznę myśleć w bardziej praktyczny sposób ;)

    Przemyślę kod pod tym względem. I poprawię.

    Faktycznie wszystkie zmienne pomocnicze zostaną w pamięci, muszę w takim razie zrobić je globalnymi i używać w procedurach, wtedy nie będę mnożył bytów.

    Tutaj enkapsulacja robi narzut - ma to sens.
    • 38: CommentAuthortebe
    • CommentTime14 Nov 2019
     
    wystarczy że w ciele procedury dodasz
    y:=0;

    to wystarczy, nie potrzebujesz globalnych zmiennych, wystarczą lokalne, tylko musisz je zaincjować na początku bloku jeśli będziesz chciał wielokrotnie korzystać z takiej procedury/funkcji

    w MP możesz stosować lokalne jak i globalne zmienne, bez znaczenia, dostęp do nich jest tak samo szybki, bo są to cały czas lokalne zmienne tylko o różnych przestrzeniach nazw
    • 39: CommentAuthorzbyti
    • CommentTime14 Nov 2019 zmieniony
     
    @tebe chodziło mi raczej o przypadek jaki opiszę poniżej.

    W procedurach korzystam często z iteratorów w pętlach.

    1. Czy jeżeli mam trzy procedury i w każdej zadeklarowane dwie zmienne i0b i i1b typu byte to kompilator zarezerwuje 6 bajtów, tak?

    2. A jeżeli tego typy zmienne będę miał piętro wyżej każda z tych trzech procedur będzie z nich korzystać to kompilator zarezerwuj dwa bajty, tak?

    Język jest proceduralny, nie występuje ryzyko nadpisania sobie wartości więc muszę tylko pamiętać o zainicjowaniu żądaną wartością w procedurze.

    Dobrze kombinuje? Czy kompilator zbiera tego typy zmienne i w obu przypadkach będę miał zarezerwowane tylko dwa bajty?

    Pomyślałem, że mogę oszczędzić pamieć deklarując niektóre zmienne tylko raz.
    • 40: CommentAuthorMADRAFi
    • CommentTime14 Nov 2019
     
    zaoszczedzisz :)
    • 41: CommentAuthortebe
    • CommentTime14 Nov 2019
     
    ad 1: tak
    ad 2: tak
    • 42: CommentAuthorzbyti
    • CommentTime14 Nov 2019 zmieniony
     
    @tebe & MADRAFi no to fajnie :)

    Jeszcze muszę ogarnąć dlaczego nie działa mi to w praktyce :D
    Jak nie dojdę to zwrócę się o pomoc ;)

    EDIT:
    A dobra już wiem. Zrobiłem błędne założenie, że się nic nie nadpisze a przecież mogę wywołać procedurę w procedurze i dupa blada :)

    No to będę oszczędzał pamięć ale z głową :D
    • 43: CommentAuthormono
    • CommentTime14 Nov 2019
     
    @Tebe: A nie dałoby się zrobić jakiegoś grafu wywołań funkcji i recyklingować zmienne? Albo też określić kiedy jest sens kopiować zmienną, która mimo że przekazywana przez kopię nigdy nie jest modyfikowana?
    • 44: CommentAuthortebe
    • CommentTime14 Nov 2019 zmieniony
     
    można też zagnieżdżać procedury/funkcje w swojej procedurze przez to będą one miały dostęp do zmiennych lokalnych tej procedury, ale jest to niebezpieczne jeśli z poziomu takiej pętli zaczniemy wywoływać procedurę która modyfikuje taką zmienną wykorzystywaną przez licznik pętli

    procedure test;
    var x,y: byte;

    procedure test2;
    begin
    for x:=0 to 100 do ;
    end;

    begin
    for x:=0 to 10 do ;
    end;


    w FPC takie podejście wygeneruje błąd 'Illegal counter variable'
    • 45: CommentAuthortebe
    • CommentTime14 Nov 2019 zmieniony
     
    w MP wszystkie zmienne są statycznie alokowane przy pierwszym uruchomieniu programu, nie są przekazywane przez stos, jak ma to miejsce w oryginalnym podejściu CC65 albo Pascal-ach z dużych platform

    Stos w MP to mały wycinek pamięci strony zerowej która jest wykorzystywana do przekazania parametrów do procedury i ich zdjęcia (teoretycznie można się tego pozbyć), albo wywołania innych procedur wbudowanych w kompilator których nie udało się zamienić INLINE, dotyczy to najczęściej operacji na typach rzeczywistych

    w sumie bardziej jest to przekazanie parametrów przez zmienną za pośrednictwem mini stosu strony zerowej

    Natywny kompilator CLSN Pascal dla Atari 130XE korzysta z pamięci dodatkowej (64KB) aby na niej realizować stos programowy i oryginalne podejście poprzez alokacje zmiennych przez stos

    ->link<-
    • 46: CommentAuthorzbyti
    • CommentTime14 Nov 2019 zmieniony
     
    @tebe nie ma szansy na taką konstrukcję?

    type TChessman = array[0..56] of byte;

    var chessboard = array[0..63] of TChessman;

    Kompiluje się do póki nie próbuję zainicjować lub wypełnić chessboard.

    To jest ten sam case? ->link<-

    -------------------------------------------------------------

    Przecież mógłbym chyba zrobić:

    type TChessman = string[57];

    var chessboard = array[0..63] of TChessman;

    Kosztowało by mnie to tłumaczenie liter na wartości ale efekt miał bym ten sam.

    I by pewnie zadziałało. Jaka jest technicznie różnica i trudność w realizacji pierwszego sposobu?
    • 47: CommentAuthorzbyti
    • CommentTime14 Nov 2019 zmieniony
     
    W sumie to widać, że ciągle zapominam, że nie pisze w Pascalu tylko mam pewien jego podzbiór a docelowo chodzi o szybki kod maszynowy.

    Chciałem mieć osobną reprezentację stołu dla GUI i osobną dla silnika. Ostatecznie skorzystam z kodu Sargona i zrealizuję to podobnie, więc pytanie nie aktualne.

    ;************************************************************
    ; BOARD -- Board Array. Used to hold the current position
    ; of the board during play. The board itself
    ; looks like:
    ; FFFFFFFFFFFFFFFFFFFF
    ; FFFFFFFFFFFFFFFFFFFF
    ; FF0402030506030204FF
    ; FF0101010101010101FF
    ; FF0000000000000000FF
    ; FF0000000000000000FF
    ; FF0000000000000060FF
    ; FF0000000000000000FF
    ; FF8181818181818181FF
    ; FF8482838586838284FF
    ; FFFFFFFFFFFFFFFFFFFF
    ; FFFFFFFFFFFFFFFFFFFF
    ; The values of FF form the border of the
    ; board, and are used to indicate when a piece
    ; moves off the board. The individual bits of
    ; the other bytes in the board array are as
    ; follows:
    ; Bit 7 -- Color of the piece
    ; 1 -- Black
    ; 0 -- White
    ; Bit 6 -- Not used
    ; Bit 5 -- Not used
    ; Bit 4 --Castle flag for Kings only
    ; Bit 3 -- Piece has moved flag
    ; Bits 2-0 Piece type
    ; 1 -- Pawn
    ; 2 -- Knight
    ; 3 -- Bishop
    ; 4 -- Rook
    ; 5 -- Queen
    ; 6 -- King
    ; 7 -- Not used
    ; 0 -- Empty Square
    ;**********************************************************
    • 48: CommentAuthorgorgh
    • CommentTime14 Nov 2019
     
    bardzo fajnie zbyti, że się wziąłeś za programowanie dla Atari
    • 49: CommentAuthortebe
    • CommentTime14 Nov 2019
     
    to jest dwuwymiarowa tablica

    var chessboard : array[0..63, 0..56] of byte;


    działa jej inicjowanie, przykład dla mniejszego zakresu
    type TChessman = array[0..1] of byte;
    var chessboard : array[0..1] of TChessman = ((0,1),(2,3));
    • 50: CommentAuthorzbyti
    • CommentTime14 Nov 2019 zmieniony
     
    @tebe a faktycznie, ale tablic 2D unikam ze względu na wydajność ;)

    Sorki za pytanie, mogłem się zastanowić przed zadaniem.

    var chessboard : array[0..63] of TChessman = (rook, knight, ...);

    Tak chciałem ją wypełnić :D

    Zamiast śmiesznych wygibasów w pętlach jakie teraz robię, żeby narysować stół, chciałem sobie przelecieć po 64 polach z jednej tablicy w jednej pętli. Znów przyzwyczajenia z innych języków. Chyba for each mi się zachciało ;)

    Dobrze, że FOR COMPREHENSIONS nie chciałem użyć :D

    @gorgh zobaczymy co z tego wyjdzie ;) jak na razie miałem parę lat przerwy od programowania w ogóle i do tego widzę, że mam jakieś złe praktyki zakorzenione :D Ale powoli odrzdzewieję ;)

    EDIT: ale to chyba, można zrobić jednowymiarową tablicę ze wskaźnikami do bierek? Spróbuję :)