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
     
    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 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 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 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
     

    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
     
    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 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 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 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 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 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 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
     
    Bardzo ładnie i szybko :)
    • 14: CommentAuthorpaw
    • CommentTime22 May 2020 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 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
     
    @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 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 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
     
    - "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
     
    @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 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 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 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
     
    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
     
    @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 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 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
     
    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 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 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 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
     
    @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 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 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 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
     
    @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 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
     
    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
     
    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 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 zmieniony
     
    Dodałem klatkę animacji i trochę zmieniłem wygląd, teraz tylko animować ;)
    • 42: CommentAuthorzbyti
    • CommentTime26 May 2020 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
     
    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 zmieniony
     
    @Dracon nie mam pojęcia, możesz coś zaproponować ;)

    EDIT: Jeszcze przerobiłem trochę fonty.
    • 45:
       
      CommentAuthorDracon
    • CommentTime26 May 2020
     
    @zbyti:
    Hehe.... Ile znaków rezerwowałbyś sobie na uzbrojony pojazd kosmiczny głównego bohatera? ;)
    • 46: CommentAuthorzbyti
    • CommentTime26 May 2020 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 zmieniony
     
    Pierwsza proba narysowania juz byla :)
    • 48: CommentAuthorzbyti
    • CommentTime26 May 2020 zmieniony
     
    To robocza koncepcja by @MADRAFi

    • 49:
       
      CommentAuthorMq
    • CommentTime26 May 2020
     
    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 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.