atarionline.pl Scramble in Action! - 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: CommentAuthorxxl
      • CommentTime19 May 2020 23:05
       
      Ok wrzucam od $F do $C może mieć to sens


      mozesz wsadzic stara (ta dluga z pha i pla) procedure DLI ale nowe wartosci w HSCROL ? zobaczymy czy sie wyrobi. moze sie myle.
      • 2: CommentAuthorzbyti
      • CommentTime20 May 2020 00:05 zmieniony
       
      @xxl potwierdzam, nie mylisz się, program zaczął się wyrabiać gdy iterowałem się od $F a nie od $3 na wersji kodu z glitchem ->link<-
      • 3: CommentAuthorzbyti
      • CommentTime20 May 2020 03:05 zmieniony
       
      MEMO

      Jeżeli $495=8 i nie używam edytora Action! to:

      - CODEBASE ustawiane ze pomocą SET $E może zaczynać się już od $E0A
      - tablica symboli zaczyna się od $9400
      - DL Action! leży na $9C00
      - ekran zadeklarowany w DL zaczyna się od $9C40

      Przy metodzie pracy pracy polegającej na pisaniu poza Atari a tylko kompilowaniu na A8 do dyspozycji mam pamięć ciągłą od adresu $E0A do $93ff czyli $85F6 a w bajach to 34294.

      Po kompilacji do dyspozycji mam jeszcze pamięć od $9400 do $BFFF czyli dodatkowe $2BFF czyli 11263 bajty.

      Także bez większych kombinacji do dyspozycji mamy $B1F5 czyli 45557 bajty, plus szósta strona.

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

      Niestety nie mam pojęcia jak przebiega kompilacja, gdzie są wczytywane źródła itd.
      • 4: CommentAuthorzbyti
      • CommentTime20 May 2020 14:05 zmieniony
       
      Zapętliłem rysowanie terenu:

      ; jeżeli zbliżasz się do końca pętli zniweluj teren

      ROW=NEXTROW

      IF LMS>STARTSCREEN+LOOP-$30 THEN
      IF ROW>0 THEN
      NEXTROW==-1
      DRAWROW=RSLOPE DRAWNEXTROW=RFILL
      RET
      ELSE
      DRAWROW=GLADE RET
      FI
      FI

      ;-----------------------------------------------

      PROC DRAWLINE=*()
      SETBLOCK(STARTSCREEN+STARTROW+$120,$30,GLADE)
      RET

      ;-----------------------------------------------

      IF LMS=STARTSCREEN+LOOP+4 THEN
      DRAWLINE()
      NEXTROW=0 SCREENI=STARTROW LMS=STARTSCREEN
      ELSE

      Przy LOOP=$300 zużywam w GR.0 na rysowanie ekranu niecałe $800.

      Powyższy kod odpowiada mojej koncepcji gry gdzie co każde LOOP-$30 podbijam PHASE na liczniku gry o jeden, wypłaszczam teren i daję graczowi 1 ekran (~3,8 sekundy) odpoczynku. Może puszczę wtedy jakiegoś bossa? Zobaczymy :]

      PHASE zlicza coś w stylu dzisiejszych WAVES, krótko mówiąc oznacza ile razy przeżyłeś przelot nad wygenerowanym terenem :]

      EDIT: jakby co to wiem, że można ustawiać LMS dla każdej linii scrolla i pętlić inaczej :]
      • 5: CommentAuthorzbyti
      • CommentTime20 May 2020 19:05
       

      Vertical Blank Interrupts:

      The vectors are called Immediate VBlank and Deferred VBlank. Atari engineers split the Vertical Blank period into two separate sections because a VBI can extend for about 20,000 cycles or nearly all the time available before the next VBI. The Immediate VBlank portion refers to the time critical period when the electron beam is actually offscreen. It is here that shadowing and hardware registers are updated. Once the OS VBI routine has completed its housekeeping chores, it jumps through the Deferred VBlank vector, which is set by the OS to point to a routine that will restore the registers and return the computer to its position before the interrupt. The OS VBI routine will abort if the computer was in the middle of a time critical I/0 routine such as sending data to a cassette or disk drive. In such a case, the Deferred VBlank vector is bypassed. Unless you are using disk 1/0 where your code must be short enough not to delay shadowing updating, you can use Deferred VBlank without being concerned.

      A major question asked by many programmers is: How much time do I have in the VBI routine to execute my code? To answer this we must examine the TV process again.

      A television image is composed of 525 lines. Because of what is called interlacing, only half are drawn per frame, and some of these are offscreen due to normal vertical overscan. It takes the TV 63.5 microseconds to draw a single line. This includes the time it takes to shut the electron beam off and reposition it back on the left edge one scan line below. The length of Vertical Blank is equivalent to 22 scan lines or roughly 1400 microseconds. With the Atari's 6502B CPU running at 1.79 MHz, 1400 microseconds is equivalent to approximately 2500 machine cycles (1400 X 1.79 = 2506). So, how much can you do "inside" the Vertical Blank period? Not very much, if you are trying to accomplish things like moving players and scrolling the screen solely inside the Vertical Blank period. The important thing to remember is that one television frame is 1/60th of a second, which is equivalent to 16,666 microseconds or just about 30,000 machine cycles. This means that there is a maximum of approximately 30,000 machine cycles BETWEEN Vertical Blanks. ANTIC delays processor time in order to fetch screen data and look up character data during the screen drawing process. A programmer using an extensive Vertical Blank Interrupt routine will want to be sure that the routine is finished before the next VBI occurs; otherwise, his routine will be aborted in the middle unless very special precautions are taken. A programmer will also want to be sure that his VBlank routine is not so long that it causes serious delays to the program code that is running outside VBlank.

      Programmers often ask if the 2500 cycle VBlank time constraint seriously limits the amount of time for smooth offscreen animation and updating. The answer is No! True, all of the graphics updating must be performed while the beam is offscreen, but you can also gain some additional time. Remember what a normal display list looks like. It begins with 24 blank lines. That gives 24 by 63.5 microseconds/line or another 2728 cycles that can be considered offscreen. High scores, player scores and messages generally cover the top few lines too. This adds additional time offscreen. Obviously if your Vertical Blank routine is even longer, you should be OK as long as you do all of your graphics updating within the first 5200 cycles of your routine. Figure that you have a maximum of 20,000 cycles (4500 instructions) in Deferred VBlank, but you must finish before the next VBI or your program will crash.

      While programmers have written entire games in Deferred VBlank, only certain operations should be put in VBlank. All graphics updating, including scrolling the screen, moving player-missile objects, and changing color registers, should definitely be done in VBlank. In addition, collisions should be checked, and joysticks or paddles should be read. This is also the best place to implement time critical sound routines. Everything else, including calculations, should be in your main code outside VBlank.

      ->link<-
      • 6:
         
        CommentAuthorMq
      • CommentTime20 May 2020 21:05
       
      Fajny opis. Czyli na dobrą sprawę można praktycznie całą grę napisać w przerwaniu VBlank:-)

      Zauważyłem, że jak się wrzuci dużą ilość kodu (praktycznie wszystko) w przerwanie vblank, to i tak wszystko śmiga elegancko. Jedyne co, to trzeba w pierwszej fazie przerwania zrobić krytyczne operacje graficzne, żeby zdążyć przed wyświetlaniem grafiki. W szczególności np. trzeba zdążyć przełączyć adresy kolejnych DLI jeśli mamy ich więcej, przescrollować ekran, żeby zachować płynność, czy zanimować elementy animowane żeby nadążyły za scrollingiem.

      Na wykresie performance w Altirra widać też, że jeśli przerwanie vbl trwa dłużej i leci jeszcze w trakcie wyświetlania juz następnej ramki, to przerwania DLI, które wystąpią w tym czasie otrzymują wyższy priorytet i przerywają wykonywanie przerwania od vblank, a po ich wykonaniu leci znów dalej sobie to niedokończone przerwanie vblank.

      Można sobie zrobić licznik w przerwaniu VBL np. do trzech, który zlicza ramki, i wtedy rozrzucić niektóre operacje i wykonywać je tylko w ramce o określonym numerku. W ten sposób można wydłużyć sobie ilość czasu dostępnego dla całego programu, a nadal pozostawić jego szybkość działania na tym samym poziomie, bo np. krytyczne operacje graficzne wykonujemy co ramkę, a sprawdzanie joysticka co trzy ramki, a np. jakieś liczenie punktów, albo obsługę odświeżania energii, albo przeliczanie jakichś rzeczy które nie muszą się dziać w czasie rzeczywistym możemy robić nawet co 10 ramek, lub po kawałku takie obliczenie kontynuować co ramkę tak długo jak to konieczne, żeby został jeszcze czas na inne rzeczy w każdej ramce.
      • 7: CommentAuthorzbyti
      • CommentTime21 May 2020 00:05 zmieniony
       
      @Mq dzięki za dorzucenie paru ciekawych informacji w temacie :]

      ;-----------------------------------------------------------

      Ok. Wiele problemów ze "środowiskiem Action!" już sobie rozwiązałem. Odkryłem także potrzebne mi sztuczki programistyczne i konstrukcje Action! Czas pchać grę dalej :]

      Na ten moment naiwna implementacja rysowania radaru. Będę to jeszcze poprawiał.

      EDIT: optymalizacja była szybka, "raster" wrócił na swoje miejsce ;)
      • 8: CommentAuthorzbyti
      • CommentTime21 May 2020 11:05 zmieniony
       

      Display List Interrupts:

      Display list interrupts are generally used to change the color registers midscreen or switch character sets in use. These changes can be made very rapidly since they are short and usually modify only a few bytes. Take care so that changes of this type are offscreen during Horizontal Blank, or they will appear crude and annoying. When ANTIC encounters the DLI instruction, it completes the last scan line for the mode it is drawing, then services the interrupt. This means in effect that the interrupt must be set during the mode line above the one you want the interrupt to effect.
      The period of Horizontal Blank is seven microseconds. Horizontal Overscan is another 3.31 microseconds. These 10.31 microseconds mean approximately eighteen machine cycles offscreen. In order for an interrupt routine to synchronize with Horizontal Blank, a special hardware register in ANTIC freezes the 6502 until Horizontal Blank occurs. Thi's register at $D40A is known as WSYNC. Writing to this location pulls down the ready line on the CPU until Horizontal Sync. If you insert a STA WSYNC instruction, then change the value in a color register, color won't be changed in The Middle of the current line but will go into effect when the beam is off the left edge of the screen one scan line lower.

      What if eighteen cycles are not enough time to make all the changes you need? There are several approaches that can be taken, and the proper one depends of course upon the situation.

      As with the VBI, you need not worry about crashing the program because the code does not fit in the Horizontal Blank time or even within the time it takes to do the entire scan line. Only if the code is so long that another DLI occurs before the previous one has finished would you be likely to run into problems and crash the program. There is no reason to believe that you must complete the interrupt routine by the end of the scan line. There are some programs that have one DLI set at the top of the screen and do not return from the interrupt until the entire screen has been drawn, hundreds of scan lines and thousands of machine cycles later. The interrupt routine is used to control graphics information to the screen, line by line. A DLI routine written in this manner is called a kernel.

      Programmers using DLI's for simple screen changes should decide if all of them must be made on a single line. Perhaps only a few changes need be made immediately. The rest can be made on the next line by waiting again for Horizontal Sync. All the changes must be made on a single line, if there is a major screen division between the score line and the playfield requiring different colors and character set. In this case, it might be practical to insert a zero in the display list. A zero is the blank line instruction in a display list. Changes could be made past Horizontal Blank on this line while the raster beam is drawing it and still be invisible to the viewer.

      There is one more important point for those readers who still need to count cycles. Although a horizontal line takes 63.5 microseconds, you do not have 113 cycles per line (63.5 x 1.79 = 113.6). This is because ANTIC's Direct Memory Access (DMA) ability allows it to freeze the 6502 CPU and steal cycles in order to get screen data from screen memory, player/missile data from player/missile memory, and to look up character set data. It even steals cycles to look at the display list so it knows what type of information to display. The amount of time stolen per scan line can vary. ANTIC steals a cycle for each byte in memory it must access. This DMA is controlled by a hardware register called DMACTL at $D400 (54272 decimal). The OS VBlank routine rewrites the value found at its shadow (SDMCTL) at $22F (559 decimal) every VBI. By setting bits in SDMCTL, the program can control screen width from either 128, 160, or 228 color clocks. Selecting screen width tells ANTIC it may steal cycles from the 6502 to access the display list and screen memory in order to display information. Bits are also set here so that ANTIC may steal cycles to look up player and/or missile data in memory.

      Kernels
      A kernel is a special DLI routine designed to control graphics information on a line-by-line basis for the entire screen. It does this by monitoring the VCOUNT (vertical line counter) register. The most frequent use is for producing multi-colored players. Even the player width can be changed on a line-by-line basis. For example, a cowboy image could be made out of one player; a broad white hat defined at double width changes a few scan lines down to a slim pink face, then changes a few scan lines down to a brown cowboy suit and finally to black boots; four colors and two different resolutions in a single player. Another example is the players in Atari's Basketball cartridge. You cannot create multi-colored players like these without Display List Interrupts because DLI's are keyed to playfield vertical positions, not player positions.
      Kernels are difficult to use because graphics information changes only during Horizontal Blank. Kernels also drastically reduce the amount of time available for program logic, since most of the 6502's time is spent writing graphics information and waiting for Horizontal Sync on the next line. Since virtually no computation time is available during display time, and only about 4000 cycles are available during Vertical Blank and overscan time, kernels are limited to simple skill and action games.

      ->link<-

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

      PAGE ZERO w pigułce ->link<- ->link<-

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

      Strona zerowa w grze Seaquest

      ; $81 = frame counter
      ; $82 = random number seed
      ; $85 = attract mode XOR mask
      ; $86 = attract mode AND mask
      ; $87 = player 1 color
      ; $88 = player 2 color
      ; $89 = water color
      ; $8A = player 1 underwater color
      ; $8B = player 2 underwater color
      ; $8C = header color
      ; $8D = water color #2
      ; $8E = oxygen bar color
      ; $8F = sea bed color
      ; $90 = used up O2 bar color
      ; $91 = logo and diver color
      ; $92,$93 = score digit 1 temp
      ; $94,$95 = score digit 2 temp
      ; $96,$97 = score digit 3 temp
      ; $98,$99 = score digit 4 temp, player sub graphics pointer
      ; $9A,$9B = score digit 5 temp
      ; $9C,$9D = score digit 6 temp
      ; $9E-A1 = enemy positions
      ; $A2 = attract counter (inc on $81 rollover, cleared on movement)
      ; $A4-A7 = enemy repeat flags
      ; D2 = 1 left
      ; D1 = 1 middle
      ; D0 = 1 right
      ; $A8-AB = visible enemy repeat flags
      ; $AC-AF = shark/sub colors
      ; $B0-B3 = diver hurry-up flags
      ; $B4 = row index of enemy hit by missile ($FF = none)
      ; $B5 = row index of enemy hit by player ($FF = none)
      ; $B6 = row index of diver rescued by player ($FF = none)
      ; $B7 = current player (0/1)
      ; $B8 = score hi byte
      ; $B9 = score med byte
      ; $BA = score low byte
      ; $BB = lives left
      ; $BD = wave (0+)
      ; $BE = diver count (0-6)
      ; $BF = other player score hi byte
      ; $C0 = other player score med byte
      ; $C1 = other player score low byte
      ; $C6 = player horizontal position
      ; $C7-CA = diver/shot horizontal position
      ; $CE = shark/sub point value
      ; $D6 = player reflect bit (bit 3)
      ; $D9-DC = enemy flags
      ; D4 = 1 diver present
      ; D3 = 1 reflect horizontally
      ; D0-D2 shark/sub frame
      ; $DD = shark vertical offset (0-7)
      ; $E0 = player sub frame
      ; $E1 = player vertical location
      ; $E6 = O2 level (0-64)
      ; $E7 = player missile position
      ; $E8 = victory flags
      ; 0 normal
      ; 1 refilling (NOT when surfacing with less than 6 divers)
      ; 6 awarding points for remaining O2
      ; $E9 = death effect downcounter
      ; $EA = diver sound effect counter
      ; $F6 = enemy patrol boat position
      ; $F8 = player/enemy collision byte
      • 9: CommentAuthorzbyti
      • CommentTime21 May 2020 15:05 zmieniony
       
      Action! TIP

      Jeżeli zależy nam na szybkości (kosztem zajętego miejsca w RAM) to w Action! unikajmy pętli jeżeli możemy to zrobić inaczej.

      Mad Pascal ma tutaj ogromną przewagę nad Action! zwłaszcza jeżeli iterujemy się po typie CARD.

      Szybki kod
      SCREEN(SCREENI+$150)=0
      SCREEN(SCREENI+$120)=0
      SCREEN(SCREENI+$F0)=0
      SCREEN(SCREENI+$C0)=0
      SCREEN(SCREENI+$90)=0
      SCREEN(SCREENI+$60)=0
      SCREEN(SCREENI+$30)=0
      SCREEN(SCREENI)=0

      Wolny kod
      FOR CTMP1=0 TO $150 STEP $30 DO
      SCREEN(SCREENI+CTMP1)=0
      OD

      Różnica na poniższych zrzutach.
      • 10: CommentAuthorzbyti
      • CommentTime21 May 2020 18:05 zmieniony
       
      ; wizualne porównanie czasu pracy procedur

      RSYNC(50)
      [RASTERBARON]
      SCREEN(SCREENI+$150)=0
      SCREEN(SCREENI+$120)=0
      SCREEN(SCREENI+$F0)=0
      SCREEN(SCREENI+$C0)=0
      SCREEN(SCREENI+$90)=0
      SCREEN(SCREENI+$60)=0
      SCREEN(SCREENI+$30)=0
      SCREEN(SCREENI)=0
      [RASTERBAROFF]

      RSYNC(60)
      [RASTERBARON]
      CTMP1=SCREENI DO
      SCREEN(CTMP1)=0
      CTMP1==+$30
      UNTIL CTMP1=SCREENI+$150
      OD
      [RASTERBAROFF]

      RSYNC(70)
      [RASTERBARON]
      FOR CTMP1=0 TO $150 STEP $30 DO
      SCREEN(SCREENI+CTMP1)=0
      OD
      [RASTERBAROFF]



      Wygląda jak miejsce na optymalizację ;) bo czyszczenie kolumny to ~50% czasu procedury generującej teren.
      • 11: CommentAuthorzbyti
      • CommentTime21 May 2020 22:05 zmieniony
       
      No to zabieramy się za optymalizacje Action!

      "Szybki" kod bez wstawek ASM ale obszerny
      SCREEN(SCREENI+$150)=0
      SCREEN(SCREENI+$120)=0
      SCREEN(SCREENI+$F0)=0
      SCREEN(SCREENI+$C0)=0
      SCREEN(SCREENI+$90)=0
      SCREEN(SCREENI+$60)=0
      SCREEN(SCREENI+$30)=0
      SCREEN(SCREENI)=0

      112E: 18 CLC
      112F: A5 5E LDA $5E ;OLDADR
      1131: 69 50 ADC #$50
      1133: 85 AE STA $AE ;LELNUM+1
      1135: A5 5F LDA $5F ;OLDADR+1
      1137: 69 01 ADC #$01
      1139: 85 AF STA $AF ;STENUM
      113B: 18 CLC
      113C: AD 0C 0E LDA $0E0C
      113F: 65 AE ADC $AE ;LELNUM+1
      1141: 85 AC STA $AC ;EXSVPR
      1143: AD 0D 0E LDA $0E0D
      1146: 65 AF ADC $AF ;STENUM
      1148: 85 AD STA $AD ;LELNUM
      114A: A9 00 LDA #$00
      114C: A0 00 LDY #$00
      114E: 91 AC STA ($AC),Y ;EXSVPR
      1150: 18 CLC
      1151: A5 5E LDA $5E ;OLDADR
      1153: 69 20 ADC #$20
      1155: 85 AE STA $AE ;LELNUM+1
      1157: A5 5F LDA $5F ;OLDADR+1
      1159: 69 01 ADC #$01
      115B: 85 AF STA $AF ;STENUM
      115D: 18 CLC
      115E: AD 0C 0E LDA $0E0C
      1161: 65 AE ADC $AE ;LELNUM+1
      1163: 85 AC STA $AC ;EXSVPR
      1165: AD 0D 0E LDA $0E0D
      1168: 65 AF ADC $AF ;STENUM
      116A: 85 AD STA $AD ;LELNUM
      116C: A9 00 LDA #$00
      116E: 91 AC STA ($AC),Y ;EXSVPR
      1170: 18 CLC
      1171: A5 5E LDA $5E ;OLDADR
      1173: 69 F0 ADC #$F0
      1175: 85 AE STA $AE ;LELNUM+1
      1177: A5 5F LDA $5F ;OLDADR+1
      1179: 69 00 ADC #$00
      117B: 85 AF STA $AF ;STENUM
      117D: 18 CLC
      117E: AD 0C 0E LDA $0E0C
      1181: 65 AE ADC $AE ;LELNUM+1
      1183: 85 AC STA $AC ;EXSVPR
      1185: AD 0D 0E LDA $0E0D
      1188: 65 AF ADC $AF ;STENUM
      118A: 85 AD STA $AD ;LELNUM
      118C: A9 00 LDA #$00
      118E: 91 AC STA ($AC),Y ;EXSVPR
      1190: 18 CLC
      1191: A5 5E LDA $5E ;OLDADR
      1193: 69 C0 ADC #$C0
      1195: 85 AE STA $AE ;LELNUM+1
      1197: A5 5F LDA $5F ;OLDADR+1
      1199: 69 00 ADC #$00
      119B: 85 AF STA $AF ;STENUM
      119D: 18 CLC
      119E: AD 0C 0E LDA $0E0C
      11A1: 65 AE ADC $AE ;LELNUM+1
      11A3: 85 AC STA $AC ;EXSVPR
      11A5: AD 0D 0E LDA $0E0D
      11A8: 65 AF ADC $AF ;STENUM
      11AA: 85 AD STA $AD ;LELNUM
      11AC: A9 00 LDA #$00
      11AE: 91 AC STA ($AC),Y ;EXSVPR
      11B0: 18 CLC
      11B1: A5 5E LDA $5E ;OLDADR
      11B3: 69 90 ADC #$90
      11B5: 85 AE STA $AE ;LELNUM+1
      11B7: A5 5F LDA $5F ;OLDADR+1
      11B9: 69 00 ADC #$00
      11BB: 85 AF STA $AF ;STENUM
      11BD: 18 CLC
      11BE: AD 0C 0E LDA $0E0C
      11C1: 65 AE ADC $AE ;LELNUM+1
      11C3: 85 AC STA $AC ;EXSVPR
      11C5: AD 0D 0E LDA $0E0D
      11C8: 65 AF ADC $AF ;STENUM
      11CA: 85 AD STA $AD ;LELNUM
      11CC: A9 00 LDA #$00
      11CE: 91 AC STA ($AC),Y ;EXSVPR
      11D0: 18 CLC
      11D1: A5 5E LDA $5E ;OLDADR
      11D3: 69 60 ADC #$60
      11D5: 85 AE STA $AE ;LELNUM+1
      11D7: A5 5F LDA $5F ;OLDADR+1
      11D9: 69 00 ADC #$00
      11DB: 85 AF STA $AF ;STENUM
      11DD: 18 CLC
      11DE: AD 0C 0E LDA $0E0C
      11E1: 65 AE ADC $AE ;LELNUM+1
      11E3: 85 AC STA $AC ;EXSVPR
      11E5: AD 0D 0E LDA $0E0D
      11E8: 65 AF ADC $AF ;STENUM
      11EA: 85 AD STA $AD ;LELNUM
      11EC: A9 00 LDA #$00
      11EE: 91 AC STA ($AC),Y ;EXSVPR
      11F0: 18 CLC
      11F1: A5 5E LDA $5E ;OLDADR
      11F3: 69 30 ADC #$30
      11F5: 85 AE STA $AE ;LELNUM+1
      11F7: A5 5F LDA $5F ;OLDADR+1
      11F9: 69 00 ADC #$00
      11FB: 85 AF STA $AF ;STENUM
      11FD: 18 CLC
      11FE: AD 0C 0E LDA $0E0C
      1201: 65 AE ADC $AE ;LELNUM+1
      1203: 85 AC STA $AC ;EXSVPR
      1205: AD 0D 0E LDA $0E0D
      1208: 65 AF ADC $AF ;STENUM
      120A: 85 AD STA $AD ;LELNUM
      120C: A9 00 LDA #$00
      120E: 91 AC STA ($AC),Y ;EXSVPR
      1210: 18 CLC
      1211: AD 0C 0E LDA $0E0C
      1214: 65 5E ADC $5E ;OLDADR
      1216: 85 AE STA $AE ;LELNUM+1
      1218: AD 0D 0E LDA $0E0D
      121B: 65 5F ADC $5F ;OLDADR+1
      121D: 85 AF STA $AF ;STENUM
      121F: A9 00 LDA #$00
      1221: 91 AE STA ($AE),Y ;LELNUM+1

      Wolny kod bez wstawek ASM
      FOR CTMP1=0 TO $150 STEP $30 DO
      SCREEN(SCREENI+CTMP1)=0
      OD

      1126: A0 00 LDY #$00
      1128: 84 62 STY $62 ;PALNTS
      112A: 84 61 STY $61 ;FKDEF+1
      112C: A9 50 LDA #$50
      112E: C5 61 CMP $61 ;FKDEF+1
      1130: A9 01 LDA #$01
      1132: E5 62 SBC $62 ;PALNTS
      1134: B0 03 BCS $1139
      1136: 4C 6B 11 JMP $116B
      1139: 18 CLC
      113A: A5 5E LDA $5E ;OLDADR
      113C: 65 61 ADC $61 ;FKDEF+1
      113E: 85 AE STA $AE ;LELNUM+1
      1140: A5 5F LDA $5F ;OLDADR+1
      1142: 65 62 ADC $62 ;PALNTS
      1144: 85 AF STA $AF ;STENUM
      1146: 18 CLC
      1147: AD 0C 0E LDA $0E0C
      114A: 65 AE ADC $AE ;LELNUM+1
      114C: 85 AC STA $AC ;EXSVPR
      114E: AD 0D 0E LDA $0E0D
      1151: 65 AF ADC $AF ;STENUM
      1153: 85 AD STA $AD ;LELNUM
      1155: A9 00 LDA #$00
      1157: A0 00 LDY #$00
      1159: 91 AC STA ($AC),Y ;EXSVPR
      115B: 18 CLC
      115C: A5 61 LDA $61 ;FKDEF+1
      115E: 69 30 ADC #$30
      1160: 85 61 STA $61 ;FKDEF+1
      1162: A5 62 LDA $62 ;PALNTS
      1164: 69 00 ADC #$00
      1166: 85 62 STA $62 ;PALNTS
      1168: 4C 2C 11 JMP $112C

      "Szybki" tak jak pierwszy, ze wstawką ASM - podstawa do optymalizacji
      CTMP2=STARTSCREEN+SCREENI
      FOR BTMP1=0 TO 7 DO
      [$A9$0$A0$00$91$CC]
      CTMP2==+$30
      OD

      112E: 18 CLC
      112F: A9 00 LDA #$00
      1131: 65 5E ADC $5E ;OLDADR
      1133: 85 CC STA $CC
      1135: A9 80 LDA #$80
      1137: 65 5F ADC $5F ;OLDADR+1
      1139: 85 CD STA $CD
      113B: A0 00 LDY #$00
      113D: 84 CA STY $CA ;LOADFLG
      113F: A9 07 LDA #$07
      1141: C5 CA CMP $CA ;LOADFLG
      1143: B0 03 BCS $1148
      1145: 4C 60 11 JMP $1160
      1148: A9 00 LDA #$00
      114A: A0 00 LDY #$00
      114C: 91 CC STA ($CC),Y
      114E: 18 CLC
      114F: A5 CC LDA $CC
      1151: 69 30 ADC #$30
      1153: 85 CC STA $CC
      1155: A5 CD LDA $CD
      1157: 69 00 ADC #$00
      1159: 85 CD STA $CD
      115B: E6 CA INC $CA ;LOADFLG
      115D: 4C 3F 11 JMP $113F
      1160: 00 BRK
      • 12: CommentAuthorzbyti
      • CommentTime22 May 2020 02:05 zmieniony
       
      OK. Wykonałem optymalizację kasowania prawej kolumny ekranu.

      CTMP2=STARTSCREEN+SCREENI
      [
      $A2$07$A9$00$A8$91$CC$18
      $A5$CC$69$30$85$CC$A5$CD$69$00
      $85$CD$CA$10$EB
      ]

      ; CTMP2=STARTSCREEN+SCREENI
      1126: 18 CLC
      1127: A9 00 LDA #$00
      1129: 65 5E ADC $5E
      112B: 85 CC STA $CC
      112D: A9 80 LDA #$80
      112F: 65 5F ADC $5F
      1131: 85 CD STA $CD

      ; moj kod w ASM
      1133: A2 07 LDX #$07
      1135: A9 00 LDA #$00
      1137: A8 TAY
      1138: 91 CC STA ($CC),Y
      113A: 18 CLC
      113B: A5 CC LDA $CC
      113D: 69 30 ADC #$30
      113F: 85 CC STA $CC
      1141: A5 CD LDA $CD
      1143: 69 00 ADC #$00
      1145: 85 CD STA $CD
      1147: CA DEX
      1148: 10 EB BPL $1135

      @mono zaproponował skrócenie powyższego kodu, można zyskać jeszcze 3 cykle.

      1133: A2 07     LDX #$07
      1135: A9 00 LDA #$00
      1137: A8 TAY
      1138: 91 CC STA ($CC),Y
      113A: 18 CLC
      113B: A5 CC LDA $CC
      113D: 69 30 ADC #$30
      113F: 85 CC STA $CC
      1141: 90 02 BCC $1145
      1143: E6 CD INC $CD
      1145: CA DEX
      1146: 10 ED BPL $1135
      • 13:
         
        CommentAuthorKaz
      • CommentTime22 May 2020 02:05
       
      Bardzo ładnie i szybko :)
      • 14: CommentAuthorpaw
      • CommentTime22 May 2020 09:05 zmieniony
       
      Ten wątek rozwija się dokładnie tak jak moja nauka programowania w cc65, w pewnym momencie było więcej wstawek w asemblerze niż kodu w c.

      A w powyższym kodzie można jeszcze wykorzystać, że Y się nie zmienia:
      LDX #$07
      LDY #$00
      tu
      TYA
      STA ($CC),Y
      CLC
      LDA $CC
      ADC #$30
      STA $CC
      BCC tam
      INC $CD
      tam
      DEX
      BPL tu
      • 15: CommentAuthorzbyti
      • CommentTime22 May 2020 13:05 zmieniony
       
      @paw dobra optymalizacja, o 2 nad ranem mi umknęło :]

      Na razie w kodzie który "pracuje" (DLI pomijam) jest tylko jedna wstawka ;)

      Rzecz w tym, że ja się uczę Atari w ogóle, gra będzie efektem ubocznym.

      Jak widać po jakości kodu wynikowego kompilatora Action! to albo Guremu uda się napisać Effectusa albo będę uciekał w inne języki pomimo mojej sympatii do Action! :]

      Z resztą to ponoć ogólna praktyka, że krytyczne miejsca w kodzie, także w CC65, Mad Pascalu itd. przepisuje się na ASM :)
      • 16:
         
        CommentAuthorMq
      • CommentTime22 May 2020 14:05
       
      @zbyti, jest tak dlatego, że Atari to ośmiobitowiec z 64k pamięci i ekranem, który już sam w sobie pochłania jej całkiem sporo. Na takim sprzęcie, na którym trzeba bezpośrednio operować komórkami pamięci i rejestrami specjalizowanych układów, żeby wykorzystać ich możliwości, w językach wyższego poziomu można sobie pisać programy typu podaj swoje imię ile masz lat i takie tam obliczenia A+B. Jak piszesz grę, to musisz odwoływać się do sprzętu, a wtedy traci sens unikanie assemblera.
      W Mad Pascalu można pisać procedury obsługi przerwań w Pascalu. Ale żeby one zadziałały, to i tak musisz "myśleć po sprzętowemu", a więc ułożyć taki kod w Pascalu, który będzie sprawnie operował sprzętem. Krótko mówiąc zauważyłem, że piszę w Pascalu, ale myślę w assemblerze i składam kod Pascala tak, żeby wygenerował mi się później z niego dobry assembler:-)
      Tylko że Mad Pascal umie wtedy dobrze to zrobić, czy Action potrafi? Tego nie wiem. Ale zapewne spece od Action wiedzą jak taki kod pisać, tylko że tu wracamy do punktu wyjścia, że tego assemblera nie da się uniknąć.
      A jak ktoś nie zna dobrze sprzętu, nie zna choćby podstaw assemblera i nie umie "myśleć po sprzętowemu", to nie zrobi dobrego kodu do np. dynamicznej gry w żadnym języku wysokiego poziomu.
      Czyli dochodzimy do wniosku, że nawet jeśli ktoś pisze grę w języku wyższego poziomu, to prawdopodobnie zna też przynajmniej częściowo assemblera, więc nieraz odruchowo napisze w nim wstawki, żeby się nie męczyć.
      • 17: CommentAuthorzbyti
      • CommentTime22 May 2020 15:05 zmieniony
       

      Mq:

      Mad Pascal umie wtedy dobrze to zrobić, czy Action potrafi? Tego nie wiem. Ale zapewne spece od Action wiedzą jak taki kod pisać, tylko że tu wracamy do punktu wyjścia, że tego assemblera nie da się uniknąć.

      Ale ja wiem, wynik kompilacji sprawdzam regularnie ;D

      - Właśnie miałeś przykład pętli FOR + STEP, DO OD i korzystania z tablicy wraz z porównaniem prędkości i długości kodu wynikowego.

      - W innych miejscach publikowałem WHILE i inne popularne konstrukcje.

      - "spece od Action!" - powoli jestem już jednym z nich, więc możesz polegać na moich opiniach o Action! ;)

      - Action! jest kompilatorem jednego przebiegu więc cudów nie będzie.

      Tyle @tdc naopowiadał o przewagach Action!, że ktoś w końcu musiał się poświęcić i to sprawdzić :D
      • 18: CommentAuthorzbyti
      • CommentTime22 May 2020 16:05 zmieniony
       
      Kolejna optymalizacja:

      ; old code
      DEFINE
      DRAWROW="MATRIX(SCREENI+ROWOFFSET(ROW))",
      DRAWNEXTROW="MATRIX(SCREENI+ROWOFFSET(NEXTROW))"

      IF ROW=6 THEN
      IF TILE=3 THEN
      DRAWROW=GLADE RET
      ELSE
      NEXTROW=5
      DRAWROW=RSLOPE
      DRAWNEXTROW=RFILL
      RET
      FI
      FI

      ; new code
      IF ROW=6 THEN
      IF TILE=3 THEN
      POKE(SCREENI,GLADE) RET
      ELSE
      ROW=5
      POKE(SCREENI,RSLOPE)
      SCREENI==+$30
      POKE(SCREENI,RFILL)
      RET
      FI
      FI

      Oszczędność:
      - krótszy kod wynikowy
      - nie sięgam 2x do tablicy OFFSET
      - oszczędzam jedno dodawanie na CARD

      Koszt:
      - procedura czyszcząca prawą kolumnę musi każdorazowo wyliczyć swoje położenie, ale zaleta taka, że robi to tylko jedno dodawanie bez odwoływania się to OFFSET

      Sądzę, że jeszcze uproszczę pierwszą naiwną implementację generowania terenu ale już jest sporo lepiej :]
      • 19:
         
        CommentAuthorMq
      • CommentTime22 May 2020 17:05
       
      - "spece od Action!" - powoli jestem już jednym z nich, więc możesz polegać na moich opiniach o Action! ;)


      @zbyti, nie dopisuję tu za dużo, bo nie znam się na Action, ale akurat jak wiesz robię niektóre podobne rzeczy w swojej grze w Mad Pascalu, więc temat nam się zazębia, stąd trochę się wtrącam:-)
      Traktuję Twój wątek jako bardzo fajną kopalnię wiedzy, czytam od dechy do dechy, bo czasem coś tam się trafi czego nie wiedziałem, albo czasem sam coś dopowiem skoro zaobserwowałem:-)
      Natomiast po sposobie prowadzenia przez Ciebie tego projektu od samego początku aż do teraz, mam pełne zaufanie do fachowości tego co tu opisujesz:-)
      • 20: CommentAuthorzbyti
      • CommentTime22 May 2020 17:05
       
      @Mq a ja bardzo sobie cenię Twoje wpisy w tym wątku i w wątku o "Kolesiu" - są bardzo merytoryczne :]
      • 21: CommentAuthorzbyti
      • CommentTime22 May 2020 18:05 zmieniony
       
      Po ostatnich zmianach (do zobaczenia na github) zanotowałem znaczny spadek objętości kodu, przy poprawie jego wydajności :]

      Na screenie można zobaczyć jak pracują DLI i LMS w DL, ale najlepiej "na żywo" w 65xedebugger :D

      • 22:
         
        CommentAuthorMq
      • CommentTime22 May 2020 19:05 zmieniony
       
      @zbyti, Twoje zrzuty ekranów zachęciły mnie do odpalenia tego debugera. Ściągnąłem go sobie, ale nie mogę za cholerę odpalić tego. Jak to zrobić? Mógłbyś opisać krok po kroku zupełne podstawy:
      - jak wczytać xex-a
      - jak go uruchomić
      - i może dosłownie ze dwa słowa o najczęściej używanych opcjach, np. jak zafreezować, czy tam zrobić jakieś breakpointy czy coś
      Ogólnie nie chodzi mi o pełen podręcznik, tylko kilka podstaw w paru zdaniach, bo w instrukcji jest opisane jak wczytywać pliki od c64, ale analogiczną drogą z plikami xex nic się nie dzieje i nie mogę tego w ogóle uruchomić, a pewnie rzecz jest trywialna:-)
      • 23: CommentAuthorzbyti
      • CommentTime22 May 2020 20:05 zmieniony
       
      @Mq na ten moment tylko mogę pomóc Ci to uruchomić, używasz z linii poleceń by wgrać XEX, lub z menu programu, działa tak jak Atari800, tylko klawiszologia lekko zmieniona.

      ./65xedebugger SCRAMBLE.XEX

      Problemem może być u Ciebie to, że domyślne program startuje z Atari (chyba) 800 48KB, musisz to sobie zmienić.

      Opisałem to tutaj ->link<-

      Więcej szczegółów nie znam, jak zacznę częściej używać to opiszę.
      • 24:
         
        CommentAuthorMq
      • CommentTime22 May 2020 21:05
       
      Dzięki, o to chodziło. F9 załatwia temat, nie trafiłem na to, wiedziałem, że coś trywialnego jest na rzeczy.
      Następnie trzeba ustawić Atari 800XL (czy tam inny jaki się chce, bo domyślnie jest A400 i 16k RAM) oraz ścieżkę do ROM-u.
      Po zrestartowaniu programu wszystko śmiga.
      xex-a ładuje się z poziomu menu F9 lub Ctrl+O.
      • 25: CommentAuthorpaw
      • CommentTime23 May 2020 20:05
       
      @Zbyti
      staram się nie zostawać w tyle i co ciekawe bardzo mi to ułatwiasz wprowadzając rozwiązania bliźniaczo podobne do moich i nie mam na myśli dli,
      źródła: ->link<-
      • 26: CommentAuthorzbyti
      • CommentTime23 May 2020 20:05 zmieniony
       
      @paw dzięki za źródła, chętnie je "przeczytam"!

      Skoro wprowadzam rozwiązania bliźniacze do Twoich to jest to fajna koincydencja :] Ale to znaczy, że masz moje optymalizacje przede mną :D To dobrze świadczy o Twoich umiejętnościach :)

      Ja się na razie trzymam modelu: naiwna implementacja, optymalizacja, powtórz krok :]

      Widzę, że stosujesz tę poradę:
      ANTIC.nmien = NMIEN_DLI | NMIEN_VBI;

      Rozważałem to dziś po przeczytaniu tutka @Yaron Nir ->link<-
      • 27: CommentAuthorzbyti
      • CommentTime23 May 2020 21:05 zmieniony
       
      Podpatrzyłem u @paw stary trick, więc niezwłocznie wprowadziłem ;)

      BYTE ARRAY
      SHIPSBODYTABLE=[1 1 3 3 5],
      SHIPSHEADTABLE=[2 4 4 6 6]

      PROC DRAWROCKET=*()
      SHIPTYPE=RANDOM & 15
      IF SHIPTYPE>4 THEN RET FI
      POKE(SCREENI-$30,SHIPSBODYTABLE(SHIPTYPE))
      POKE(SCREENI-$60,SHIPSHEADTABLE(SHIPTYPE))
      RET

      Co eliminuje niepotrzebne dodawanie gdy dane rakiety były w jednej tablicy.
      • 28: CommentAuthorpaw
      • CommentTime23 May 2020 22:05
       
      Nie przesadzajmy z moimi umiejętnościami,
      podstawowa wiedza o trybach adresowania, parę "tricków" i wyłączenie systemu to podstawa moich dokonań.
      Publikując kod chciałem pokazać że asembler nie jest taki straszny jak go malują. Może dodam do kodu trochę więcej od siebie aczkolwiek z zastrzeżeniem, że niekoniecznie jest to właściwa metoda programowania.

      I mam podobny model, tylko w miejscu optymalizacji u mnie jest usuwanie błędów.
      • 29: CommentAuthorzbyti
      • CommentTime23 May 2020 22:05 zmieniony
       
      @paw masz racje, czytelność Twojego kodu jest dla mnie duża i faktycznie w Twoim wydaniu ASM nie wygląda tak strasznie, zwłaszcza jak w komentarzu dajesz kawałki kodu Action! i jego implementację w ASM - tak trzymaj! :]

      Tymczasem w końcu widzę zastosowanie dla POKEC ;)

      Kolejna prosta optymalizacja, pozbywamy się dwóch odejmowań na CARD.

      ; old
      PROC DRAWCANNON=*()
      POKE(SCREENI-$32,27)
      POKE(SCREENI-$62,0)
      POKE(SCREENI-$31,28)
      POKE(SCREENI-$61,0)
      POKE(SCREENI-$30,29)
      POKE(SCREENI-$60,30)
      RET

      ; new
      POKEC(SCREENI-$32,$1C1B)
      POKEC(SCREENI-$62,0)
      POKE(SCREENI-$30,29)
      POKE(SCREENI-$60,30)
      RET
      • 30: CommentAuthorzbyti
      • CommentTime24 May 2020 00:05 zmieniony
       
      Teraz już naprawdę przyspieszyłem procedurę TERRAIN :D

      CARD
      SCREENI=$5E, ; REUSED OLDADR
      CTMP1=$CA

      ;----------------------------------------------------------
      ; DRAW TERRAIN CHAR
      ;----------------------------------------------------------
      PROC TPoke=*(BYTE v)
      [$A0$00$91$5E$60]
      ; 0E6D: A0 00 LDY #$00
      ; 0E6F: 91 5E STA ($5E),Y ;OLDADR
      ; 0E71: 60 RTS

      ;----------------------------------------------------------
      ; DRAW BUILDINGS CHAR
      ;----------------------------------------------------------
      PROC BPoke=*(BYTE v)
      [$A0$00$91$CA$60]
      ; 0E72: A0 00 LDY #$00
      ; 0E74: 91 CA STA ($CA),Y ;LOADFLG
      ; 0E76: 60 RTS

      ;----------------------------------------------------------
      ; DRAW BUILDINGS TWO CHARS
      ;----------------------------------------------------------
      PROC BPokeC=*(CARD v)
      [$A0$00$91$CA$C8$8A$91$CA$60]
      ; 0E77: A0 00 LDY #$00
      ; 0E79: 91 CA STA ($CA),Y ;LOADFLG
      ; 0E7B: C8 INY
      ; 0E7C: 8A TXA
      ; 0E7D: 91 CA STA ($CA),Y ;LOADFLG
      ; 0E7F: 60 RTS

      ;----------------------------------------------------------
      ; PROCEDURE DRAWS ION CANNON STRUCTURE
      ;----------------------------------------------------------
      PROC DRAWCANNON=*()
      CTMP1=SCREENI-$32 BPOKEC($1C1B)
      CTMP1=SCREENI-$62 BPOKEC(0)
      CTMP1=SCREENI-$30 BPOKE(29)
      CTMP1=SCREENI-$60 BPOKE(30)
      RET

      Sztuczka polega na tym, że użycie bibliotecznego POKE
      POKE(SCREENI-$30,29)

      skutkowało kodem którym pracował według algorytmu:

      1. wylicz SCREENI-$30 i wstaw wynik typu CARD do $a0 i $a1
      2. wczytaj wartość $a0, $a1 i wstaw do rejestru A i X, do Y wstaw drugi parametr
      3. skocz (JSR) do procedury POKE z załadowanym AXY
      4. POKE zrzucał A i X do $a0 i $a1 i dopiero robił właściwą pracę

      Ja pominąłem w nowym POKE w pkt.2 LDA i LDX a w pkt.4 STA i STX.

      To tyle na temat rysowania rakiet i budynków.

      W POKE do rysowania terenu nie przekazuję adresu w którym aktualnie należy postawić znak tylko korzystam z tego, że wiem pod jakim adresem jest właściwa wartość.
      • 31: CommentAuthorzbyti
      • CommentTime24 May 2020 01:05 zmieniony
       
      Po lewej Action! ze wstawkami ML (nowy POKE) a po prawej ASM.

      @PAW dajesz! Przyspieszamy! :D



      Glitch na ekranie z wersją w Action! to nieszczęśliwy moment zrobienia screenshota.

      Co prawda mi raster trochę skacze a u @paw jest stały ale nawet gdy mój w kod wpada we wszystkie IF-y to i tak zabiera mniej cykli :]
      • 32: CommentAuthorpaw
      • CommentTime24 May 2020 15:05
       
      @zbyti
      ok, daję, na githubie nowa wersja
      prawdopodobieństwo pojawienia się "cannon" odrobinę zmalało ale powinno być dużo szybciej

      Aczkolwiek obawiam się, że moja obecna metoda nie ma długiej przyszłości, może rozpoczniemy negocjacje by ograniczyć liczbę wierszy z terenem do 6?

      i coś niepokojącego się dzieje z kolorami po dłużej pracy twojej wersji
      • 33: CommentAuthorzbyti
      • CommentTime24 May 2020 15:05 zmieniony
       
      @paw fajnie, zaraz obadam Twoją nową wersję.

      Ja też właśnie wrzuciłem na GitHub nowe optymalizacje, pozbyłem się z kodu kilku IF-ów, więc też powinno być szybciej.

      Co do zmiany kolorów w mojej wersji to nie zaobserwowałem czegoś takiego, a oglądałem do 3-4 pełnych przebiegów, polecam odpalić na nowszej wersji emulatora 4.2.0.

      Do tego Atari800 jak go nie dotykasz ma jakiś "attract mode" i zmienia kolory ekranu, może to zaobserwowałeś?

      Liczba wierszy z terenem wynosi 7, jeden mniej robi różnicę?

      EDIT: odpaliłem Twoją nową wersję. Gratuluję znacznego przyspieszenia! :]
      • 34: CommentAuthorzbyti
      • CommentTime24 May 2020 16:05 zmieniony
       
      Kolejne porównanie, tym razem @paw na prowadzeniu, ale i tak jestem zadowolony z tego co udało mi się wycisnąć z Action! :]

      Po lewej Action! po prawej ASM:



      Oczywiście raster nie jest stały, wersja ASM zazyczaj pracuje "oszczędniej" ale pik dla każdego programu wygląda mniej więcej tak jak na zrzucie (poza jednym momentem gdzie ASM skacze doganiając mój raster).

      Ciekawe jak się tam ma wersja w Mad Pascalu? ;)
      • 35: CommentAuthorzbyti
      • CommentTime24 May 2020 17:05 zmieniony
       
      Ciekawe jak zrobić w Action! szybsze sięganie po element tablicy?

      Znów mam trochę nadmiarowego kodu po kompilacji.

      Chyba ostatnie miejsce do optymalizacji w moim obecnym kodzie, trzeba jakoś oszukać kompilator Action!, ale nie wiem jeszcze jak to zrobię i czy w ogóle :>

      SHIPTYPE=RANDOM & 15
      IF SHIPTYPE>4 THEN RET FI
      POKEADDR=SCREENI-$30 ELMPOKE(SHIPSBODY(SHIPTYPE))

      0F11: AD 0A D2 LDA $D20A ;RANDOM
      0F14: 29 0F AND #$0F
      0F16: 85 60 STA $60 ;FKDEF
      0F18: A9 04 LDA #$04
      0F1A: C5 60 CMP $60 ;FKDEF
      0F1C: 90 03 BCC $0F21
      0F1E: 4C 22 0F JMP $0F22
      0F21: 60 RTS

      0F22: 38 SEC
      0F23: A5 5E LDA $5E ;OLDADR
      0F25: E9 30 SBC #$30
      0F27: 85 CA STA $CA ;LOADFLG
      0F29: A5 5F LDA $5F ;OLDADR+1
      0F2B: E9 00 SBC #$00
      0F2D: 85 CB STA $CB

      0F2F: 18 CLC
      0F30: AD 4F 0E LDA $0E4F
      0F33: 65 60 ADC $60 ;FKDEF
      0F35: 85 AE STA $AE ;LELNUM+1
      0F37: AD 50 0E LDA $0E50
      0F3A: 69 00 ADC #$00
      0F3C: 85 AF STA $AF ;STENUM
      0F3E: A0 00 LDY #$00
      0F40: B1 AE LDA ($AE),Y ;LELNUM+1
      0F42: 85 A0 STA $A0 ;TSLNUM

      0F44: A5 A0 LDA $A0 ;TSLNUM
      0F46: 20 DB 0E JSR $0EDB
      • 36: CommentAuthorpaw
      • CommentTime24 May 2020 18:05
       
      @zbyti
      te kolory to faktycznie może być "attract mode", trochę wstyd że jako stary atarowiec tego nie skojarzyłem ale jak wspominałem zwykle wyłączam system - tak jest dużo prościej

      a jak będzie 6 wierszy to będzie można sięgnąć do każdego elementu terenu z jednego miejsca żonglując tylko indeksem a 7x40>255,

      i jeszcze muszę sprawdzić dlaczego jest tak duża różnica w wielkości plików
      • 37: CommentAuthorzbyti
      • CommentTime24 May 2020 18:05 zmieniony
       
      @paw jak jest włączony HSCROL to wiersz w GR.0 ma $30 bajtów.

      $6 x $30 = $120 czyli też Cię to nie urządza, chyba, że dodajesz sobie brakujące 8 bajtów na wiersz.

      EDIT: jak rysujesz "działo" to twój max raster jest na oko równy mojemu maksymalnemu :] Masz ewidentnie miejsce do usprawnienia ;)

      W rysowaniu rakiet masz przewagę bo kompilator Action! z tablicy bierze wartości "na około".

      Chyba zrezygnuję z tablicy w tym przypadku bo @MADRAFi dorysował parę rakiet.

      Sądzę, że średnia arytmetyczna rastra w obu programach jest bardzo podobna :]
      • 38: CommentAuthorpaw
      • CommentTime24 May 2020 20:05
       
      faktycznie, ograniczenie do 6 wierszy nic nie da,
      na szczęście to ty piszesz grę, ja tylko staram się wypaść nie gorzej niż program z 1983 roku

      co do "działa" to sprawiło mi najwięcej problemów, muszę to jeszcze przemyśleć bo nie w każdym przypadku "działo" się pojawia choć powinno
      • 39: CommentAuthorzbyti
      • CommentTime25 May 2020 16:05
       
      Parę nowych znaków od @MADRAFi-ego, między innymi nowa rakieta :]

      W zestawie jest także obracająca się kopuła działa/radaru - może będę ją dziś animował?
      • 40: CommentAuthorzbyti
      • CommentTime25 May 2020 20:05 zmieniony
       
      Nawina implementacja animacji kopuły, kod uruchamiany co czwartą ramkę.

      BTMP2==+1
      IF (BTMP2&1)=0 THEN
      BTMP1==+1
      IF (BTMP1&3)=0 THEN MOVEBLOCK(CHARSET+96,CHARSET+104,8) FI
      IF (BTMP1&3)=1 THEN MOVEBLOCK(CHARSET+96,CHARSET+112,8) FI
      IF (BTMP1&3)=2 THEN MOVEBLOCK(CHARSET+96,CHARSET+104,8) FI
      IF (BTMP1&3)=3 THEN MOVEBLOCK(CHARSET+96,CHARSET+120,8) FI
      FI

      zalety:
      - nie muszę wiedzieć gdzie na ekranie jest kopuła

      wady:
      - użyty jest MoveBlock do podstawiania znaku
      - wszystkie kręcą się synchronicznie

      Czas na optymalizację :]
      • 41: CommentAuthorzbyti
      • CommentTime25 May 2020 22:05 zmieniony
       
      Dodałem klatkę animacji i trochę zmieniłem wygląd, teraz tylko animować ;)
      • 42: CommentAuthorzbyti
      • CommentTime26 May 2020 01:05 zmieniony
       
      Może jednak 3 klatki będą lepsze ale wracające z prawej na lewą?

      Trochę dłużej kopuła "patrzy" w lewo bo najczęściej będzie strzelać w tym kierunku.

      Na razie zostaje tak jak w załączniku, muszę popracować nad logiką animacji.
      • 43:
         
        CommentAuthorDracon
      • CommentTime26 May 2020 01:05
       
      Nieźle idzie...
      A jak ma wyglądać główny statek kosmiczny, który będzie przelatywał nad tymi niebezpieczeństwami? Coś a'la pojazd z HUMANOID-a ?
      • 44: CommentAuthorzbyti
      • CommentTime26 May 2020 01:05 zmieniony
       
      @Dracon nie mam pojęcia, możesz coś zaproponować ;)

      EDIT: Jeszcze przerobiłem trochę fonty.
      • 45:
         
        CommentAuthorDracon
      • CommentTime26 May 2020 11:05
       
      @zbyti:
      Hehe.... Ile znaków rezerwowałbyś sobie na uzbrojony pojazd kosmiczny głównego bohatera? ;)
      • 46: CommentAuthorzbyti
      • CommentTime26 May 2020 12:05 zmieniony
       
      @Dracon jako, że jestem niedoświadczony w świecie A8 myślałem zrobić pojazd na duszkach.

      Chociaż pewnie nie ma to sensu bo zapewne nic się nie da ciekawego narysować co by do hi-res pasowało z powodu ich rozdzielczość.

      Ale na razie jest koncepcja, że pojazd ma być na playerach i mogę na nie zużyć wszystkie 4.
      • 47: CommentAuthorMADRAFi
      • CommentTime26 May 2020 13:05 zmieniony
       
      Pierwsza proba narysowania juz byla :)
      • 48: CommentAuthorzbyti
      • CommentTime26 May 2020 13:05 zmieniony
       
      To robocza koncepcja by @MADRAFi

      • 49:
         
        CommentAuthorMq
      • CommentTime26 May 2020 13:05
       
      Hej, spojrzałem na ten zrzut z Mad Studio, i jak ten pojazd jest pokazany tak obok siebie w rozmiarach normal/double/quadrable, to nasunęło mi się, że można by za pomocą przełączania tej szerokości duszków zrobić fajny efekt jakiejś prędkości nadświetlnej czy czegoś w tym stylu. Takie przyspieszenie z przemieszczeniem i rozszerzeniem, a następnie z powrotem zwolnienie i zwężenie. Fajnie by to mogło wyglądać, nie wiem gdzie i czy by się w grze tutaj przydało, ale tak mi się nasunęło.
      • 50: CommentAuthorzbyti
      • CommentTime26 May 2020 13:05 zmieniony
       
      Kompletnie nie rozumiem takiego zachowania Atari jak zaraz opiszę...

      Aby animacja tła był najszybsza postanowiłem sobie przygotować 4 zestawy znaków po 256B i się między nimi przełączać.

      O ile za pierwszym razem CHBAS mogę ustawić na dowolnie wybranej stronie pamięci to następne przełączenie musi być już o $400 nawet jak mój zestaw realnie ma w pamięci tylko $100.

      To jeszcze bym przebolał, chociaż nie rozumiem co sprawia, że po ustawieniu $60 dla CHBAS to wpisanie tam $61, $62, $63 już nic nie zmienia. Rozumiem, że coś tego "pilnuje", ok.

      Ale dlaczego z poniższego testowego kodu IF BTMP1=4 też jest olewane to już nie...

      Co to za "architektura"? Znów jakiś "okrojony liczniki"? :D

      BTMP1==+1
      IF BTMP1=1 THEN CHBAS=$60 FI
      IF BTMP1=2 THEN CHBAS=$64 FI
      IF BTMP1=3 THEN CHBAS=$68 FI
      IF BTMP1=4 THEN CHBAS=$6B FI
      IF BTMP1=5 THEN CHBAS=$68 FI
      IF BTMP1=6 THEN CHBAS=$64 FI
      IF BTMP1=7 THEN CHBAS=$60 BTMP1=0 FI

      XEX poniżej, specjalnie pod $6B00 są same zera, żeby chociaż mrugnęło obrazem, a tu nic...

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

      @Mq dobry pomysł, pewnie wykorzystam :]

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

      EDIT:

      zbyti:

      O ile za pierwszym razem CHBAS mogę ustawić na dowolnie wybranej stronie pamięci (...)

      Nie jest to prawdą, myliłem się, jak to ujął @mono: Granulacja jest zawsze co $400 czyli 1KB.