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
      • CommentTime16 Aug 2025 08:49
       
      wynik assemblacji wyrzuca na konsolę informacje

      ZPAGE: $0080..$00D3
      RTBUF: $0400..$04FF
      RTLIB: $2030..$2295
      SYSTEM: $22C0..$22D1

      z w/w wynika że możesz od $d4 dać absolute dla swoich zmiennych

      absolute jest pewniejsze

      PByte jest dodatkowo optymalizowane jeśli jest register lub absolute na stronie zerowej
      • 2:
         
        CommentAuthorMaW
      • CommentTime16 Aug 2025 13:25 zmieniony
       
      Dzięki, jak dobrze liczę, można 44 rejestry założyć na stronie zerowej?
      I myślę, że z absolute najbezpieczniej od $FF jechać w dół, gdyby MP przy kompilacji jeszcze coś dołożył i ZPAGE poszło do góry?
      • 3: CommentAuthortebe
      • CommentTime16 Aug 2025 13:57
       
      jeśli wyłączysz OS, to możesz od $00..$7f
      • 4:
         
        CommentAuthorMaW
      • CommentTime24 Jan 2026 11:03 zmieniony
       
      Hej, mam problem z podpięciem tego plajerka pod vblanka:
      Program SelfTestPlayer;

      {$librarypath '../blibs'}
      uses atari, sysutils, b_crt, graph;

      const
      AUDF1 = $D200;
      AUDCTL = $D208;
      RTCLOCK = $14;
      Melody0: array[0..26] of byte = (
      0, 0, 5, // clockVal=0, noteNum=0, notes-1
      32, 81, 168, 8, // nuta 1: noteTime, audf, audc, audctl
      32, 91, 168, 8, // nuta 2
      32, 68, 168, 8, // nuta 3
      16, 60, 168, 8, // nuta 4
      16, 45, 168, 8, // nuta 5
      32, 53, 168, 8 // nuta 6
      );
      Melody1: array[0..26] of byte = (
      0, 0, 5, // clockVal=0, noteNum=0, notes-1
      32, 81, 168, 0, // nuta 1: noteTime, audf, audc, audctl
      32, 91, 168, 0, // nuta 2
      32, 68, 168, 0, // nuta 3
      16, 60, 168, 0, // nuta 4
      16, 45, 168, 0, // nuta 5
      32, 53, 168, 0 // nuta 6
      );
      Melody2: array[0..26] of byte = (
      0, 0, 5, // clockVal=0, noteNum=0, notes-1
      32, 81, 168, 0, // nuta 1: noteTime, audf, audc, audctl
      32, 91, 168, 0, // nuta 2
      32, 68, 168, 0, // nuta 3
      16, 60, 168, 0, // nuta 4
      16, 45, 168, 0, // nuta 5
      32, 53, 168, 0 // nuta 6
      );
      Melody3: array[0..26] of byte = (
      0, 0, 5, // clockVal=0, noteNum=0, notes-1
      32, 81, 168, 0, // nuta 1: noteTime, audf, audc, audctl
      32, 91, 168, 0, // nuta 2
      32, 68, 168, 0, // nuta 3
      16, 60, 168, 0, // nuta 4
      16, 45, 168, 0, // nuta 5
      32, 53, 168, 0 // nuta 6
      );
      audioChannels = 2;

      var
      i: byte = 0;

      procedure PlayMelody;// interrupt;

      var
      melody_pos: word;
      melody_pos1: byte;
      currentAUDRej: word;
      currentMelodyAdr: word;
      channelCounter: byte;
      timeCounter: byte;

      begin

      //asm { phr ; store registers };
      channelCounter := 0;
      timeCounter := Peek(RTCLOCK);
      //
      repeat

      case channelCounter of
      0: currentMelodyAdr := word(@Melody0);
      1: currentMelodyAdr := word(@Melody1);
      2: currentMelodyAdr := word(@Melody2);
      3: currentMelodyAdr := word(@Melody3);
      end;

      //melody_pos na początku wskazuje pozycję zero tablicy melodii,
      //teraz to curruntNote[EndTime] == MelodyN[0]
      melody_pos:= currentMelodyAdr;

      // ustawienie rejestru własciwego dla kanału
      currentAUDRej:= AUDF1;
      inc(currentAUDRej, channelCounter shl 1);

      //aktualizuj, gdy nadszedł czas grania
      // zerowy element (EndTime) <= timeCounter
      if (Peek(melody_pos) <= timeCounter) then
      begin
      inc(melody_pos);

      Writeln(intToStr(timeCounter),' ',intToStr(Peek(currentMelodyAdr)),' ',intToStr(Peek(melody_pos)),' ',intToStr(Peek(melody_pos+1)),' ');

      //jeżeli numer nuty (melody_pos) jest równy ilości nut (melody_pos+1)
      if (Peek(melody_pos) = Peek(melody_pos+1)) then // m0 > notesCount (pozycja 2 w tablicy)
      begin
      melody_pos1:= 0;// ustaw numer nuty na pierwszą
      end
      else
      begin
      melody_pos1:= Peek(melody_pos)+1;// zwiększ noteNum o 1
      end;

      Poke(melody_pos, melody_pos1); //wstaw do pozycji bieżącej nuty

      inc(melody_pos, 2); //ustaw noteTime na pierwszą nutę
      inc(melody_pos, melody_pos1 shl 2); // przeskocz (do czasu aktualnej nuty) o noteNum*4
      //inc(timeCounter, Peek(melody_pos)); // zwiększ timeCounter o noteTime tej nuty
      Poke(currentMelodyAdr, Peek(melody_pos)+timeCounter); // wstaw timeCounter na pozycję zerową (startTime)
      inc(melody_pos); // przesuń do audf nuty
      Poke(currentAUDRej, Peek(melody_pos)); // wpisz audf do currentAUDRej
      inc(melody_pos); // przesuń do audc nuty
      inc(currentAUDRej); // przesuń rejestr na AUDC
      Poke(currentAUDRej, Peek(melody_pos)); // wpisz audc do AUDC
      inc(melody_pos); // przesuń do audctl nuty
      Poke(AUDCTL, Peek(melody_pos)); // audctl do AUDCTL
      end;
      // zmiana kanału
      inc(channelCounter);
      until channelCounter >= audioChannels;

      end;

      procedure InstallVBL;
      begin
      SetIntVec(iVBL, @PlayMelody);
      end;

      //
      // START PROGRAM
      //
      begin
      //Reserve memoryPage
      RAMTOP:=$50;
      InitGraph(0);

      // Set graphics mode and playfield colors
      CRT_Init;
      CRT_Clear(0);
      //Poke(710, 122); Poke(712, 130);
      //Poke(709, 64);

      //InstallVBL;
      //{*
      repeat
      PlayMelody;
      until CRT_KeyPressed;
      //*}
      end.

      Dopóki jest w pętli, działa prawidłowo. W momencie wpięcia pod przerwanie powoduje crash komputera :(

      Drugie pytanie: dodałem pełny opis w komentarzu - czy da się coś zoptymalizować, nie przechodząc do asemblera?
      • 5: CommentAuthortebe
      • CommentTime24 Jan 2026 15:06 zmieniony
       
      obsługa przerwań musi kończyć się odpowiednim skokiem 'JMP xxxx'

      ->link<-

      Przerwanie VBLD (VBL opóźnione) kończymy skokiem pod adres XITVBV ($E462) co spowoduje przywrócenie wartości rejestrów A X Y CPU6502.

      Przerwanie VBLDI (VBL natychmiastowe) kończymy skokiem pod adres SYSVBV ($E45F) co spowoduje kontynuację obsługi przerwania VBL.

      p.s.
      używanie WRITELN na przerwaniu to poważne przeginanie pały

      użycie IntToStr, gdzie WRITELN automatycznie rozpoznaje, tekst, liczby etc. jest nadmiarowe

      p.s. #2
      nie powinno sie używać na przerwaniu kompilowanego kodu, bo taki kod może korzystać ze strony zerowej, a to spowoduje konflikt z głównym programem (chyba że zadbamy o zapamiętanie komórek strony zerowej i ich przywrócenie na końcu przerwania)


      // zmiana kanału
      inc(channelCounter);
      until channelCounter >= audioChannels;

      asm
      jmp xitvbv
      end;
      end;

      procedure InstallVBL;
      begin
      SetIntVec(iVBLD, @PlayMelody);
      end;

      //
      // START PROGRAM
      //
      begin
      //Reserve memoryPage
      RAMTOP:=$50;
      InitGraph(0);

      // Set graphics mode and playfield colors
      CRT_Init;
      CRT_Clear(0);
      //Poke(710, 122); Poke(712, 130);
      //Poke(709, 64);

      InstallVBL;

      repeat until CRT_KeyPressed;

      {*
      repeat
      PlayMelody;
      until CRT_KeyPressed;
      *}
      end.
      • 6:
         
        CommentAuthorMaW
      • CommentTime24 Jan 2026 17:41 zmieniony
       
      Dziękuję!!!
      Widzę, że sam bym tego "nie pochytał" - w załączeniu *.pas i *.xex.

      PS. WriteLn było wyłącznie dla testów "poza VBLK" - dzięki za wskazówki!
      • 7:
         
        CommentAuthorMaW
      • CommentTime25 Jan 2026 18:44 zmieniony
       
      jeszcze tylko takie pytanie: czy procedura z deklaracją "interrupt" nie powinna być "objęta" rozkazami
      asm {
      phr ;na start
      }
      //...
      //i
      asm {
      plr ;na koniec przed
      jmp XITVBV
      }

      ?
      • 8: CommentAuthortebe
      • CommentTime25 Jan 2026 22:39
       
      interrupt to NMI, IRQ, DLI etc. więc nie ma jednego wspólnego schematu