diff --git a/.gitignore b/.gitignore index 015326c..8cb7caf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,5 @@ .project *.bak -scorch.lab -scorch.lst -textproc.lab -textproc.lst +*.lab +*.lst artwork/talk.as_ diff --git a/display_main_menu.asm b/Atari/display_main_menu.asm similarity index 99% rename from display_main_menu.asm rename to Atari/display_main_menu.asm index 44ae147..94661e1 100644 --- a/display_main_menu.asm +++ b/Atari/display_main_menu.asm @@ -4,7 +4,7 @@ ;----------------------------------------------- ; start of "variables" (RAM) ;----------------------------------------------- -OptionsHere +OptionsHere ; 0123456789012345678901234567890123456789 dta d"Players : 2 3 4 5 6 " dta d"Cash : none 2K 8K 12K 20K " diff --git a/display_purchasedl.asm b/Atari/display_purchasedl.asm similarity index 97% rename from display_purchasedl.asm rename to Atari/display_purchasedl.asm index f2d8353..79e3779 100644 --- a/display_purchasedl.asm +++ b/Atari/display_purchasedl.asm @@ -15,7 +15,7 @@ DLPurTitleAddr .byte $50 .byte $42 .word purchaseTextBuffer - .byte $00+$80 + .byte $00+$80 .byte $20+$80,$10+$80,$42 MoreUpdl .word EmptyLine diff --git a/display_static.asm b/Atari/display_static.asm similarity index 66% rename from display_static.asm rename to Atari/display_static.asm index 52e2674..f56a21f 100644 --- a/display_static.asm +++ b/Atari/display_static.asm @@ -8,54 +8,54 @@ ;----------------------------------------------- OptionsScreen dta d"Welcome to Scorch v. " - build ; 4 bytes from scorch.asm (fancy method) :) + build ; 4 bytes from scorch.asm (fancy method) :) dta d" (un)2000-2023" .IF TARGET = 800 - dta d" Please select option with " - dta $fe,$dc,$dd,$ff ; cursors in inverse - dta d" and " - dta d"Tab"* - dta d" " - dta d" Press " - dta d"Return"* - dta d" to proceed " + dta d" Please select option with " + dta $fe,$dc,$dd,$ff ; cursors in inverse + dta d" and " + dta d"Tab"* + dta d" " + dta d" Press " + dta d"Return"* + dta d" to proceed " .ELIF TARGET = 5200 - dta d" Please select option with joystick one " - dta d" and press FIRE to proceed " + dta d" Please select option with joystick one " + dta d" and press FIRE to proceed " .ENDIF ; 0123456789012345678901234567890123456789 ;----------------------------------------------- NameScreen .IF TARGET = 800 - dta d" Enter names of players " + dta d" Enter names of players " .ELIF TARGET = 5200 - dta d"Hold " - dta d "FIRE"* - dta d " to enter player names " + dta d"Hold " + dta d "FIRE"* + dta d " to enter player names " .ENDIF NameScreen3 dta d" Human/Atari (difficulty level) " NameScreen5 .IF TARGET = 800 - dta d"TAB"* - dta d" - Port nr " - dta $fe,$dc,$dd,$ff ; cursors in inverse - dta d" - Difficulty" - dta d" " - dta d"INV"* - dta d" - Shape " - dta d"Return"* - dta d" - Proceed " + dta d"TAB"* + dta d" - Port nr " + dta $fe,$dc,$dd,$ff ; cursors in inverse + dta d" - Difficulty" + dta d" " + dta d"INV"* + dta d" - Shape " + dta d"Return"* + dta d" - Proceed " .ELIF TARGET = 5200 - dta d" " - dta d"(5)"* - dta d" - Port/Shape " - dta d"Joy"* - dta d" - Diffic. " - dta d" " - dta d"FIRE"* - dta d" - Proceed " + dta d" " + dta d"(5)"* + dta d" - Port/Shape " + dta d"Joy"* + dta d" - Diffic. " + dta d" " + dta d"FIRE"* + dta d" - Proceed " .ENDIF ;----------------------------------------------- MoreUp @@ -73,51 +73,46 @@ MoreDown WeaponsDescription ; 0123456789012345678901234567890123456789 .IF TARGET = 800 - dta d"Tab"* - dta d ": Defensive/Offensive weapon " + dta d"Tab"* + dta d ": Defensive/Offensive weapon " .ELIF TARGET = 5200 - dta d"Left"* - dta d ": Defensive/Offensive weapon" + dta d"Left"* + dta d ": Defensive/Offensive weapon" .ENDIF PurchaseDescription ; 0123456789012345678901234567890123456789 .IF TARGET = 800 - dta d"Space"* - dta d": Purchase " - dta d"Return"* - dta d": Finish " + dta d"Space"* + dta d": Purchase " + dta d"Return"* + dta d": Finish " .ELIF TARGET = 5200 - dta d"Right"* - dta d": Purchase " - dta d"FIRE"* - dta d": Finish " + dta d"Right"* + dta d": Purchase " + dta d"FIRE"* + dta d": Finish " .ENDIF ActivateDescription ; 0123456789012345678901234567890123456789 .IF TARGET = 800 - dta d"Space"* - dta d": Activate " - dta d"Return"* - dta d": Finish " + dta d"Space"* + dta d": Activate " + dta d"Return"* + dta d": Finish " .ELIF TARGET = 5200 - dta d"Right"* - dta d": Activate " - dta d"FIRE"* - dta d": Finish " + dta d"Right"* + dta d": Activate " + dta d"FIRE"* + dta d": Finish " .ENDIF EmptyLine dta d" " ;--------------------------------------------------- OptionsTitle .IF TARGET = 800 - dta d" scorch "* + dta d" scorch "* .ELIF TARGET = 5200 - dta d" scorch supersystem "* -; dta d" scorch "* -; dta d"5" -; dta d"k"* -; dta d"2" -; dta d" "* + dta d" scorch supersystem "* .ENDIF DifficultyTitle dta d" difficulty "* @@ -135,7 +130,7 @@ GameOverTitle2 dl ; MAIN game display list .byte $70 - .byte $42 + .byte $42 .word statusBuffer .byte $02, $02 .byte $10+$80 ; 2 blank lines + DLI @@ -182,19 +177,19 @@ dl ; MAIN game display list ;----------------------------------------------- OptionsDL .byte $70 - .byte $47 - .word OptionsTitle + .byte $47 + .word OptionsTitle .byte $70,$70 .byte $42 .word OptionsScreen .byte $30,$02,$02,$70 - .byte $42 - .word OptionsHere - .byte $10 + .byte $42 + .word OptionsHere + .byte $10 :maxOptions-1 .by $02,$10 - :(9-maxOptions) .by $70,$10 - .byte $80 - .byte $60 ; to match moved sprites + :(9-maxOptions) .by $70,$10 + .byte $80 + .byte $60 ; to match moved sprites .byte $4f .word (display+140*40) :21 .by $0f ;76 @@ -204,25 +199,25 @@ OptionsDL ;Enter names of tanks DL NameDL .byte $70 - .byte $47 - .word DifficultyTitle - .byte $70,$70 ; 16 empty lines + .byte $47 + .word DifficultyTitle + .byte $70,$70 ; 16 empty lines .byte $42 .word NameScreen - .byte $30 ; 4 empty lines - .byte $42 - .word NameScreen2 - .byte $30+$80 ; 4 empty lines + DLI - .byte $42 - .word NameScreen3 - .byte $10 ; 2 empty lines - .byte $42 - .word NameScreen4 - .byte $02,$02 - .byte $30 ; 4 empty lines - .byte $42 - .word NameScreen5 - .byte $02 + .byte $30 ; 4 empty lines + .byte $42 + .word NameScreen2 + .byte $30+$80 ; 4 empty lines + DLI + .byte $42 + .word NameScreen3 + .byte $10 ; 2 empty lines + .byte $42 + .word NameScreen4 + .byte $02,$02 + .byte $30 ; 4 empty lines + .byte $42 + .word NameScreen5 + .byte $02 .byte $41 .word NameDL ; ------------------------------------------------- @@ -252,8 +247,8 @@ GameOverDL .byte $42 .word GameOverResults :5 .byte $00+$80,$02 - .byte $01 - .word DLCreditsFragm + .byte $01 + .word DLCreditsFragm ; --------------- ; end of "constants" (ROM) ;----------------------------------------------- diff --git a/display_status.asm b/Atari/display_status.asm similarity index 100% rename from display_status.asm rename to Atari/display_status.asm diff --git a/Atari/gr_basics.asm b/Atari/gr_basics.asm new file mode 100644 index 0000000..467f8fe --- /dev/null +++ b/Atari/gr_basics.asm @@ -0,0 +1,679 @@ +.IF *>0 ;this is a trick that prevents compiling this file alone + +; Basic hardware-dependent graphics routines. + +; ----------------------------------------- +.proc unPlot +; plots a point and saves the plotted byte, reverts the previous plot. +; ----------------------------------------- + ldx #0 ; only one pixel +unPlotAfterX + stx WhichUnPlot + + ; first remake the oldie + lda oldplotL,x + sta oldplot + lda oldplotH,x + sta oldplot+1 + + lda oldply,x + tay + lda oldora,x + sta (oldplot),y + + + ; is it not out of the screen ???? + cpw ydraw #screenheight + jcc CheckX + mwa #0 ydraw +CheckX + cpw xdraw #screenwidth + jcs EndOfUnPlot +MakeUnPlot + ; let's count coordinates taken from xdraw and ydraw + ;xbyte = xbyte/8 + lda xdraw+1 + lsr + lda xdraw + ror ;just one bit over 256. Max screenwidth = 512!!! + lsr + lsr +;--- + tay + ldx WhichUnPlot + tya + sta oldply,x + + ldx ydraw + lda linetableL,x + sta xbyte + sta oldplot + lda linetableH,x + sta xbyte+1 + sta oldplot+1 + + lda xdraw + and #$7 + tax + + lda color + bne ClearUnPlot + + ;plotting here + lda (xbyte),y + sta OldOraTemp + ora bittable,x + sta (xbyte),y + bne ContinueUnPlot ; allways <>0 +ClearUnPlot + lda (xbyte),y + sta OldOraTemp + and bittable2,x + sta (xbyte),y +ContinueUnPlot + ldx WhichUnPlot + lda OldOraTemp + sta oldora,x + lda oldplot + sta oldplotL,x + lda oldplot+1 + sta oldplotH,x + ; and now we must solve the problem of several plots + ; in one byte + ldx #4 + ldy WhichUnPlot +LetsCheckOverlapping + cpx WhichUnPlot + beq SkipThisPlot + lda oldplotL,x + cmp oldplotL,y + bne NotTheSamePlot + lda oldplotH,x + cmp oldplotH,y + bne NotTheSamePlot + lda oldply,x + cmp oldply,y + bne NotTheSamePlot + ; the pixel is in the same byte so let's take correct contents + lda oldora,x + sta oldora,y +NotTheSamePlot +SkipThisPlot + dex + bpl LetsCheckOverlapping +EndOfUnPlot + rts +.endp + +; ----------------------------------------- +.proc plot ;plot (xdraw, ydraw, color) +; color == 1 --> put pixel +; color == 0 --> erase pixel +; this is one of the most important routines in the whole +; game. If you are going to speed up the game, start with +; plot - it is used by every single effect starting from explosions +; through line drawing and small text output!!! +; +; Optimized by 0xF (Fox) THXXXX!!! + +; ----------------------------------------- + ; is it not over the screen ??? + cpw ydraw #(screenheight+1); changed for one additional line. cpw ydraw #(screenheight-1) + bcs unPlot.EndOfUnPlot ;nearest RTS +CheckX02 + cpw xdraw #screenwidth + bcs EndOfPlot +MakePlot + ; let's calculate coordinates from xdraw and ydraw + + ;xbyte = xbyte/8 + lda xdraw+1 + lsr + lda xdraw + ror ;just one bit over 256. Max screenwidth = 512!!! + lsr + lsr + sta xbyte + ;--- + ldx ydraw + ldy linetableL,x + lda linetableH,x + sta xbyte+1 + + lda xdraw + and #$7 + tax + lda color + bne ClearPlot + + lda (xbyte),y + ora bittable,x + sta (xbyte),y +EndOfPlot + rts +ClearPlot + lda (xbyte),y + and bittable2,x + sta (xbyte),y + rts +.endp + +; ----------------------------------------- +.proc point_plot +; ----------------------------------------- + ; checks state of the pixel (coordinates in xdraw and ydraw) + ; result is in A (zero or appropriate bit is set) + + ; let's calculate coordinates from xdraw and ydraw + + ;xbyte = xbyte/8 + lda xdraw+1 + lsr + lda xdraw + ror ;just one bit over 256. Max screenwidht = 512!!! + lsr + lsr + sta xbyte + ;--- + ldx ydraw + ldy linetableL,x + lda linetableH,x + sta xbyte+1 + + lda xdraw + and #$7 + tax + + lda (xbyte),y + eor #$ff + and bittable,x + rts +.endp +;-------------------------------------------------- +.proc drawmountains +;-------------------------------------------------- + mwa #0 xdraw + mwa #mountaintable modify + mva #1 color + +drawmountainsloop + ldy #0 + lda (modify),y + cmp #screenheight + beq NoMountain + sta ydraw + sty ydraw+1 +.IF FASTER_GRAF_PROCS = 1 +; there was Drawline proc + lda #screenheight + sec + sbc ydraw + sta tempbyte01 + jsr plot.MakePlot + ; after plot we have: (xbyte),y - addres of screen byte; X - index in bittable (number of bit) +; jmp IntoDraw ; jumps inside Draw routine + ; because one pixel is already plotted (and who cares? :) ) +@ + lda (xbyte),y + and bittable2,x + sta (xbyte),y +;IntoDraw + adw xbyte #screenBytes + dec tempbyte01 + bne @- +; end of Drawline proc +.ELSE +; there was Drawline proc +drawline + jsr plot.MakePlot + inc ydraw + lda ydraw + cmp #screenheight + bne drawline +; end of Drawline proc +.ENDIF +NoMountain + inw modify + inw xdraw + cpw xdraw #screenwidth + bne drawmountainsloop + rts +.endp +;-------------------------------------------------- +.proc TypeChar +; puts char on the graphics screen +; in: CharCode +; in: left LOWER corner of the char coordinates (xdraw, ydraw) +;-------------------------------------------------- + ; char to the table + lda CharCode + sta fontind + lda #$00 + sta fontind+1 + ; char intex times 8 + aslw fontind + rolw fontind + rolw fontind + + adw fontind #TankFont + + ; and 8 bytes to the table + ldy #7 +CopyChar + lda (fontind),y + eor #$ff + sta char1,y + lda #$ff + sta char2,y + dey + bpl CopyChar + ; and 8 subsequent bytes as a mask + adw fontind #8 + ldy #7 +CopyMask + lda (fontind),y + eor #$ff + sta mask1,y + lda #$00 + sta mask2,y + dey + bpl CopyMask + +.IF FASTER_GRAF_PROCS = 1 + ; calculating coordinates from xdraw and ydraw + mwa xdraw xbyte + + lda xbyte + and #$7 + sta ybit + + lsrw xbyte ; div 8 + rorw xbyte + rorw xbyte +;--- + ldy xbyte + + lda ydraw ; y = y - 7 because left lower. shouldn't it be 8? + sec + sbc #7 + tax + + lda linetableL,x + sta xbyte + lda linetableH,x + sta xbyte+1 + ; mask preparation and character shifting + ldx ybit + beq MaskOK00 +MakeMask00 + .rept 8 + lsr mask1+# + ror mask2+# + .endr + sec + .rept 8 + ror char1+# ; in second (and next) lines we have C=1 - one SEC enough + ror char2+# + .endr + dex + bne MakeMask00 +MaskOK00 + ; here x=0 + lda Erase + beq CharLoopi ; it works, because x=0 + lda #$ff + ldx #7 +EmptyChar + sta char1,x + sta char2,x + dex + bpl EmptyChar + ldx #0 +CharLoopi + lda (xbyte),y + ora mask1,x + and char1,x + sta (xbyte),y + iny + lda (xbyte),y + ora mask2,x + and char2,x + sta (xbyte),y + dey + adw xbyte #screenBytes + inx + cpx #8 + bne CharLoopi +.ELSE + mvx #7 temp ; line counter (Y) +CharLoop1 + mva #7 temp+1 ; pixel counter (X) +CharLoop2 + mva #0 color + rol mask1,x + bcc NoMaskNoPlot + rol char1,x + bcs NoPlot +MakeCharPlot + lda Erase + bne ErasingChar + inc color +ErasingChar +NoPlot + jsr plot.MakePlot +AfterCharPlot + inw xdraw + ldx temp + dec temp+1 + bpl CharLoop2 + sec + sbw xdraw #8 + dec ydraw + ldx temp + dex + stx temp + bpl CharLoop1 + clc + lda ydraw + adc #8 + sta ydraw + bne EndPutChar +NoMaskNoPlot + rol char1,x + jmp AfterCharPlot +.ENDIF +EndPutChar + rts +.endp + +;-------------------------------------------------- +.proc PutChar4x4 +; puts 4x4 pixels char on the graphics screen +; in: dx, dy (LOWER left corner of the char) +; in: CharCode4x4 (.sbyte) +; in: plot4x4color (0/255) +; all pixels are being drawn +; (empty and not empty) +;-------------------------------------------------- + cpw dy #(screenheight-1) + jcs TypeChar.EndPutChar ;nearest RTS + cpw dy #(4) + jcc TypeChar.EndPutChar ;nearest RTS + cpw dx #(screenwidth-4) + jcs TypeChar.EndPutChar ;nearest RTS + ; checks ommited. + ; char to the table + lda CharCode4x4 + and #%00000001 + beq Upper4bits + lda #$ff ; better option to check (nibbler4x4 = $00 or $ff) +Upper4bits + sta nibbler4x4 + lda CharCode4x4 + lsr + sta fontind + lda #$00 + sta fontind+1 + + adw fontind #font4x4 + + ; and 4 bytes to the table + ldy #0 + ldx #3 +CopyChar + lda (fontind),y ; Y must be 0 !!!! + bit nibbler4x4 + bpl GetUpper4bits + :4 rol +GetUpper4bits + ora #$0f + sta char1,x + lda #$ff + sta char2,x + ; and 4 bytes as a mask + lda #$f0 + sta mask1,x + lda #$00 + sta mask2,x + adw fontind #32 ; next byte of 4x4 font + dex + bpl CopyChar + +.IF FASTER_GRAF_PROCS = 1 + ; calculating coordinates from xdraw and ydraw + mwa dx xbyte + + lda xbyte + and #$7 + sta ybit + + :3 lsrw xbyte ; div 8 +; rorw xbyte +; rorw xbyte +;--- + ldy xbyte ; horizontal byte offet stored in Y + lda dy ; y = y - 3 because left lower. + sec + sbc #3 + tax + + lda linetableL,x + sta xbyte + lda linetableH,x + sta xbyte+1 + ; mask preparation and character shifting + ldx ybit + beq MaskOK01 +MakeMask01 + .rept 4 + lsr mask1+# + ror mask2+# + .endr + sec + .rept 4 + ror char1+# ; in second (and next) lines we have C=1 - one SEC enough + ror char2+# + .endr + dex + bne MakeMask01 +MaskOK01 + ldx #0 +CharLoopi4x4 + lda (xbyte),y + ora mask1,x + bit plot4x4color + bpl PutInColor0_1 ; only mask - no char + and char1,x +PutInColor0_1 + sta (xbyte),y + iny + lda (xbyte),y + ora mask2,x + bit plot4x4color + bpl PutInColor0_2 ; only mask - no char + and char2,x +PutInColor0_2 + sta (xbyte),y + dey + adw xbyte #screenBytes + inx + cpx #4 + bne CharLoopi4x4 +.ELSE + mwa xdraw char2 + mwa ydraw mask2 + mva color mask2+2 + mwa dx xdraw + mwa dy ydraw + mvx #3 temp ; line counter (Y) +CharLoop1 + mva #3 temp+1 ; pixel counter (X) +CharLoop2 + mva #0 color + rol mask1,x + bcc NoMaskNoPlot + rol char1,x + bcs NoPlot +MakeCharPlot + lda plot4x4color + beq ErasingChar + inc color +ErasingChar +NoPlot + jsr plot.MakePlot +AfterCharPlot + inw xdraw + ldx temp + dec temp+1 + bpl CharLoop2 + sec + sbw xdraw #4 + dec ydraw + ldx temp + dex + stx temp + bpl CharLoop1 + mwa char2 xdraw + mwa mask2 ydraw + mva mask2+2 color + bpl EndPut4x4 +NoMaskNoPlot + rol char1,x + jmp AfterCharPlot +.ENDIF +EndPut4x4 + rts +.endp + +;-------------------------------------------------- +.proc ClearScreen +;-------------------------------------------------- + mwa #display temp + ldy #0 +@ lda #$ff + sta (temp),y + inw temp + cpw temp #display+screenheight*screenBytes+1 + bne @- + rts +.endp + +;-------------------------------------------------- +.proc GenerateLineTable + + mwa #display temp + mwa #linetableL temp2 + mwa #linetableH modify + ldy #0 +@ lda temp + sta (temp2),y + lda temp+1 + sta (modify),y + adw temp #40 + iny + cpy #screenheight+1 + bne @- + rts +.endp +;-------------------------------------------------- +.proc SetMainScreen +; mva #0 dmactls + SetDLI DLIinterruptGraph ; jsr SetDLI for graphics (game) screen + mwa #dl dlptrs ; issue #72 (glitches when switches) + lda #%00111110 +; and #$fc +; ora #$02 ; 2=normal, 3 = wide screen width + sta dmactls + mva WallsType COLBAKS ; set color of background + jmp WaitOneFrame + ; rts +.endp +;-------------------------------------------------- + + +; ******* This is weapon .... but ... ******* +; ------------------------------------------------- +.proc AtomicWinter +; ------------------------------------------------- +; This routine is run from inside of the main loop +; and replaces Shoot and Flight routines +; X and TankNr - index of shooting tank +; ------------------------------------------------- + mva #sfx_sandhog sfx_effect +.IF FASTER_GRAF_PROCS = 1 + ldy #0 ; byte counter (from 0 to 39) +NextColumn + ; big loop - we repat internal loops for each column of bytes + sty magic + ldx #120 ; line counter (from 0 to 60 ) + ; first loop - inverse column of bytes for a while + ldy magic +NextLine1 + jsr InverseScreenByte + dex + dex + bpl NextLine1 + ; + jsr WaitOneFrame ; wait uses A only + ; second loop - inverse again and put random "snow" to column of bytes + ldx #120 + ldy magic + mva #$55 magic+1 +NextLine2 + jsr InverseScreenByte + lda random + ora magic+1 + and (temp),y + sta (temp),y + lda magic+1 + eor #$ff + sta magic+1 + dex + dex + bpl NextLine2 + ; and go to next column + iny + cpy #40 + bne NextColumn +.ELSE + mva #1 color + mwa #120 ydraw +NextLineSlow + lda #0 + sta xdraw + sta xdraw+1 +NextPixelSlow + bit random + bpl NoPlot + bvc NoPlot + jsr plot.MakePlot +NoPlot + inw xdraw + cpw xdraw #screenwidth + bne NextPixelSlow + dec ydraw + dec ydraw + bpl NextLineSlow +.ENDIF + ; and we have "snow" :) + lda #0 + ldx TankNr + sta ActiveDefenceWeapon,x ; deactivate Nuclear Winter + jsr SetFullScreenSoilRange + jmp SoilDown2.NoClearTanks + ; rts + + ; in order to optimize the fragment repeated in both internal loops + ; we save 15 bytes :) +InverseScreenByte + lda LineTableL,x + sta temp + lda LineTableH,x + sta temp+1 + lda (temp),y + eor #$ff + sta (temp),y + rts +.endp + +.ENDIF \ No newline at end of file diff --git a/interrupts.asm b/Atari/interrupts.asm similarity index 52% rename from interrupts.asm rename to Atari/interrupts.asm index 175bdb1..21bfd42 100644 --- a/interrupts.asm +++ b/Atari/interrupts.asm @@ -1,114 +1,114 @@ -; @com.wudsn.ide.asm.mainsourcefile=scorch.asm +; @com.wudsn.ide.asm.mainsourcefile=scorch.asm .IF *>0 ;this is a trick that prevents compiling this file alone ;-------------------------------------------------- .proc DLIinterruptGraph - pha - phy - ldy dliCounter - lda dliColorsBack,y + pha + phy + ldy dliCounter + lda dliColorsBack,y .IF TARGET = 800 - nop ; necessary on 800 because DLIs take less time, jitter visible without it - nop - nop + nop ; necessary on 800 because DLIs take less time, jitter visible without it + nop + nop .ENDIF - nop - nop + nop + nop sta COLPF1 - lda GradientNr - bne GoGradient - ldy #$ff ; one mauntain color + lda GradientNr + bne GoGradient + ldy #$ff ; one mauntain color GoGradient - iny - lda (GradientColors),y ; mountains colors array - sta COLPF2 - inc dliCounter + iny + lda (GradientColors),y ; mountains colors array + sta COLPF2 + inc dliCounter ply pla rti .endp ;-------------------------------------------------- .proc DLIinterruptOptions - pha - phy - lda #0 ; background color + pha + phy + lda #0 ; background color sta COLPF1 - ldy GradientNr - beq @+ - ldy #1 -@ lda (GradientColors),y ; mountains colors array - sta COLPF2 - ply + ldy GradientNr + beq @+ + ldy #1 +@ lda (GradientColors),y ; mountains colors array + sta COLPF2 + ply pla rti .endp ;-------------------------------------------------- .proc DLIinterruptGameOver - pha - phy - lda dliCounter - bne EndofPMG - lda #%00100001 ; playfield after P/M - prior=1 - ;STA WSYNC + pha + phy + lda dliCounter + bne EndofPMG + lda #%00100001 ; playfield after P/M - prior=1 + ;STA WSYNC sta PRIOR - bne EndOfDLI_GO + bne EndOfDLI_GO EndofPMG - cmp #1 - bne ColoredLines - lda #%00100100 ; playfield before P/M - ;STA WSYNC + cmp #1 + bne ColoredLines + lda #%00100100 ; playfield before P/M + ;STA WSYNC sta PRIOR - bne EndOfDLI_GO + bne EndOfDLI_GO ColoredLines - cmp #9 - beq CreditsScroll - tay - lda GameOverColoursTable-3,y ; -2 because this is DLI nr 2 and -1 (labels line) - ldy #$0a ; text colour (brightnes) - ;STA WSYNC - sta COLPF2 - sty COLPF1 - bne EndOfDLI_GO + cmp #9 + beq CreditsScroll + tay + lda GameOverColoursTable-3,y ; -2 because this is DLI nr 2 and -1 (labels line) + ldy #$0a ; text colour (brightnes) + ;STA WSYNC + sta COLPF2 + sty COLPF1 + bne EndOfDLI_GO CreditsScroll - lda #$00 - sta COLPF2 + lda #$00 + sta COLPF2 EndOfDLI_GO - inc dliCounter - ply - pla - rti + inc dliCounter + ply + pla + rti .endp ;-------------------------------------------------- .proc DLIinterruptText pha - lda dliCounter - bne MoreBarsColorChange + lda dliCounter + bne MoreBarsColorChange lda #TextBackgroundColor - ;sta WSYNC + ;sta WSYNC sta COLPF2 mva #TextForegroundColor COLPF3 - bne EndOfDLI_Text + bne EndOfDLI_Text MoreBarsColorChange - and #%00000001 - rol - sta COLPF2 + and #%00000001 + rol + sta COLPF2 EndOfDLI_Text - inc dliCounter + inc dliCounter pla DLIinterruptNone - rti - + rti + .endp ;-------------------------------------------------- .proc VBLinterrupt - mva #0 dliCounter - mva #$02 DliColorBack - - lda PAL - and #%00001110 - beq itsPAL - ;it is NTSC here + mva #0 dliCounter + mva #$02 DliColorBack + + lda PAL + and #%00001110 + beq itsPAL + ;it is NTSC here dec NTSCcounter bne itsPAL mva #6 NTSCcounter @@ -118,13 +118,13 @@ DLIinterruptNone itsPAL ; pressTimer is trigger tick counter. always 50 ticks / s bit:smi:inc pressTimer ; timer halted if >127. max time measured 2.5 s - + SkippedIfNTSC - bit RMT_blocked - bmi SkipRMTVBL + bit RMT_blocked + bmi SkipRMTVBL ; ------- RMT ------- - lda sfx_effect + lda sfx_effect bmi lab2 asl @ ; * 2 tay ;Y = 2,4,..,16 instrument number * 2 (0,2,4,..,126) @@ -138,80 +138,88 @@ SkippedIfNTSC lab2 jsr RASTERMUSICTRACKER+3 ;1 play ; ------- RMT ------- -SkipRMTVBL - bit ScrollFlag - bpl EndOfCreditsVBI +SkipRMTVBL + bit ScrollFlag + bpl EndOfCreditsVBI CreditsVBI - inc CreditsVScrol - lda CreditsVScrol - cmp #32 ;not too fast - beq nextlinedisplay - :2 lsr ;not too fast - sta VSCROL - jmp EndOfCreditsVBI + inc CreditsVScrol + lda CreditsVScrol + cmp #32 ;not too fast + beq nextlinedisplay + :2 lsr ;not too fast + sta VSCROL + jmp EndOfCreditsVBI nextlinedisplay - lda #0 - sta CreditsVScrol - sta VSCROL - clc - lda DLCreditsAddr - adc #40 - sta DLCreditsAddr - bcc @+ - inc DLCreditsAddr+1 + lda #0 + sta CreditsVScrol + sta VSCROL + clc + lda DLCreditsAddr + adc #40 + sta DLCreditsAddr + bcc @+ + inc DLCreditsAddr+1 @ - cmp #CreditsLastLine - bne EndOfCreditsVBI -; adw DLCreditsAddr #40 -; cpw DLCreditsAddr #CreditsLastLine -; bne EndOfCreditsVBI - mwa #Credits DLCreditsAddr + cmp #CreditsLastLine + bne EndOfCreditsVBI +; adw DLCreditsAddr #40 +; cpw DLCreditsAddr #CreditsLastLine +; bne EndOfCreditsVBI + mwa #Credits DLCreditsAddr EndOfCreditsVBI - .IF TARGET = 5200 - lda SkStatSimulator - bmi @+ - inc SkStatSimulator + .IF TARGET = 800 + ; support for joysticks :) + ldx JoystickNumber + lda STICK0,x + sta STICK0 + lda STRIG0,x + sta STRIG0 + jmp XITVBV + .ELIF TARGET = 5200 + lda SkStatSimulator + bmi @+ + inc SkStatSimulator @ - lda JoystickNumber ; select port - ora #%00000100 ; Speaker off, Pots enabled + lda JoystickNumber ; select port + ora #%00000100 ; Speaker off, Pots enabled sta CONSOL5200 center = 114 ;Read analog stick and make it look like a digital stick threshold = 60 - - lda JoystickNumber - asl - tax + + lda JoystickNumber + asl + tax lda paddl0,x ;Read POT0 value (horizontal position) cmp #center+threshold ;Compare with right threshold rol stick0 ;Feed carry into digital stick value cmp #center-threshold ;Compare with left threshold rol stick0 ;Feed carry into digital stick value - + lda paddl1,x ;Read POT1 value (vertical position) cmp #center+threshold ;Compare with down threshold rol stick0 ;Feed carry into digital stick value cmp #center-threshold ;Compare with down threshold rol stick0 ;Feed carry into digital stick value - + lda stick0 ;0 indicates a press so the right/down values need to be inverted eor #2+8 and #$0f sta stick0 - - ldx JoystickNumber - ; check shift key (5200 second fire button) - lda SKSTAT - :3 lsr ; third bit - and trig0,x ; and first button - ;lda trig0,x - sta strig0 ;Move hardware to shadow - + + ldx JoystickNumber + ; check shift key (5200 second fire button) + lda SKSTAT + :3 lsr ; third bit + and trig0,x ; and first button + ;lda trig0,x + sta strig0 ;Move hardware to shadow + mva chbas chbase - + lda skstat ;Reset consol key shadow is no key is pressed anymore and #4 beq @+ @@ -224,44 +232,36 @@ EndOfCreditsVBI pla tax pla - rti - .ELSE - ; support for joysticks :) - ldx JoystickNumber - lda STICK0,x - sta STICK0 - lda STRIG0,x - sta STRIG0 - jmp XITVBV - .ENDIF + rti + .ENDIF .endp .IF TARGET = 5200 .proc kb_continue sta kbcode ;Store key code in shadow. - mva #0 SkStatSimulator + mva #0 SkStatSimulator exit pla tay pla tax pla rti -.endp +.endp .ENDIF ;-------------------------------------------------- .macro SetDLI -; SetDLI #WORD -; Initialises Display List Interrupts +; SetDLI #WORD +; Initialises Display List Interrupts LDY # <:1 LDX # >:1 - jsr _SetDLIproc + jsr _SetDLIproc .endm .proc _SetDLIproc - LDA #$C0 - STY VDSLST - STX VDSLST+1 - STA NMIEN - rts + LDA #$C0 + STY VDSLST + STX VDSLST+1 + STA NMIEN + rts .endp .ENDIF diff --git a/lib/5200MACRO.ASM b/Atari/lib/5200MACRO.ASM similarity index 100% rename from lib/5200MACRO.ASM rename to Atari/lib/5200MACRO.ASM diff --git a/lib/5200SYS.ASM b/Atari/lib/5200SYS.ASM similarity index 100% rename from lib/5200SYS.ASM rename to Atari/lib/5200SYS.ASM diff --git a/lib/ATARISYS.ASM b/Atari/lib/ATARISYS.ASM similarity index 100% rename from lib/ATARISYS.ASM rename to Atari/lib/ATARISYS.ASM diff --git a/lib/MACRO.ASM b/Atari/lib/MACRO.ASM similarity index 100% rename from lib/MACRO.ASM rename to Atari/lib/MACRO.ASM diff --git a/textproc.asm b/Atari/textproc.asm similarity index 70% rename from textproc.asm rename to Atari/textproc.asm index 7b55476..b36270d 100644 --- a/textproc.asm +++ b/Atari/textproc.asm @@ -27,51 +27,50 @@ lda #%00111110 ; normal screen width, DL on, P/M on sta dmactls - jsr SetPMWidth + jsr SetPMWidth mva #TextBackgroundColor COLOR2 jsr ColorsOfSprites - mva #$ca COLOR1 - mva #$00 COLBAKS ; set color of background - + mva #$ca COLOR1 + mva #$00 COLBAKS ; set color of background + SetDLI DLIinterruptOptions ; jsr SetDLI for Options text screen -; -------- setup bottom (tanks) line - lda NumberOfPlayers - pha +; -------- setup bottom (tanks) line + lda NumberOfPlayers + pha lda mountainsDeltaTableH sta mountainDeltaH lda mountainsDeltaTableL sta mountainDeltaL - mva #6 NumberOfPlayers + mva #6 NumberOfPlayers jsr PMoutofScreen ;let P/M disappear ;jsr clearscreen ;let the screen be clean (clean-ish already) - jsr ClearPMmemory + jsr ClearPMmemory jsr placetanks ;let the tanks be evenly placed jsr calculatemountains ;let mountains be easy for the eye jsr drawmountains ;draw them - ldx NumberOfPlayers - dex -@ jsr RandomizeAngle - sta AngleTable,x - dex - bpl @- + ldx NumberOfPlayers + dex +@ jsr RandomizeAngle + sta AngleTable,x + dex + bpl @- jsr drawtanks ;finally draw tanks - pla - sta NumberOfPlayers -; -------- + pla + sta NumberOfPlayers mva #0 OptionsY OptionsMainLoop - lda WindChangeInRound - sta OptionsHere+126 + lda WindChangeInRound + sta OptionsHere+126 jsr OptionsInversion jsr getkey bit escFlag spl:rts - + cmp #@kbcode._down ; $f ;cursor down bne OptionsNoDown inc:lda OptionsY @@ -113,37 +112,39 @@ OptionsNoLeft OptionsNoRight cmp #@kbcode._ret ; $c ;Return key bne OptionsNoReturn - rts ; options selected - + rts ; options selected + OptionsNoReturn - cmp #@kbcode._tab ; Tab key - bne OptionsNoTab - jsr SelectNextGradient + cmp #@kbcode._tab ; Tab key + bne OptionsNoTab + jsr SelectNextGradient OptionsNoTab jmp OptionsMainLoop .endp + .proc SelectNextGradient - lda OptionsY ; if "Wind" option selected - cmp #$03 - bne NotWind - lda WindChangeInRound ; wind change after each turn (not round only) flag - eor #$1f ; '?' character - sta WindChangeInRound - rts + lda OptionsY ; if "Wind" option selected + cmp #$03 + bne NotWind + lda WindChangeInRound ; wind change after each turn (not round only) flag + eor #$1f ; '?' character + sta WindChangeInRound + rts NotWind - ldy GradientNr - iny - cpy #$03 - bne NoGradientLoop - ldy #$00 + ldy GradientNr + iny + cpy #$03 + bne NoGradientLoop + ldy #$00 NoGradientLoop - sty GradientNr - lda GradientAddrL,y - sta GradientColors - lda GradientAddrH,y - sta GradientColors+1 - rts + sty GradientNr + lda GradientAddrL,y + sta GradientColors + lda GradientAddrH,y + sta GradientColors+1 + rts .endp + ;-------- ; inversing selected option (cursor) ;-------- @@ -154,7 +155,7 @@ optionWidth = 6 nameWidth = 10 mwa #OptionsHere temp ; offset of the first option=11 mva #0 YPos ;option number pointer - mva #0 Xpos ;X position in the menu + sta Xpos ;X position in the menu tay ; Y is zero here... OptionsSetMainLoop ldx YPos ; Y position in the menu @@ -173,7 +174,7 @@ OptionsLoop cpy #optionWidth ; width of the option highlight bne OptionsLoop ldy #0 - ; next X position of the + ; next X position of the adw temp #optionWidth ; width of the option highlight inc:lda XPos cmp #5 ; number of options in a row @@ -190,12 +191,12 @@ OptionsLoop _inverter beq invertme ; clean inversion otherwise - lda (temp),y + lda (temp),y and #$7f ; clear the top bit sta (temp),y bpl @+ ; JMP invertme - lda (temp),y + lda (temp),y ora #$80 ; set the top bit sta (temp),y @ @@ -204,104 +205,45 @@ invertme rts .endp -; -------------------------------------- -; Sets the appropriate variables based on the options table -; -.proc SetVariablesFromOptions - ;first option - ldy OptionsTable - iny - iny - sty NumberOfPlayers ;1=1 player (but minimum is 2) - - ;second option (cash) - - - ldy OptionsTable+1 - ldx #0 -@ - lda CashOptionL,y - sta moneyL,x - lda CashOptionH,y - sta moneyH,x - inx - cpx NumberOfPlayers - bne @- - - ;third option (gravity) - ldy OptionsTable+2 - lda GravityTable,y - sta gravity - - ;fourth option (wind) - ldy OptionsTable+3 - lda MaxWindTable,y - sta MaxWind - - ;fifth option (no of rounds) - ldy OptionsTable+4 - lda RoundsTable,y - sta RoundsInTheGame - - ;6th option (shell speed) - ldy OptionsTable+5 - lda flyDelayTable,y - sta flyDelay - - ;7th option (Airstrike after how many missess) - ldy OptionsTable+6 - lda seppukuTable,y - sta seppukuVal - - ;8th option (how aggressive are mountains) - ldy OptionsTable+7 - lda mountainsDeltaTableH,y - sta mountainDeltaH - lda mountainsDeltaTableL,y - sta mountainDeltaL - - - rts -.endp - +.proc CallPurchaseForEveryTank ;------------------------------------------- ; call of the purchase (and activate) screens for each tank -.proc CallPurchaseForEveryTank +;------------------------------------------- - mva #0 TankNr - sta isInventory + mva #0 TankNr + sta isInventory @ - ldx TankNr - lda SkillTable,x - beq ManualPurchase - jsr PurchaseAI ; remember to make ActivateAI :) !!! - jmp AfterManualPurchase + ldx TankNr + lda SkillTable,x + beq ManualPurchase + jsr PurchaseAI ; remember to make ActivateAI :) !!! + jmp AfterManualPurchase ManualPurchase - lda JoyNumber,x - sta JoystickNumber ; set joystick port for player - mva #0 isInventory - jsr Purchase ; purchase weapons - bit escFlag - spl:rts - jsr DefensivesActivate ; activate weapons - bit escFlag - spl:rts + lda JoyNumber,x + sta JoystickNumber ; set joystick port for player + mva #0 isInventory + jsr Purchase ; purchase weapons + bit escFlag + spl:rts + jsr DefensivesActivate ; activate weapons + bit escFlag + spl:rts AfterManualPurchase - inc:lda TankNr - cmp NumberOfPlayers - bne @- - rts + inc:lda TankNr + cmp NumberOfPlayers + bne @- + rts .endp ;-------------------------------------------------- .proc DefensivesActivate ;-------------------------------------------------- ; This proc call Inventory and set Defensives activation first - - mwa #ListOfDefensiveWeapons WeaponsListDL ;switch to the list of offensive weapons + + mwa #ListOfDefensiveWeapons WeaponsListDL ;switch to the list of offensive weapons mva #$ff IsInventory mva #%10000000 WhichList ; offensive weapon - 0, defensive - %10000000 - jmp Purchase.GoToActivation + jmp Purchase.GoToActivation .endp ;-------------------------------------------------- @@ -323,7 +265,7 @@ AfterManualPurchase jsr CopyFromPurchaseAndGameOver mwa #ListOfWeapons WeaponsListDL ;switch to the list of offensive weapons - + ; we are clearing list of the weapons mva #$00 WhichList ; offensive weapon - 0, deffensive - %10000000 @@ -337,21 +279,21 @@ GoToActivation sta dmactls lda #song_supermarket - bit IsInventory - bpl @+ - lda #song_inventory -@ jsr RmtSongSelect - + bit IsInventory + bpl @+ + lda #song_inventory +@ jsr RmtSongSelect + ldx tankNr lda TankStatusColoursTable,x sta COLOR2 ; there is a tank (player) number in tanknr ; we are displaying name of the player - lda #$ca - sta COLOR1 ; set color of header text - ldy #0 - sty COLBAKS ; set color of background + lda #$ca + sta COLOR1 ; set color of header text + ldy #0 + sty COLBAKS ; set color of background lda tanknr :3 asl ; 8 chars per name tax @@ -362,10 +304,10 @@ NextChar03 iny cpy #$08 bne NextChar03 - ; displaying number of active controller port - ldy JoystickNumber - lda digits+1,y - sta purchaseTextBuffer+17 + ; displaying number of active controller port + ldy JoystickNumber + lda digits+1,y + sta purchaseTextBuffer+17 ; and we display cash of the given player @@ -389,15 +331,15 @@ AfterPurchase ldx #$00 ; index of the checked weapon stx HowManyOnTheListOff ; amounts of weapons (shells, bullets) in both lists stx HowManyOnTheListDef - + jsr CreateList - bit isInventory ; + bit isInventory ; bpl ChoosingItemForPurchase - + lda whichList bne PositionDefensive - + ; calculate positionOnTheList from the activeWeapon (offensives) ldx tankNr lda activeWeapon,x @@ -406,7 +348,7 @@ AfterPurchase cmp IndexesOfWeaponsL1,y beq ?weaponfound iny - cpy #(last_offensive_____ - first_offensive____)+1 ; maxOffensiveWeapons + cpy #(last_offensive - first_offensive )+1 ; maxOffensiveWeapons bne @- ; not found apparently? ; TODO: check border case (the last weapon) @@ -414,19 +356,19 @@ AfterPurchase beq ?weaponFound ; jmp PositionDefensive jsr calcPosDefensive - + ?weaponFound ; weapon index in Y sty positionOnTheList - jsr _MakeOffsetDown ; set list screen offset + jsr _MakeOffsetDown ; set list screen offset ; Here we have all we need ; So choose the weapon for purchase ...... ;-------------------------------------------------- ChoosingItemForPurchase ;-------------------------------------------------- - + jsr PutLitteChar ; Places pointer at the right position jsr getkey bit escFlag @@ -465,7 +407,7 @@ GoUpOffensive ldy HowManyOnTheListOff dey sty PositionOnTheList - jmp MakeOffsetDown + jmp MakeOffsetDown MakeOffsetUp ; If offset is larger than pointer position, ; it must be equal then. @@ -483,16 +425,16 @@ PurchaseKeyDown bne EndGoDownX ldy #0 sty PositionOnTheList - beq MakeOffsetUp + beq MakeOffsetUp GoDownOffensive inc:lda PositionOnTheList cmp HowManyOnTheListOff bne MakeOffsetDown ldy #0 sty PositionOnTheList - beq MakeOffsetUp + beq MakeOffsetUp MakeOffsetDown - jsr _MakeOffsetDown + jsr _MakeOffsetDown EndGoDownX jmp ChoosingItemForPurchase @@ -508,7 +450,7 @@ _MakeOffsetDown sbc #15 sta OffsetDL1 _EndGoDownX - rts + rts ; swapping the displayed list and setting pointer to position 0 ListChange @@ -524,7 +466,7 @@ ListChange beq @+ ; inventory jsr calcPosOffensive - jsr _MakeOffsetDown ; set list screen offset + jsr _MakeOffsetDown ; set list screen offset jmp ChoosingItemForPurchase @ mva #0 PositionOnTheList @@ -541,7 +483,7 @@ DeffensiveSelected jmp ChoosingItemForPurchase .endp -; + ;-------------------------------------------------- .proc CreateList ;-------------------------------------------------- @@ -555,11 +497,11 @@ CreateList lda WeaponUnits,x jeq NoWeapon - ldy tanknr - + ldy tanknr + bit isInventory jmi itIsInventory - + ; put "Purchase" on the screen mwa #PurchaseDescription PurActDescAddr ; and Title @@ -574,7 +516,7 @@ CreateList cmp WeaponPriceL,x @ jcc TooLittleCash - + ; we have enough cash and the weapon can be ; added to the list @@ -643,7 +585,7 @@ notInventory jsr HowManyBullets sta decimal - adw xbyte #1 displayposition + adw xbyte #1 displayposition jsr displaybyte ldx temp ;weapon index @@ -697,7 +639,7 @@ notInventory NotTheSameAsLastTime ; increase appropriate counter txa - cpx #last_offensive_____+1 + cpx #last_offensive +1 bcs DefenceList ldy HowManyOnTheListOff sta IndexesOfWeaponsL1,y @@ -715,15 +657,15 @@ NoWeapon ; next weapon. If no more weapons then finish! inx - cpx #last_offensive_____+1 + cpx #last_offensive +1 bne NoDefense ; if we got to the defense weapons, ; we switch address to the second table. mwa #ListOfDefensiveWeapons xbyte NoDefense - cpx #last_defensive_____+1 - + cpx #last_defensive +1 + jne CreateList ; offset may be only too big @@ -744,20 +686,20 @@ WeHaveOffset lda HowManyOnTheListOff sta xbyte ; multiplier (temporarily here, it will be erased anyway) - lda #$00 ; + lda #$00 ; sta xbyte+1 ; higher byte of the Result ldx #$05 ; 2^5 @ asl xbyte rol xbyte+1 dex bne @- - + ; add to the address of the list adw xbyte #ListOfWeapons ldy #0 ClearList1 cpw xbyte #ListOfWeapons1End - beq ListCleared1 + beq ListCleared1 tya ; now there is zero here sta (xbyte),y inw xbyte @@ -769,7 +711,7 @@ ListCleared1 ; of the first erased char. lda HowManyOnTheListDef sta xbyte ; multiplier (temporarily here, it will be erased anyway) - lda #$00 ; + lda #$00 ; sta xbyte+1 ; higher byte of the Result ldx #$05 ; 2^5 @ asl xbyte @@ -782,7 +724,7 @@ ListCleared1 ldy #0 ClearList2 cpw xbyte #ListOfDefensiveWeaponsEnd - beq ListCleared2 + beq ListCleared2 tya ; now there is zero here sta (xbyte),y inw xbyte @@ -824,36 +766,36 @@ PurchaseAll lda moneyH,x sbc WeaponPriceH,y sta moneyH,x - -positiveMoney + +positiveMoney ; now we have to get address of ; the table of the weapon of the tank ; and add appropriate number of shells sty LastWeapon ; store last purchased weapon ; because we must put screen pointer next to it - - ; but if we purchasing "Buy me!" then we must draw the winning weapon. - - cpy #ind_Buy_me_________ - bne NoSuprise - -Suprise ; get a random weapon - lda random - cmp #51 ; defensive weapons are less likely because they are more expensive - probability 255:51 (5:1) - bcc GetRandomDefensive + + ; but if we purchasing "Buy me!" then we must draw the winning weapon. + + cpy #ind_Buy_me + bne NoSuprise + +Suprise ; get a random weapon + lda random + cmp #51 ; defensive weapons are less likely because they are more expensive - probability 255:51 (5:1) + bcc GetRandomDefensive GetRandomOffensive - randomize ind_Missile________ last_offensive_____ - ;cmp #ind_Buy_me_________ ; buy me do not buy buy me :) - ;beq GetRandomOffensive - tay - bne NoSuprise ; Y always <> 0 + randomize ind_Missile last_offensive + ;cmp #ind_Buy_me ; buy me do not buy buy me :) + ;beq GetRandomOffensive + tay + bne NoSuprise ; Y always <> 0 GetRandomDefensive - randomize ind_Battery________ last_defensive_____ - tay -; lda WeaponUnits,y ; check if weapon exist -; beq GetRandomDefensive - + randomize ind_Battery last_defensive + tay +; lda WeaponUnits,y ; check if weapon exist +; beq GetRandomDefensive + NoSuprise lda TanksWeaponsTableL,x sta weaponPointer @@ -882,54 +824,54 @@ inventorySelect ldx tankNr sta activeWeapon,x jmp WaitForKeyRelease ; rts - + invSelectDef ldy PositionOnTheList lda IndexesOfWeaponsL2,y tay ldx tankNr - cmp #ind_Battery________ + cmp #ind_Battery bne NotBattery ; if activate battery, we do it differently mva #sfx_battery sfx_effect - phy + phy mva #99 Energy,x - jsr MaxForceCalculate - ply + jsr MaxForceCalculate + ply jmp DecreaseDefensive ; bypass activation NotBattery - cmp #ind_Auto_Defense___ - bne NoAutoDefense + cmp #ind_Auto_Defense + bne NoAutoDefense ; Auto Defense - do it like battery mva #sfx_auto_defense sfx_effect - mva #$A1 AutoDefenseFlag,x ; this is "A" in inverse - for status line :) + mva #$A1 AutoDefenseFlag,x ; this is "A" in inverse - for status line :) jmp DecreaseDefensive ; bypass activation NoAutoDefense - cmp #ind_Lazy_Boy_______ - bne NoLazyBoy - ; Lazy Boy - do it like battery - mva #%01000000 LazyFlag + cmp #ind_Lazy_Boy + bne NoLazyBoy + ; Lazy Boy - do it like battery + mva #%01000000 LazyFlag jmp DecreaseDefensive ; bypass activation NoLazyBoy - cmp #ind_Lazy_Darwin____ - bne NoLazyDarwin - ; Lazy Darwin - do it like battery - mva #%11000000 LazyFlag + cmp #ind_Lazy_Darwin + bne NoLazyDarwin + ; Lazy Darwin - do it like battery + mva #%11000000 LazyFlag jmp DecreaseDefensive ; bypass activation NoLazyDarwin - cmp #ind_Spy_Hard_______ - bne NotSpy - mva #$ff SpyHardFlag - jmp DecreaseDefensive ; bypass activation + cmp #ind_Spy_Hard + bne NotSpy + mva #$ff SpyHardFlag + jmp DecreaseDefensive ; bypass activation NotSpy - cmp #ind_Long_Barrel____ - bne NotBarrel - ; if activate long barrel, we do it differently too - mva #sfx_long_barrel sfx_effect + cmp #ind_Long_Barrel + bne NotBarrel + ; if activate long barrel, we do it differently too + mva #sfx_long_barrel sfx_effect mva #LongBarrel BarrelLength,x - bne DecreaseDefensive ; bypass activation + bne DecreaseDefensive ; bypass activation NotBarrel - cmp #ind_White_Flag_____ + cmp #ind_White_Flag bne NotWhiteFlag cmp ActiveDefenceWeapon,x bne NoDeactivateWhiteFlag @@ -955,14 +897,15 @@ DecreaseDefensive sec sbc #1 sta (weaponPointer),y - + DefActivationEnd jmp WaitForKeyRelease ; rts - .endp -; ----------------------------------------------------- + +;-------------------------------------------------- .proc calcPosDefensive ; calculate positionOnTheList from the activeWeapon (defensives) +;-------------------------------------------------- ldx tankNr lda ActiveDefenceWeapon,x beq ?noWeaponActive @@ -971,7 +914,7 @@ DefActivationEnd cmp IndexesOfWeaponsL2,y beq ?weaponfound iny - cpy #(last_defensive_____ - first_defensive____)+1 ; maxDefensiveWeapon + cpy #(last_defensive - first_defensive )+1 ; maxDefensiveWeapon bne @- ; not found apparently? ; TODO: check border case (the last weapon) @@ -994,7 +937,7 @@ DefActivationEnd cmp IndexesOfWeaponsL1,y beq ?weaponfound iny - cpy #(last_offensive_____ - first_offensive____) ; maxOffensiveWeapon + cpy #(last_offensive - first_offensive ) ; maxOffensiveWeapon bne @- ; not found apparently? ; TODO: check border case (the last weapon) @@ -1006,11 +949,13 @@ DefActivationEnd sty positionOnTheList rts .endp -; ----------------------------------------------------- + +;-------------------------------------------------- .proc PutLitteChar +;-------------------------------------------------- ; first let's clear both lists from little chars mwa #ListOfWeapons xbyte - ldx #last_defensive_____ ; there are xx lines total + ldx #last_defensive ; there are xx lines total ldy #$00 EraseLoop tya ; lda #$00 @@ -1027,10 +972,10 @@ EraseLoop mwa #ListOfDefensiveWeapons xbyte ldx PositionOnTheList beq SelectList2 ; if there is 0 we add nothing -AddLoop2 - adw xbyte #32 ; narrow screen - dex - bne AddLoop2 +@ + adw xbyte #32 ; narrow screen + dex + bne @- SelectList2 lda #$7f ; little char (tab) - this is the pointer sta (xbyte),y @@ -1048,10 +993,10 @@ CharToList1 mwa #ListOfWeapons xbyte ldx PositionOnTheList beq SelectList1 ; if there is 0 we add nothing -AddLoop1 - adw xbyte #32 ; narrow screen - dex - bne AddLoop1 +@ + adw xbyte #32 ; narrow screen + dex + bne @- SelectList1 lda #$7f ; pointer = little char = (tab) sta (xbyte),y @@ -1059,10 +1004,10 @@ SelectList1 mwa #ListOfWeapons xbyte ldx OffsetDL1 beq SetWindowList1 ; if zero then add nothing -LoopWindow1 - adw xbyte #32 ; narrow screen - dex - bne LoopWindow1 +@ + adw xbyte #32 ; narrow screen + dex + bne @- SetWindowList1 mwa xbyte WeaponsListDL ; and we change Display List @@ -1102,14 +1047,14 @@ NoArrowDown SetDLI DLIinterruptText ; jsr SetDLI for text (names) screen mva #0 TankNr - sta COLBAKS ; set color of background + sta COLBAKS ; set color of background @ tax lda TankStatusColoursTable,x sta COLOR2 ; set color of player name line jsr EnterPlayerName bit escFlag spl:rts - jsr CheckTankCheat + jsr CheckTankCheat inc TankNr lda TankNr cmp NumberOfPlayers @@ -1132,24 +1077,16 @@ NoArrowDown ldx tanknr lda skillTable,x sta difficultyLevel - lda digits+1,x + lda digits+1,x sta NameScreen2+7 - ; clear tank name editor field - not necessary -; ldx #8 -; lda #0 -;@ sta NameAdr,x -; dex -; bpl @- - ; copy existing name and place cursor at end lda TankNr :3 asl tax - + ldy #0 @ lda TanksNames,x -; beq endOfTankName sta NameAdr,y inx iny @@ -1157,34 +1094,33 @@ NoArrowDown bne @- endOfTankName -@ lda NameAdr,y - and #$7f - bne LastNameChar - dey - bpl @- +@ lda NameAdr,y + and #$7f + bne LastNameChar + dey + bpl @- LastNameChar - cpy #7 - beq @+ - iny -@ sty PositionInName + cpy #7 + seq:iny + sty PositionInName CheckKeys jsr HighlightLevel ; setting choosen level of the opponent (Moron, etc) - ldx TankNr - lda JoyNumber,x + ldx TankNr + lda JoyNumber,x tay - lda digits+1,y - sta NameScreen2+11 ; display joystick port number - lda TankShape,x + lda digits+1,y + sta NameScreen2+11 ; display joystick port number + lda TankShape,x tay - lda digits+1,y - sta NameScreen2+15 ; display tank shape number - jsr CursorDisplay + lda digits+1,y + sta NameScreen2+15 ; display tank shape number + jsr CursorDisplay jsr getkey bit escFlag spl:rts - - .IF TARGET = 800 ; only the A800 has a keyboard + + .IF TARGET = 800 ; only the A800 has a keyboard ; is the char to be recorded? ldx #keycodesEnd-keycodes ;table was 38 chars long IsLetter @@ -1200,11 +1136,10 @@ YesLetter sta NameAdr,x inx cpx #$08 ; is there 8 characters? - bne @+ - dex -@ stx PositionInName ; if not, we store + sne:dex + stx PositionInName ; if not, we store jmp CheckKeys - .ENDIF + .ENDIF CheckFurtherX01 ; here we check Tab, Return and Del cmp #@kbcode._ret ; $0c ; Return jeq EndOfNick @@ -1218,19 +1153,19 @@ CheckFurtherX01 ; here we check Tab, Return and Del beq ChangeOfLevel3Up cmp #@kbcode._up ; $e ;cursor up beq ChangeOfLevel3Down - cmp #@kbcode._atari ; atari (inverse) key - jeq ChangeOfShapeUp + cmp #@kbcode._atari ; atari (inverse) key + jeq ChangeOfShapeUp cmp #@kbcode._del ; $34 ; Backspace (del) bne CheckKeys ; handling backing one char ldx PositionInName - beq FirstChar ; ferst char - no go back - cpx #7 - bne NotLastChar + beq FirstChar ; ferst char - no go back + cpx #7 + bne NotLastChar lda NameAdr,x - and #$7f - bne LastIsNotSpace ; last char not empty - first clear last char (no go back) + and #$7f + bne LastIsNotSpace ; last char not empty - first clear last char (no go back) NotLastChar dex LastIsNotSpace @@ -1241,65 +1176,54 @@ FirstChar jmp CheckKeys ;---- ChangeOfJoyUp - ldx TankNr - inc JoyNumber,x - lda JoyNumber,x - and #%00000011 ; max 4 joysticks - sta JoyNumber,x - .IF TARGET = 5200 - beq ChangeOfShapeUp ; change tank shape - .ENDIF + ldx TankNr + inc JoyNumber,x + lda JoyNumber,x + and #%00000011 ; max 4 joysticks + sta JoyNumber,x + .IF TARGET = 5200 + beq ChangeOfShapeUp ; change tank shape + .ENDIF jmp CheckKeys ;---- ChangeOfLevelUp ; change difficulty level of computer opponent inc:lda DifficultyLevel cmp #9 ; 9 levels are possible - bne DoNotLoopLevelUp - mva #$0 DifficultyLevel -DoNotLoopLevelUp + sne:mva #$0 DifficultyLevel ; DoNotLoopLevelUp jmp CheckKeys ;---- ChangeOfLevelDown dec:lda DifficultyLevel - bpl DoNotLoopLevelDown - mva #$8 DifficultyLevel -DoNotLoopLevelDown + spl:mva #$8 DifficultyLevel ; DoNotLoopLevelDown jmp CheckKeys ;---- ChangeOfLevel3Up adb DifficultyLevel #3 - cmp #9 - bcc DoNotLoopLevel3Up - - sbb DifficultyLevel #9 - -DoNotLoopLevel3Up + scc:sbb DifficultyLevel #9 ; DoNotLoopLevel3Up jmp CheckKeys ;---- ChangeOfLevel3Down sbb DifficultyLevel #3 - bpl @+ - adb DifficultyLevel #9 -@ + spl:adb DifficultyLevel #9 jmp CheckKeys ;---- ChangeOfShapeUp - ldx TankNr - inc TankShape,x - lda TankShape,x - cmp #$03 - bne @+ - lda #$00 - sta TankShape,x -@ jmp CheckKeys + ldx TankNr + inc TankShape,x + lda TankShape,x + cmp #$03 + bne @+ + lda #$00 + sta TankShape,x +@ jmp CheckKeys ;---- EndOfNick - ; now check long press joy button (or Return...) + ; now check long press joy button (or Return...) mva #0 pressTimer ; reset WaitForLongPress - lda STRIG0 ; wait only for joy long press - bne ShortJoyPress + lda STRIG0 ; wait only for joy long press + bne ShortJoyPress lda pressTimer cmp #25 ; 1/2s bcc WaitForLongPress @@ -1313,9 +1237,9 @@ ShortJoyPress ldx tanknr lda DifficultyLevel sta skilltable,x - beq NotRobot - lda #$03 ; shape for robotanks - sta TankShape,x + beq NotRobot + lda #$03 ; shape for robotanks + sta TankShape,x NotRobot ; storing name of the tank in the right space ; (without cursor!) @@ -1332,7 +1256,7 @@ NotRobot ; check if all chars are empty (" ") ldy #7 lda #0 -@ ora NameAdr,y +@ ora NameAdr,y and #$7F ; remove inverse (Cursor) dey bpl @- @@ -1340,129 +1264,129 @@ NotRobot beq MakeDefaultName ldy #0 -nextchar04 - lda NameAdr,y - and #$7f ; remove inverse (Cursor) - sta tanksnames,x - inx - iny - cpy #$08 - bne nextchar04 +@ + lda NameAdr,y + and #$7f ; remove inverse (Cursor) + sta tanksnames,x + inx + iny + cpy #$08 + bne @- rts MakeDefaultName -nextchar05 - lda tanksnamesDefault,x - sta tanksnames,x - inx - iny - cpy #$08 - bne nextchar05 +@ + lda tanksnamesDefault,x + sta tanksnames,x + inx + iny + cpy #$08 + bne @- rts .endp ;-------------------------------------------------- .proc CursorDisplay - ldy #7 + ldy #7 CursorLoop - lda NameAdr,y - and #$7f - cpy #0 - bne NotFirstLetter - and #$3f ; First letter should be Capital letter + lda NameAdr,y + and #$7f + cpy #0 + bne NotFirstLetter + and #$3f ; First letter should be Capital letter ; (nice trick does not affect digits) NotFirstLetter - cpy PositionInName - bne @+ + cpy PositionInName + bne @+ ora #$80 ; place cursor -@ sta NameAdr,y - dey - bpl CursorLoop - rts +@ sta NameAdr,y + dey + bpl CursorLoop + rts .endp ;-------------------------------------------------- .proc EnterNameByJoy mva #sfx_keyclick sfx_effect - jsr CursorDisplay - ldy PositionInName - ; now in Y we have PositionInName - ldx #(keycodesEnd-keycodes) + jsr CursorDisplay + ldy PositionInName + ; now in Y we have PositionInName + ldx #(keycodesEnd-keycodes) SearchCharacter - lda NameAdr,y - and #$7f - cmp #$20 - bcc CharOK ; digit or space - cmp #$60 - bcs CharOK ; not capital letter - ora #$40 + lda NameAdr,y + and #$7f + cmp #$20 + bcc CharOK ; digit or space + cmp #$60 + bcs CharOK ; not capital letter + ora #$40 CharOK - cmp scrcodes,x - beq CharacterFound - dex - bpl SearchCharacter - inx + cmp scrcodes,x + beq CharacterFound + dex + bpl SearchCharacter + inx CharacterFound - ; now in X we have Character (index) on PositionInName - ; wait for centered joy + ; now in X we have Character (index) on PositionInName + ; wait for centered joy mva #128-15 pressTimer ; reset (trick) -@ lda STICK0 - and #$0f - cmp #$0f - beq checkjoy - bit pressTimer ; trick (no A change) - bpl @- -checkjoy - lda STICK0 - and #$0f - cmp #$0f - bne JoyNotCentered +@ lda STICK0 + and #$0f + cmp #$0f + beq checkjoy + bit pressTimer ; trick (no A change) + bpl @- +checkjoy + lda STICK0 + and #$0f + cmp #$0f + bne JoyNotCentered notpressedJoy - ;fire - lda STRIG0 - beq checkjoy ; fire still pressed - rts + ;fire + lda STRIG0 + beq checkjoy ; fire still pressed + rts JoyNotCentered - ; this is a place for code :) - cmp #7 - bne NoRight - ; joy right - cpy #7 - beq GoToMainLoop ; the last character - iny - bne GoToMainLoop + ; this is a place for code :) + cmp #7 + bne NoRight + ; joy right + cpy #7 + beq GoToMainLoop ; the last character + iny + bne GoToMainLoop NoRight - cmp #11 - bne NoLeft - ; joy left - lda #0 - sta NameAdr,y - dey - bpl GoToMainLoop - iny - beq GoToMainLoop + cmp #11 + bne NoLeft + ; joy left + lda #0 + sta NameAdr,y + dey + bpl GoToMainLoop + iny + beq GoToMainLoop NoLeft - cmp #14 - bne NoUp - ; joy up - cpx #(keycodesEnd-keycodes-1) - bne @+ - ldx #$00 ; set to the first character index (loop) - beq CharAndMainLoop -@ inx - bne CharAndMainLoop + cmp #14 + bne NoUp + ; joy up + cpx #(keycodesEnd-keycodes-1) + bne @+ + ldx #$00 ; set to the first character index (loop) + beq CharAndMainLoop +@ inx + bne CharAndMainLoop NoUp - cmp #13 - bne EnterNameByJoy ; not down - ; joy down - dex - bpl CharAndMainLoop - ldx #(keycodesEnd-keycodes-1) ; set to the last character index (loop) + cmp #13 + bne EnterNameByJoy ; not down + ; joy down + dex + bpl CharAndMainLoop + ldx #(keycodesEnd-keycodes-1) ; set to the last character index (loop) CharAndMainLoop - lda scrcodes,x - sta NameAdr,y + lda scrcodes,x + sta NameAdr,y GoToMainLoop - sty PositionInName - jmp EnterNameByJoy + sty PositionInName + jmp EnterNameByJoy .endp ;-------------------------------------------------- @@ -1532,24 +1456,24 @@ TooLittle000 dex ;rightnumber ; displaying without leading zeroes (if zeroes exist then display space at this position) ldy #0 - ldx #0 ; digit flag (cut leading zeroes) + ldx #0 ; digit flag (cut leading zeroes) displayloop lda decimalresult,y - cpx #0 - bne noleading0 - cpy #4 - beq noleading0 ; if 00000 - last 0 must stay - cmp zero - bne noleading0 - lda #space - beq displaychar ; space = 0 ! + cpx #0 + bne noleading0 + cpy #4 + beq noleading0 ; if 00000 - last 0 must stay + cmp zero + bne noleading0 + lda #space + beq displaychar ; space = 0 ! noleading0 - inx ; set flag (no leading zeroes to cut) + inx ; set flag (no leading zeroes to cut) displaychar sta (displayposition),y nexdigit iny - cpy #5 + cpy #5 bne displayloop rts @@ -1603,227 +1527,60 @@ displayloop1 rts .endp -;-------------------------------- -.proc DisplayResults ; -;displays results of the round -;using 4x4 font - jsr RoundOverSprites - - - mva #$ff plot4x4color - - ;centering the result screen - mva #((ScreenHeight/2)-(8*4)) ResultY - - - ;upper frame - mva ResultY LineYdraw - jsr TL4x4_top - - adb ResultY #4 ;next line - - ;Header1 - ;Displays round number - lda CurrentRoundNr - cmp RoundsInTheGame - beq GameOver4x4 - - sta decimal - mwa #RoundNrDisplay displayposition - jsr displaybyte ;decimal (byte), displayposition (word) - - mwa #LineHeader1 LineAddress4x4 - mwa #((ScreenWidth/2)-(8*4)) LineXdraw - mva ResultY LineYdraw - jsr TypeLine4x4 - beq @+ ;unconditional jump, because TypeLine4x4 ends with beq - -GameOver4x4 - RmtSong song_round_over - mwa #LineGameOver LineAddress4x4 - mwa #((ScreenWidth/2)-(8*4)) LineXdraw - mva ResultY LineYdraw - jsr TypeLine4x4 - mva #1 GameIsOver - -@ - adb ResultY #4 ;next line - - ;Empty line - mva ResultY LineYdraw - jsr TL4x4_empty - - adb ResultY #2 ;next line - - - ;Header2 - mwa #LineHeader2 LineAddress4x4 - mwa #((ScreenWidth/2)-(8*4)) LineXdraw - mva ResultY LineYdraw - jsr TypeLine4x4 - - adb ResultY #4 ;next line - - ;Empty line - mva ResultY LineYdraw - jsr TL4x4_empty - - sbb ResultY #2 ;next line (was empty) - - ldx NumberOfPlayers ;we start from the highest (best) tank - dex ;and it is the last one - stx ResultOfTankNr ;in TankSequence table - - mwa #TanksNames tempXROLLER - -ResultOfTheNextPlayer - ldx ResultOfTankNr ;we are after a round, so we can use TankNr - lda TankSequence,x ;and we keep here real number if the tank - sta TankNr ;for which we are displaying results - - - - - adb ResultY #4 ;next line - - ;there are at least 2 players, so we can safely - ;start displaying the result - - lda #3 ;it means | - sta ResultLineBuffer - - ldy TankNr - lda ResultsTable,y - sta decimal - mva #0 decimal+1 - mwa #(ResultLineBuffer+8) displayposition - jsr displaydec5 ;decimal (byte), displayposition (word) - - ; overwrite the second digit of the points (max 255) - ;it means ":" - mva #26 ResultLineBuffer+9 - - ldx #0 - lda TankNr - asl - asl ; times 8, because it is lengtgh - asl ; of the names of the tanks - tay - -TankNameCopyLoop - lda (tempXROLLER),y ;XROLLER is not working now - and #$3f ;always CAPITAL letters - inx - sta ResultLineBuffer,x - iny - cpx #8 ; end of name - bne TankNameCopyLoop - ; last letter of tank name overwrites first digit of the points (max 255) - - - ;just after the digits - ;it means | - mva #$3 ResultLineBuffer+13 - - ;result line display - mwa #ResultLineBuffer LineAddress4x4 - mwa #((ScreenWidth/2)-(8*4)) LineXdraw - mva ResultY LineYdraw - jsr TypeLine4x4 - - adb ResultY #4 ;next line - - ;Empty line - mva ResultY LineYdraw - jsr TL4x4_empty - - dec ResultOfTankNr - bmi FinishResultDisplay - - sbb ResultY #2 ;distance between lines is smaller - - jmp ResultOfTheNextPlayer - -FinishResultDisplay - mva ResultY LineYdraw - ;jmp TL4x4_bottom ; just go -.endp - -.proc TL4x4_bottom - ;bottom of the frame - mwa #LineBottom LineAddress4x4 - mwa #((ScreenWidth/2)-(8*4)) LineXdraw - jmp TypeLine4x4 ; jsr:rts -.endp - -.proc TL4x4_top - ;bottom of the frame - mwa #LineTop LineAddress4x4 - mwa #((ScreenWidth/2)-(8*4)) LineXdraw - jmp TypeLine4x4 ; jsr:rts -.endp - -.proc TL4x4_empty - ;empty frame - mwa #LineEmpty LineAddress4x4 - mwa #((ScreenWidth/2)-(8*4)) LineXdraw - jmp TypeLine4x4 ; jsr:rts -.endp - ;-------------------------------------------------- .proc GameOverScreen ;-------------------------------------------------- - jsr MakeDarkScreen + jsr MakeDarkScreen jsr WaitForKeyRelease jsr ClearScreen jsr ClearPMmemory - jsr PrepareCredits - jsr GameOverResultsClear + jsr PrepareCredits + jsr GameOverResultsClear jsr CopyFromPurchaseAndGameOver mwa #GameOverDL dlptrs - mva #$ff ScrollFlag ; credits scroll on + mva #$ff ScrollFlag ; credits scroll on lda #%00111110 ; normal screen width, DL on, P/M on sta dmactls lda #%00100100 ; playfield before P/M sta GPRIOR - jsr SetPMWidth + jsr SetPMWidth jsr ColorsOfSprites mva #0 COLOR1 - sta COLBAKS ; set color of background - sta CreditsVScrol - sta JoystickNumber ; set joystick port for player + sta COLBAKS ; set color of background + sta CreditsVScrol + sta JoystickNumber ; set joystick port for player mva #TextForegroundColor COLOR2 SetDLI DLIinterruptGameOver ; jsr SetDLI for Game Over screen - ; make text and color lines for each tank + ; make text and color lines for each tank ldx NumberOfPlayers ;we start from the highest (best) tank dex ;and it is the last one stx ResultOfTankNr ;in TankSequence table - ldy #0 ;witch line we are coloring + ldy #0 ;witch line we are coloring FinalResultOfTheNextPlayer ldx ResultOfTankNr ;we are after a round, so we can use TankNr lda TankSequence,x ;and we keep here real number if the tank - tax + tax stx TankNr ;for which we are displaying results - lda TankStatusColoursTable,x - sta GameOverColoursTable,y - ; Y - line number (from 0 to 5) - ; X - TanNr - ; let's make texts - phy - ; first calculate adres first byte of line - mwa #GameOverResults temp -@ dey - bmi LineAdresReady - adw temp #40 - jmp @- + lda TankStatusColoursTable,x + sta GameOverColoursTable,y + ; Y - line number (from 0 to 5) + ; X - TanNr + ; let's make texts + phy + ; first calculate adres first byte of line + mwa #GameOverResults temp +@ dey + bmi LineAdresReady + adw temp #40 + jmp @- LineAdresReady - ; put position of tank on the screen - pla - pha ; now we have line number in A register - ldy #1 - tax - lda zero+1,x - sta (temp),y + ; put position of tank on the screen + pla + pha ; now we have line number in A register + ldy #1 + tax + lda zero+1,x + sta (temp),y ; puts name of the tank on the screen ldy #$03 lda TankNr @@ -1836,57 +1593,75 @@ NextChar iny cpy #$08+3 bne NextChar - ; put big points on the screen + ; put big points on the screen ldx TankNr lda ResultsTable,x sta decimal mva #0 decimal+1 adw temp #12 displayposition jsr displaydec5 - mva #0 displayposition ; overwrite first digit - ; put hits points on the screen - sta decimal+1 ; pozor!!! A=0 + mva #0 displayposition ; overwrite first digit + ; put hits points on the screen + sta decimal+1 ; pozor!!! A=0 ldx TankNr lda DirectHits,x sta decimal -; lda DirectHitsH,x ; one byte enough +; lda DirectHitsH,x ; one byte enough adw temp #19 displayposition jsr displaydec5 - mva #0 displayposition ; overwrite first digit - ; put earned money on the screen + mva #0 displayposition ; overwrite first digit + ; put AI symbol or joystick ldx TankNr + lda SkillTable,x + tay + bne ThisIsAI + ldy JoyNumber,x + iny ; tricky +ThisIsAI + lda digits,y + ldy #39 + sta (temp),y ; AI level or joy number + ldy #$0a ; Joystick symbol + lda SkillTable,x + beq NotAItank + ldy #$5e ; Computer symbol +NotAItank + tya + ldy #38 + sta (temp),y + ; put earned money on the screen lda EarnedMoneyL,x sta decimal - lda EarnedMoneyH,x + lda EarnedMoneyH,x sta decimal+1 adw temp #30 displayposition jsr displaydec5 - ldy #35 - lda zero - sta (temp),y ; and last zero - ply - iny + ldy #35 + lda zero + sta (temp),y ; and last zero + ply + iny dec ResultOfTankNr jpl FinalResultOfTheNextPlayer MakeBlackLines - cpy #$06 - beq AllLinesReady - lda #0 ; black line color for rest of tanks - sta GameOverColoursTable,y - iny - bne MakeBlackLines + cpy #$06 + beq AllLinesReady + lda #0 ; black line color for rest of tanks + sta GameOverColoursTable,y + iny + bne MakeBlackLines AllLinesReady ldx #(MaxPlayers-1) MakeAllTanksVisible lda #99 sta eXistenZ,x - lda #0 - sta ActiveDefenceWeapon,x + lda #0 + sta ActiveDefenceWeapon,x dex bpl MakeAllTanksVisible - jsr SetStandardBarrels + jsr SetStandardBarrels - ; start music and animations + ; start music and animations RmtSong song_ending_looped ; initial tank positions randomization ldx #(MaxPlayers-1) ;maxNumberOfPlayers-1 @@ -1894,23 +1669,21 @@ MakeAllTanksVisible jsr RandomizeTankPos dex bpl @- -MainTanksFloatingLoop +MainTanksFloatingLoop ; main tanks floating loop ldx #(MaxPlayers-1) ;maxNumberOfPlayers-1 -AllTanksFloatingDown +AllTanksFloatingDown stx TankNr lda Ytankstable,x - cmp #(72-7) ; tank under screen - no erase - bcs NoEraseTank - mva #1 Erase - jsr DrawTankNr - mva #0 Erase - sta ATRACT ; reset atract mode + cmp #(72-7) ; tank under screen - no erase + bcs NoEraseTank + jsr ClearTankNr + sta ATRACT ; reset atract mode NoEraseTank - ldx TankNr + ldx TankNr inc Ytankstable,x - lda ActiveDefenceWeapon,x - beq NotFastTank + lda ActiveDefenceWeapon,x + beq NotFastTank :3 inc Ytankstable,x NotFastTank lda Ytankstable,x @@ -1923,127 +1696,156 @@ NotFastTank TankUnderScreen jsr RandomizeTankPos TankOnScreen - jsr DrawTankNr + jsr PutTankNr DrawOnlyParachute - lda ActiveDefenceWeapon,x - bne FastTank + lda ActiveDefenceWeapon,x + bne FastTank jsr DrawTankParachute FastTank ; ldx TankNr dex bpl AllTanksFloatingDown - jsr IsKeyPressed + jsr IsKeyPressed bne MainTanksFloatingLoop ; neverending loop - mva #$00 ScrollFlag ; credits scroll off - jsr MakeDarkScreen - jsr GameOverResultsClear - rts + mva #$00 ScrollFlag ; credits scroll off + jsr MakeDarkScreen + jmp GameOverResultsClear + ; rts RandomizeTankPos - randomize 10 (32-7) ; 10 not 8 - barrel !! :) + randomize 10 (32-7) ; 10 not 8 - barrel !! :) sta Ytankstable,x randomize 0 180 sta AngleTable,x randomize 0 (49-8) - ; x correction for P/M - ; -- - .IF XCORRECTION_FOR_PM = 1 + ; x correction for P/M + ; -- + .IF XCORRECTION_FOR_PM = 1 and #%11111110 - .ENDIF - ; -- + .ENDIF + ; -- clc adc XtankOffsetGO_L,x sta XtankstableL,x lda XtankOffsetGO_H,x adc #0 sta XtankstableH,x - lda random - cmp #32 ; like 1:8 - bcc NowFastTank - lda #0 - sta ActiveDefenceWeapon,x + lda random + cmp #32 ; like 1:8 + bcc NowFastTank + lda #0 + sta ActiveDefenceWeapon,x rts NowFastTank - lda #1 - sta ActiveDefenceWeapon,x + lda #1 + sta ActiveDefenceWeapon,x rts GameOverResultsClear - lda #$00 - tax -@ sta GameOverResults,x - inx - cpx #(6*40)+1 - bne @- - rts + lda #$00 + tax +@ sta GameOverResults,x + inx + cpx #(6*40)+1 + bne @- + rts PrepareCredits - ; Rewrites credits and places it in the middle of each line. - mwa #CreditsStart temp ; from - mwa #Credits temp2 ; to + ; Rewrites credits and places it in the middle of each line. + mwa #CreditsStart temp ; from + mwa #Credits temp2 ; to MainRewriteLoop - ldy #0 - cpw temp #CreditsEnd - beq EndOfCredits - ; count characters in this line -@ lda (temp),y - bmi LastCharFound - iny - bne @- + ldy #0 + cpw temp #CreditsEnd + beq EndOfCredits + ; count characters in this line +@ lda (temp),y + bmi LastCharFound + iny + bne @- LastCharFound - ; in Y number of characters reduced by 1 - ; let's count how many spaces add before the text - sec - sty magic - lda #40 - sbc magic - lsr ; now in A we have number of spaces in front - sta magic - ldy #0 - tya - tax + ; in Y number of characters reduced by 1 + ; let's count how many spaces add before the text + sec + sty magic + lda #40 + sbc magic + lsr ; now in A we have number of spaces in front + sta magic + ldy #0 + tya + tax FirstSpaces - sta (temp2),y ; fill the area in front of the text with spaces - iny - cpy magic - bne FirstSpaces + sta (temp2),y ; fill the area in front of the text with spaces + iny + cpy magic + bne FirstSpaces MainText - lda (temp,x) - sta (temp2),y ; rewrite the text to a new place - bmi LastCharWritten - inw temp - iny - bne MainText + lda (temp,x) + sta (temp2),y ; rewrite the text to a new place + bmi LastCharWritten + inw temp + iny + bne MainText LastCharWritten - inw temp - and #%01111111 ; remove inverse - sta (temp2),y - iny - txa ; space to A (0) + inw temp + and #%01111111 ; remove inverse + sta (temp2),y + iny + txa ; space to A (0) LastSpaces - sta (temp2),y ; fill the area behind the text with spaces - iny - cpy #40 - bne LastSpaces + sta (temp2),y ; fill the area behind the text with spaces + iny + cpy #40 + bne LastSpaces NextLine - adw temp2 #40 - jmp MainRewriteLoop + adw temp2 #40 + jmp MainRewriteLoop EndOfCredits - mwa #Credits DLCreditsAddr ; set address in DL to first line - rts + mwa #Credits DLCreditsAddr ; set address in DL to first line + rts +.endp +;------------------------------------------------- +.proc PutTankNameOnScreen +;------------------------------------------------- +; puts name of the tank on the screen + ldy #$00 +; lda TankNr + txa ; TankNr in X ! + asl + asl + asl ; 8 chars per name + tax +NextChar02 + lda tanksnames,x + sta statusBuffer+7,y + inx + iny + cpy #$08 + bne NextChar02 + ;========================= + ; displaying number of active controller port or AI level + ;========================= + ldx TankNr + ldy #$5e ; Computer symbol + lda SkillTable,x + tax + bne ThisIsAI + ldy #$0a ; Joystick symbol + ldx JoystickNumber + inx ; tricky +ThisIsAI + sty statusBuffer+16 + lda digits,x + sta statusBuffer+17 +; rts .endp ;------------------------------------------------- .proc DisplayStatus ;------------------------------------------------- - ;========================= - ; displaying number of active controller port - ;========================= - ldy JoystickNumber - lda digits+1,y - sta statusBuffer+17 - + ldx TankNr + ;========================= ;displaying symbol of the weapon ;========================= - ldx TankNr ldy ActiveWeapon,x lda WeaponSymbols,y sta statusBuffer+19 @@ -2070,7 +1872,7 @@ EndOfCredits aslw temp dey bpl @- - + adw temp #NamesOfWeapons ldy #15 @ @@ -2082,11 +1884,11 @@ EndOfCredits ;========================= ;displaying name of the defence weapon (if active) ;========================= - lda AutoDefenseFlag,x ; Auto Defense symbol (space or "A" in inverse) - bpl @+ - lda #$5e ; Auto Defense symbol + lda AutoDefenseFlag,x ; Auto Defense symbol (space or "A" in inverse) + bpl @+ + lda #$5e ; Auto Defense symbol @ - sta statusBuffer+80+21 + sta statusBuffer+80+21 lda #$08 ; ( sta statusBuffer+80+22 lda #$09 ; ) @@ -2098,7 +1900,7 @@ EndOfCredits sta statusBuffer+80+22 sta statusBuffer+80+39 mwa #emptyLine temp - jmp ClearingOnly + jmp ClearingOnly ActiveDefence sta temp ;get back number of the weapon mva #0 temp+1 @@ -2108,7 +1910,7 @@ ActiveDefence aslw temp dey bpl @- - + adw temp #NamesOfWeapons ClearingOnly ldy #15 @@ -2148,22 +1950,22 @@ ClearingOnly jsr displaybyte lda #$09 ; ) sta statusBuffer+40+13 -NoDefenceWeapon +NoDefenceWeapon NoShieldEnergy ;========================= ; display Wind ;========================= mwa Wind temp - lda #space + lda #space bit Wind+3 ; highest byte of 4 byte wind bmi DisplayLeftWind - sta statusBuffer+80+17 ; (space) char + sta statusBuffer+80+17 ; (space) char lda #$7f ; (tab) char sta statusBuffer+80+20 bne DisplayWindValue DisplayLeftWind - sta statusBuffer+80+20 ; (space) char + sta statusBuffer+80+20 ; (space) char lda #$7e ;(del) char sta statusBuffer+80+17 sec ; Wind = -Wind @@ -2179,7 +1981,7 @@ DisplayWindValue sta decimal mwa #statusBuffer+80+18 displayposition jsr displaybyte - + ;========================= ;display round number ;========================= @@ -2203,7 +2005,7 @@ DisplayWindValue ;display Angle ;========================= displayAngle - ldy #space + ldy #space ldx TankNr lda AngleTable,x cmp #90 @@ -2225,7 +2027,7 @@ AngleToLeft sty statusBuffer+40+25 ; (space) character lda #$7e ;(del) char sta statusBuffer+40+22 - bne AngleDisplay + bne AngleDisplay VerticallyUp ; now we have value 90 sta decimal @@ -2235,25 +2037,7 @@ VerticallyUp AngleDisplay mwa #statusBuffer+40+23 displayposition jsr displaybyte - ldx TankNr - rts -.endp -;------------------------------------------------- -.proc PutTankNameOnScreen -; puts name of the tank on the screen - ldy #$00 - lda TankNr - asl - asl - asl ; 8 chars per name - tax -NextChar02 - lda tanksnames,x - sta statusBuffer+7,y - inx - iny - cpy #$08 - bne NextChar02 + ldx TankNr rts .endp ;------------------------------------------------- @@ -2263,7 +2047,7 @@ NextChar02 dey lda gameOverSpritesTop,y sta temp - + ; clean the whole sprite lda #0 tax @@ -2271,11 +2055,11 @@ NextChar02 sta PMGraph+$500,x dex bne @- - + lda #$01 sta sizep0 ; P0-P1 widths sta sizep0+1 - + ; set background lda #$ff ldx #100+7 ; top of the sprites @@ -2287,10 +2071,10 @@ NextChar02 GOSbeg = 112 mva #GOSbeg hposp0 mva #GOSbeg+12 hposp0+1 - + mva #15 PCOLR0 sta PCOLR1 - + rts .endp diff --git a/C64/gr_basics.asm b/C64/gr_basics.asm new file mode 100644 index 0000000..8a175cf --- /dev/null +++ b/C64/gr_basics.asm @@ -0,0 +1,708 @@ +.IF *>0 ;this is a trick that prevents compiling this file alone + +; Basic hardware-dependent graphics routines. + +; ----------------------------------------- +.proc unPlot +; plots a point and saves the plotted byte, reverts the previous plot. +; ----------------------------------------- + ldx #0 ; only one pixel +unPlotAfterX + stx WhichUnPlot + + ; first remake the oldie + lda oldplotL,x + sta oldplot + lda oldplotH,x + sta oldplot+1 + + ldy #0 + lda oldora,x + sta (oldplot),y + + + ; is it not out of the screen ???? + cpw ydraw #screenheight + jcc CheckX + mwa #0 ydraw +CheckX + cpw xdraw #screenwidth + jcs EndOfUnPlot +MakeUnPlot + ; let's count coordinates taken from xdraw and ydraw + lda xdraw + and #%11111000 + ;sta xbyte + ;--- + ldx ydraw + clc + adc linetableL,x + sta xbyte + sta oldplot + lda linetableH,x + adc xdraw+1 + sta xbyte+1 + sta oldplot+1 + + lda xdraw + and #$7 + tax + ldy #0 + + lda color + bne ClearUnPlot + + ;plotting here + lda (xbyte),y + sta OldOraTemp + ora bittable,x + sta (xbyte),y + bne ContinueUnPlot ; allways <>0 +ClearUnPlot + lda (xbyte),y + sta OldOraTemp + and bittable2,x + sta (xbyte),y +ContinueUnPlot + ldx WhichUnPlot + lda OldOraTemp + sta oldora,x + lda oldplot + sta oldplotL,x + lda oldplot+1 + sta oldplotH,x + ; and now we must solve the problem of several plots + ; in one byte + ldx #4 + ldy WhichUnPlot +LetsCheckOverlapping + cpx WhichUnPlot + beq SkipThisPlot + lda oldplotL,x + cmp oldplotL,y + bne NotTheSamePlot + lda oldplotH,x + cmp oldplotH,y + bne NotTheSamePlot + ; the pixel is in the same byte so let's take correct contents + lda oldora,x + sta oldora,y +NotTheSamePlot +SkipThisPlot + dex + bpl LetsCheckOverlapping +EndOfUnPlot + rts +.endp + +; ----------------------------------------- +.proc plot ;plot (xdraw, ydraw, color) +; color == 1 --> put pixel +; color == 0 --> erase pixel +; this is one of the most important routines in the whole +; game. If you are going to speed up the game, start with +; plot - it is used by every single effect starting from explosions +; through line drawing and small text output!!! +; +; Optimized by 0xF (Fox) THXXXX!!! + +; ----------------------------------------- + ; is it not over the screen ??? + cpw ydraw #(screenheight+1); changed for one additional line. cpw ydraw #(screenheight-1) + bcs unPlot.EndOfUnPlot ;nearest RTS +CheckX02 + cpw xdraw #screenwidth + bcs EndOfPlot +MakePlot + ; let's calculate coordinates from xdraw and ydraw + + lda xdraw + and #%11111000 + ;sta xbyte + ;--- + ldx ydraw + clc + adc linetableL,x + sta xbyte + lda linetableH,x + adc xdraw+1 + sta xbyte+1 + + lda xdraw + and #$7 + tax + ldy #0 + lda color + bne ClearPlot + + lda (xbyte),y + ora bittable,x + sta (xbyte),y +EndOfPlot + rts +ClearPlot + lda (xbyte),y + and bittable2,x + sta (xbyte),y + rts +.endp + +; ----------------------------------------- +.proc point_plot +; ----------------------------------------- + ; checks state of the pixel (coordinates in xdraw and ydraw) + ; result is in A (zero or appropriate bit is set) + + ; let's calculate coordinates from xdraw and ydraw + + lda xdraw + and #%11111000 + ;sta xbyte + ;--- + ldx ydraw + clc + adc linetableL,x + sta xbyte + lda linetableH,x + adc xdraw+1 + sta xbyte+1 + + lda xdraw + and #$7 + tax + ldy #0 + lda (xbyte),y + eor #$ff + and bittable,x + rts +.endp +;-------------------------------------------------- +.proc drawmountains +;-------------------------------------------------- + mwa #0 xdraw + mwa #mountaintable modify + mva #1 color + +drawmountainsloop + ldy #0 + lda (modify),y + cmp #screenheight + beq NoMountain + sta ydraw + sty ydraw+1 +.IF FASTER_GRAF_PROCS = 1 +; there was Drawline proc + lda #screenheight + sec + sbc ydraw + sta tempbyte01 + jsr plot.MakePlot + ; X - index in bittable (number of bit) and nothing more (for use) in C64 :) +; jmp IntoDraw ; jumps inside Draw routine + ; because one pixel is already plotted (and who cares? :) ) +@ + lda (xbyte),y + and bittable2,x + sta (xbyte),y +;IntoDraw + inc ydraw + lda xdraw + and #%11111000 + ;sta xbyte + ;--- + ldy ydraw + clc + adc linetableL,y + sta xbyte + lda linetableH,y + adc xdraw+1 + sta xbyte+1 + ldy #0 + dec tempbyte01 + bne @- +; end of Drawline proc +.ELSE +; there was Drawline proc +drawline + jsr plot.MakePlot + inc ydraw + lda ydraw + cmp #screenheight + bne drawline +; end of Drawline proc +.ENDIF +NoMountain + inw modify + inw xdraw + cpw xdraw #screenwidth + bne drawmountainsloop + rts +.endp +;-------------------------------------------------- +.proc TypeChar +; puts char on the graphics screen +; in: CharCode +; in: left LOWER corner of the char coordinates (xdraw, ydraw) +;-------------------------------------------------- + ; char to the table + lda CharCode + sta fontind + lda #$00 + sta fontind+1 + ; char intex times 8 + aslw fontind + rolw fontind + rolw fontind + + adw fontind #TankFont + + ; and 8 bytes to the table + ldy #7 +CopyChar + lda (fontind),y + eor #$ff + sta char1,y + lda #$ff + sta char2,y + dey + bpl CopyChar + ; and 8 subsequent bytes as a mask + adw fontind #8 + ldy #7 +CopyMask + lda (fontind),y + eor #$ff + sta mask1,y + lda #$00 + sta mask2,y + dey + bpl CopyMask + +.IF FASTER_GRAF_PROCS = 1 + ; mask preparation and character shifting + lda xdraw + and #$7 + tax + beq MaskOK00 +MakeMask00 + .rept 8 + lsr mask1+# + ror mask2+# + .endr + sec + .rept 8 + ror char1+# ; in second (and next) lines we have C=1 - one SEC enough + ror char2+# + .endr + dex + bne MakeMask00 +MaskOK00 + lda ydraw + sec + sbc #7 + sta ydraw + ; X = 0 ! + lda Erase + beq CharLoopi ; it works, because x=0 + lda #$ff + ldx #7 +EmptyChar + sta char1,x + sta char2,x + dex + bpl EmptyChar + ldx #0 +CharLoopi + ; calculating coordinates from xdraw and ydraw + ldy ydraw + lda xdraw + and #%11111000 + clc + adc linetableL,y + sta xbyte + lda linetableH,y + adc xdraw+1 + sta xbyte+1 +;-- + ldy #0 + lda (xbyte),y + ora mask1,x + and char1,x + sta (xbyte),y + ldy #8 + lda (xbyte),y + ora mask2,x + and char2,x + sta (xbyte),y + inc ydraw + inx + cpx #8 + bne CharLoopi +.ELSE + mvx #7 temp ; line counter (Y) +CharLoop1 + mva #7 temp+1 ; pixel counter (X) +CharLoop2 + mva #0 color + rol mask1,x + bcc NoMaskNoPlot + rol char1,x + bcs NoPlot +MakeCharPlot + lda Erase + bne ErasingChar + inc color +ErasingChar +NoPlot + jsr plot.MakePlot +AfterCharPlot + inw xdraw + ldx temp + dec temp+1 + bpl CharLoop2 + sec + sbw xdraw #8 + dec ydraw + ldx temp + dex + stx temp + bpl CharLoop1 + clc + lda ydraw + adc #8 + sta ydraw + bne EndPutChar +NoMaskNoPlot + rol char1,x + jmp AfterCharPlot +.ENDIF +EndPutChar + rts +.endp + +;-------------------------------------------------- +.proc PutChar4x4 +; puts 4x4 pixels char on the graphics screen +; in: dx, dy (LOWER left corner of the char) +; in: CharCode4x4 (.sbyte) +; in: plot4x4color (0/255) +; all pixels are being drawn +; (empty and not empty) +;-------------------------------------------------- + cpw dy #(screenheight-1) + jcs TypeChar.EndPutChar ;nearest RTS + cpw dy #(4) + jcc TypeChar.EndPutChar ;nearest RTS + cpw dx #(screenwidth-4) + jcs TypeChar.EndPutChar ;nearest RTS + ; checks ommited. + ; char to the table + lda CharCode4x4 + and #%00000001 + beq Upper4bits + lda #$ff ; better option to check (nibbler4x4 = $00 or $ff) +Upper4bits + sta nibbler4x4 + lda CharCode4x4 + lsr + sta fontind + lda #$00 + sta fontind+1 + + adw fontind #font4x4 + + ; and 4 bytes to the table + ldy #0 + ldx #3 +CopyChar + lda (fontind),y ; Y must be 0 !!!! + bit nibbler4x4 + bpl GetUpper4bits + :4 rol +GetUpper4bits + ora #$0f + sta char1,x + lda #$ff + sta char2,x + ; and 4 bytes as a mask + lda #$f0 + sta mask1,x + lda #$00 + sta mask2,x + adw fontind #32 ; next byte of 4x4 font + dex + bpl CopyChar + +.IF FASTER_GRAF_PROCS = 1 + ; mask preparation and character shifting + lda dx + and #$7 + tax + beq MaskOK01 +MakeMask01 + .rept 4 + lsr mask1+# + ror mask2+# + .endr + sec + .rept 4 + ror char1+# ; in second (and next) lines we have C=1 - one SEC enough + ror char2+# + .endr + dex + bne MakeMask01 +MaskOK01 + lda dy + sec + sbc #3 + sta dy + ldx #0 +CharLoopi4x4 + ; calculating coordinates from xdraw and ydraw + ldy dy + lda dx + and #%11111000 + clc + adc linetableL,y + sta xbyte + lda linetableH,y + adc dx+1 + sta xbyte+1 +;-- + ldy #0 + lda (xbyte),y + ora mask1,x + bit plot4x4color + bpl PutInColor0_1 ; only mask - no char + and char1,x +PutInColor0_1 + sta (xbyte),y + ldy #8 + lda (xbyte),y + ora mask2,x + bit plot4x4color + bpl PutInColor0_2 ; only mask - no char + and char2,x +PutInColor0_2 + sta (xbyte),y + inc dy + inx + cpx #4 + bne CharLoopi4x4 +.ELSE + mwa xdraw char2 + mwa ydraw mask2 + mva color mask2+2 + mwa dx xdraw + mwa dy ydraw + mvx #3 temp ; line counter (Y) +CharLoop1 + mva #3 temp+1 ; pixel counter (X) +CharLoop2 + mva #0 color + rol mask1,x + bcc NoMaskNoPlot + rol char1,x + bcs NoPlot +MakeCharPlot + lda plot4x4color + beq ErasingChar + inc color +ErasingChar +NoPlot + jsr plot.MakePlot +AfterCharPlot + inw xdraw + ldx temp + dec temp+1 + bpl CharLoop2 + sec + sbw xdraw #4 + dec ydraw + ldx temp + dex + stx temp + bpl CharLoop1 + mwa char2 xdraw + mwa mask2 ydraw + mva mask2+2 color + bpl EndPut4x4 +NoMaskNoPlot + rol char1,x + jmp AfterCharPlot +.ENDIF +EndPut4x4 + rts +.endp + +;-------------------------------------------------- +.proc ClearScreen +;-------------------------------------------------- + mwa #displayC64 temp + ldy #0 +@ lda #$ff + sta (temp),y + inw temp + cpw temp #displayC64+screenheight*screenBytes+1 + bne @- + rts +.endp + +;-------------------------------------------------- +.proc GenerateLineTable + + mwa #displayC64 temp + mwa #linetableL temp2 + mwa #linetableH modify + ldy #0 + ldx #0 +@ lda temp + sta (temp2),y + lda temp+1 + sta (modify),y + cpx #7 + bne NotChar + ldx #0 + adw temp #(320-7) + jmp next8lines +NotChar + inw temp + inx +next8lines + iny + cpy #screenheight+1 + bne @- + rts +.endp +;-------------------------------------------------- +.proc SetMainScreen + lda #$b ; Grey background and border + lda WallsType + :4 rol + sta $d020 + sta $d021 + + lda $dd00 ; Set video bank to start at 0 + and #252 + ora #3 + sta $dd00 + lda #$18 + sta $d018 + +; SwitchVICBank(0) +; SetScreenMemory($2000) + SetHiresBitmapMode ; Hires mode on + lda #$00 + sta 53281 + ; clear color RAM + ldx #0 +@ lda #1 + sta $d800,x + sta $d900,x + sta $da00,x + sta $db00,x + lda #$0f + sta $0400,x + sta $0500,x + sta $0600,x + sta $0700,x + inx + bne @- + rts +.endp +;-------------------------------------------------- + + +; ******* This is weapon .... but ... ******* +; ------------------------------------------------- +.proc AtomicWinter +; ------------------------------------------------- +; This routine is run from inside of the main loop +; and replaces Shoot and Flight routines +; X and TankNr - index of shooting tank +; ------------------------------------------------- + mva #sfx_sandhog sfx_effect +.IF FASTER_GRAF_PROCS = 1 + mvy #0 magic ; byte counter (from 0 to 39) +NextColumn + ; big loop - we repat internal loops for each column of bytes + ldx #120 ; line counter (from 0 to 60 ) + ; first loop - inverse column of bytes for a while +NextLine1 + jsr InverseScreenByte + dex + dex + bpl NextLine1 + ; + jsr WaitOneFrame ; wait uses A only + ; second loop - inverse again and put random "snow" to column of bytes + ldx #120 + mva #$55 magic+1 +NextLine2 + jsr InverseScreenByte + lda random + ora magic+1 + and (temp),y + sta (temp),y + lda magic+1 + eor #$ff + sta magic+1 + dex + dex + bpl NextLine2 + ; and go to next column + inc magic + ldy magic + cpy #40 + bne NextColumn +.ELSE + mva #1 color + mwa #120 ydraw +NextLineSlow + lda #0 + sta xdraw + sta xdraw+1 +NextPixelSlow + bit random + bpl NoPlot + bvc NoPlot + jsr plot.MakePlot +NoPlot + inw xdraw + cpw xdraw #screenwidth + bne NextPixelSlow + dec ydraw + dec ydraw + bpl NextLineSlow +.ENDIF + ; and we have "snow" :) + lda #0 + ldx TankNr + sta ActiveDefenceWeapon,x ; deactivate Nuclear Winter + jsr SetFullScreenSoilRange + jmp SoilDown2.NoClearTanks + ; rts + + ; in order to optimize the fragment repeated in both internal loops + ; we save 15 bytes :) +InverseScreenByte + ldy magic + sty temp + ldy #0 + sty temp+1 + aslw temp + rolw temp + rolw temp + lda temp + adc LineTableL,x + sta temp + lda LineTableH,x + adc temp+1 + sta temp+1 + lda (temp),y + eor #$ff + sta (temp),y + rts +.endp + +.ENDIF \ No newline at end of file diff --git a/C64/interrupts.asm b/C64/interrupts.asm new file mode 100644 index 0000000..ff565f7 --- /dev/null +++ b/C64/interrupts.asm @@ -0,0 +1,22 @@ +; @com.wudsn.ide.asm.mainsourcefile=scorch.asm + + .IF *>0 ;this is a trick that prevents compiling this file alone + +DLIinterruptGraph = 0 +;-------------------------------------------------- +.macro SetDLI +; SetDLI #WORD +; Initialises Display List Interrupts + LDY # <:1 + LDX # >:1 + jsr _SetDLIproc +.endm +.proc _SetDLIproc +; LDA #$C0 +; STY VDSLST +; STX VDSLST+1 +; STA NMIEN + rts +.endp + + .ENDIF diff --git a/C64/lib/C64SYS.ASM b/C64/lib/C64SYS.ASM new file mode 100644 index 0000000..47d3f96 --- /dev/null +++ b/C64/lib/C64SYS.ASM @@ -0,0 +1,49 @@ +vic_spr0_x = $D000 +vic_spr0_y = $D001 +vic_spr1_x = $D002 +vic_spr1_y = $D003 +vic_spr2_x = $D004 +vic_spr2_y = $D005 +vic_spr3_x = $D006 +vic_spr3_y = $D007 +vic_spr4_x = $D008 +vic_spr4_y = $D009 +vic_spr5_x = $D00A +vic_spr5_y = $D00B +vic_spr6_x = $D00C +vic_spr6_y = $D00D +vic_spr7_x = $D00E +vic_spr7_y = $D00F +vic_spr_hi_x = $D010 +vic_cr1 = $D011 +vic_raster = $D012 +vic_lp_x = $D013 +vic_lp_y = $D014 +vic_spr_ena = $D015 +vic_cr2 = $D016 +vic_spr_exp_y = $D017 +vic_mem = $D018 +vic_irq = $D019 +vic_irq_ena = $D01A +vic_spr_dp = $D01B +vic_spr_mcolor = $D01C +vic_spr_exp_x = $D01D +vic_spr_ss_col = $D01E +vic_spr_sd_col = $D01F +vic_border = $D020 +vic_bg_color0 = $D021 +vic_bg_color1 = $D022 +vic_bg_color2 = $D023 +vic_bg_color3 = $D024 +vic_spr_color1 = $D025 +vic_spr_color2 = $D026 +vic_spr0_color = $D027 +vic_spr1_color = $D028 +vic_spr2_color = $D029 +vic_spr3_color = $D02A +vic_spr4_color = $D02B +vic_spr5_color = $D02C +vic_spr6_color = $D02D +vic_spr7_color = $D02E + +RANDOM = $D41B diff --git a/C64/lib/C64_ATARISYS.ASM b/C64/lib/C64_ATARISYS.ASM new file mode 100644 index 0000000..bb343bb --- /dev/null +++ b/C64/lib/C64_ATARISYS.ASM @@ -0,0 +1,352 @@ +;**************************************************************************** +;* ATARI PERSONAL COMPUTER * +;* SYSTEM EQUATES * +;**************************************************************************** + +FAKEADDR EQU $0002 + +ATRACT EQU FAKEADDR +RTCLOK EQU $12 ;REAL TIME CLOCK +; +; PAGE TWO RAM ASSIGNMENTS +; +VDSLST EQU FAKEADDR ;DSP LIST NMI VECTOR +VPRCED EQU FAKEADDR ;PROCEED IRQ VECTOR +VINTER EQU FAKEADDR ;INTERUPT IRQ VECTOR +VBREAK EQU FAKEADDR ;BRK INST IRQ VECTOR +VKEYBD EQU FAKEADDR ;POKEY KB IRQ VECTOR +VSERIN EQU FAKEADDR ;POKEY INPUT RDY IRQ +VSEROR EQU FAKEADDR ;POKEY OUTPUT RDY +VSEROC EQU FAKEADDR ;POKEY OUTPUT DONE +VTIMR1 EQU FAKEADDR ;POKEY TIMER 1 IRQ +VTIMR2 EQU FAKEADDR ;POKEY TIMER 2 IRQ +VTIMR4 EQU FAKEADDR ;POKEY TIMER 4 IRQ +VIMIRQ EQU FAKEADDR ;IMMED IRQ VECTOR +CDTMV1 EQU FAKEADDR ;COUNT DOWN TIMER 1 +CDTMV2 EQU FAKEADDR ;COUNT DOWN TIMER 2 +CDTMV3 EQU FAKEADDR ;COUNT DOWN TIMER 3 +CDTMV4 EQU FAKEADDR ;COUNT DOWN TIMER 4 +CDTMV5 EQU FAKEADDR ;COUNT DOWN TIMER 5 +VVBLKI EQU FAKEADDR ;IMM VBLK NMI VECTOR +VVBLKD EQU FAKEADDR ;DEF VBLK NMI VECTOR +CDTMA1 EQU FAKEADDR ;CDTMV1 JSR ADDRESS +CDTMA2 EQU FAKEADDR ;CDTMV2 JSR ADDRESS +CDTMF3 EQU FAKEADDR ;CDTMV3 FLAG +SRTIMR EQU FAKEADDR ;SOFTWARE REPEAT TMR +CDTMF4 EQU FAKEADDR ;CDTMV4 FLAG +INTEMP EQU FAKEADDR ;IAN'S TEMP +CDTMF5 EQU FAKEADDR ;CDTMV5 FLAG +DMACTLS EQU FAKEADDR ;SAVE DMACTL REG +DLPTRS EQU FAKEADDR ;SAVE DISP LIST LO +;SDLSTH EQU $0231 ;SAVE DISP LIST HI +SSKCTL EQU FAKEADDR ;SKCTL REGISTER RAM +LCOUNT EQU FAKEADDR ;LOADER TEMP +LPENH EQU FAKEADDR ;LIGHT PEN HORIZONTAL +LPENV EQU FAKEADDR ;LIGHT PEN VERTICAL +BRKKY EQU FAKEADDR ;BREAK KEY VECTOR +RELADR EQU FAKEADDR ;LOADER REL ADDR +CDEVIC EQU FAKEADDR ;COMMAND BUFFER-DEV +CCOMND EQU FAKEADDR ;COMMAND BUFFER-CMND +CAUX1 EQU FAKEADDR ;COMMAND BUFFER AUX1 +CAUX2 EQU FAKEADDR ;COMMAND BUFFER AUX2 +;TEMP EQU $023E ;TEMPORARY RAM CELL +ERRFLG EQU FAKEADDR ;DEVICE ERROR FLAG +DFLAGS EQU FAKEADDR ;DISK FLAGS(SECTOR1) +DBSECT EQU FAKEADDR ;# DISK BOOT SECTORS +BOOTAD EQU FAKEADDR ;DISK BOOT ADDRESS +COLDST EQU FAKEADDR ;COLDSTART FLAG 1=CS +RECLEN EQU FAKEADDR ;LOADER LENGTH +DSKTIM EQU FAKEADDR ;DISK TIME OUT REG +VSFLAG EQU FAKEADDR ;FINE SCROLL TEMP +KEYDIS EQU FAKEADDR ;KEY DISABLE FLAG +FINE EQU FAKEADDR ;FINE SCROLL ENABLE(A1200) +GPRIOR EQU FAKEADDR ;GLOBAL PRIORITY +PADDL0 EQU FAKEADDR ;POT 0 RAM CELL +PADDL1 EQU FAKEADDR +PADDL2 EQU FAKEADDR +PADDL3 EQU FAKEADDR +STICK0 EQU FAKEADDR ;JOYSTICK 0 RAM CELL +STICK1 EQU FAKEADDR +PTRIG0 EQU FAKEADDR ;PADDLE TRIGGER 0 +PTRIG1 EQU FAKEADDR +PTRIG2 EQU FAKEADDR +PTRIG3 EQU FAKEADDR +STRIG0 EQU FAKEADDR ;JOYSTICK TRIGGER 0 +STRIG1 EQU FAKEADDR +HIBYTE EQU FAKEADDR ;LOADER +WMODE EQU FAKEADDR ;CASSETTE R/W MODE +BLIM EQU FAKEADDR ;CASSETTE RECORD SIZE +IMASK EQU FAKEADDR +JVECK EQU FAKEADDR ;JUMP VECTOR +NEWADR EQU FAKEADDR ;LOADER NEW ADDRESS +TXTROW EQU FAKEADDR ;TEXT ROWCRS +TXTCOL EQU FAKEADDR ;TEXT COLCRS +TINDEX EQU FAKEADDR ;TEXT INDEX +TXTMSC EQU FAKEADDR ;TEXT WINDOW MEM ADD +TXTOLD EQU FAKEADDR ;TEXT OLDROW & COL +CRETRY EQU FAKEADDR ;# COMMAND RETRIES +HOLD3 EQU FAKEADDR +SUBTMP EQU FAKEADDR +HOLD2 EQU FAKEADDR +DMASK EQU FAKEADDR ;PIXEL LOCATION MASK +TMPLBT EQU FAKEADDR +ESCFLG EQU FAKEADDR ;ESCAPE FLAG +TABMAP EQU FAKEADDR ;TAB STOP MAP +LOGMAP EQU FAKEADDR ;LINE START BIT MAP +INVFLG EQU FAKEADDR ;INVERSE VIDEO FLAG +FILFLG EQU FAKEADDR ;FILL FLAG FOR DRAW +TMPROW EQU FAKEADDR +TMPCOL EQU FAKEADDR +SCRFLG EQU FAKEADDR ;SET IF SCROLLING +HOLD4 EQU FAKEADDR ;TEMP USED BY DRAW +DRETRY EQU FAKEADDR ;# OF DEVICE RETRIES +SHFLOK EQU FAKEADDR ;SHIFT/CTL LOCK FLAG +BOTSCR EQU FAKEADDR ;BOTTOM OF SCREEN +PCOLR0 EQU FAKEADDR ;P0 COLOR +PCOLR1 EQU FAKEADDR ;P1 COLOR +PCOLR2 EQU FAKEADDR ;P2 COLOR +PCOLR3 EQU FAKEADDR ;P3 COLOR +COLOR0 EQU FAKEADDR ;COLOR 0 +COLOR1 EQU FAKEADDR +COLOR2 EQU FAKEADDR +COLOR3 EQU FAKEADDR +COLOR4 EQU FAKEADDR +COLBAKS EQU COLOR4 +CHBAS EQU FAKEADDR ;CHBAS REGISTER RAM +; +; COLLEEN MNEMONICS +; +; --------------------------------------------------------------------------- +POKEY EQU FAKEADDR +; --------------------------------------------------------------------------- +; +; READ +; +POT0 EQU POKEY+$00 +POT1 EQU POKEY+$00 +POT2 EQU POKEY+$00 +POT3 EQU POKEY+$00 +POT4 EQU POKEY+$00 +POT5 EQU POKEY+$00 +POT6 EQU POKEY+$00 +POT7 EQU POKEY+$00 +ALLPOT EQU POKEY+$00 +KBCODE EQU POKEY+$00 +; !!!!! +;RANDOM EQU POKEY+$00 +; +POTGO EQU POKEY+$00 +SERIN EQU POKEY+$00 +IRQST EQU POKEY+$00 +SKSTAT EQU POKEY+$00 +; +; WRITE +; +AUDF1 EQU POKEY+$00 +AUDC1 EQU POKEY+$00 +AUDF2 EQU POKEY+$00 +AUDC2 EQU POKEY+$00 +AUDF3 EQU POKEY+$00 +AUDC3 EQU POKEY+$00 +AUDF4 EQU POKEY+$00 +AUDC4 EQU POKEY+$00 +AUDCTL EQU POKEY+$00 +STIMER EQU POKEY+$00 +SKRES EQU POKEY+$00 +SEROUT EQU POKEY+$00 +IRQEN EQU POKEY+$00 +SKCTL EQU POKEY+$00 +; +; +; +; --------------------------------------------------------------------------- +GTIA EQU FAKEADDR +; --------------------------------------------------------------------------- +; +; WRITE +; +HPOSP0 EQU GTIA+$00 +HPOSP1 EQU GTIA+$00 +HPOSP2 EQU GTIA+$00 +HPOSP3 EQU GTIA+$00 +HPOSM0 EQU GTIA+$00 +HPOSM1 EQU GTIA+$00 +HPOSM2 EQU GTIA+$00 +HPOSM3 EQU GTIA+$00 +SIZEP0 EQU GTIA+$00 +SIZEP1 EQU GTIA+$00 +SIZEP2 EQU GTIA+$00 +SIZEP3 EQU GTIA+$00 +SIZEM EQU GTIA+$00 +GRAFP0 EQU GTIA+$00 +GRAFP1 EQU GTIA+$00 +GRAFP2 EQU GTIA+$00 +GRAFP3 EQU GTIA+$00 +GRAFM EQU GTIA+$00 +COLPM0 EQU GTIA+$00 +COLPM1 EQU GTIA+$00 +COLPM2 EQU GTIA+$00 +COLPM3 EQU GTIA+$00 +COLPF0 EQU GTIA+$00 +COLPF1 EQU GTIA+$00 +COLPF2 EQU GTIA+$00 +COLPF3 EQU GTIA+$00 +COLBAK EQU GTIA+$00 +PRIOR EQU GTIA+$00 +VDELAY EQU GTIA+$00 +GRACTL EQU GTIA+$00 +HITCLR EQU GTIA+$00 +CONSOL EQU GTIA+$00 +; +; READ +; +M0PF EQU GTIA+$00 +M1PF EQU GTIA+$00 +M2PF EQU GTIA+$00 +M3PF EQU GTIA+$00 +P0PF EQU GTIA+$00 +P1PF EQU GTIA+$00 +P2PF EQU GTIA+$00 +P3PF EQU GTIA+$00 +M0PL EQU GTIA+$00 +M1PL EQU GTIA+$00 +M2PL EQU GTIA+$00 +M3PL EQU GTIA+$00 +P0PL EQU GTIA+$00 +P1PL EQU GTIA+$00 +P2PL EQU GTIA+$00 +P3PL EQU GTIA+$00 +TRIG0 EQU GTIA+$00 +TRIG1 EQU GTIA+$00 +TRIG2 EQU GTIA+$00 +TRIG3 EQU GTIA+$00 +PAL EQU GTIA+$00 +; +; +; --------------------------------------------------------------------------- +ANTIC EQU FAKEADDR +; --------------------------------------------------------------------------- +; +DMACTL EQU ANTIC+$00 +CHACTL EQU ANTIC+$00 +DLPTR EQU ANTIC+$00 +;DLISTH EQU ANTIC+$00 +HSCROL EQU ANTIC+$00 +VSCROL EQU ANTIC+$00 +PMBASE EQU ANTIC+$00 +CHBASE EQU ANTIC+$00 +WSYNC EQU ANTIC+$00 +; !!!! +VCOUNT EQU ANTIC+$00 +; ---- +PENH EQU ANTIC+$00 +PENV EQU ANTIC+$00 +NMIEN EQU ANTIC+$00 +NMIRES EQU ANTIC+$00 +NMIST EQU ANTIC+$00 +; +; +; --------------------------------------------------------------------------- +PIA EQU FAKEADDR +; --------------------------------------------------------------------------- +; +PORTA EQU PIA+0 +PORTB EQU PIA+0 +PACTL EQU PIA+0 +PBCTL EQU PIA+0 +; +; --------------------------------------------------------------------------- +; Atari ANTIC chip display list equates +; --------------------------------------------------------------------------- +; +JUMP EQU $01 ; display list jump instruction (3 byte) +JVB EQU $41 ; display list jump and wait for vblank instruction (3) +; +SCH EQU $10 ; display list horizontal scrolling +SCV EQU $20 ; display list vertical scrolling +LMS EQU $40 ; display list load memory scan instruction (3 byte) +DLII EQU $80 ; display list interrupt instruction +; +SKIP1 EQU $00 ; display list skip 1 scan line instruction +SKIP2 EQU $10 ; display list skip 2 scan lines instruction +SKIP3 EQU $20 ; display list skip 3 scan lines instruction +SKIP4 EQU $30 ; display list skip 4 scan lines instruction +SKIP5 EQU $40 ; display list skip 5 scan lines instruction +SKIP6 EQU $50 ; display list skip 6 scan lines instruction +SKIP7 EQU $60 ; display list skip 7 scan lines instruction +SKIP8 EQU $70 ; display list skip 8 scan lines instruction +; +MODE2 EQU $02 ; display list mode 2 +MODE4 EQU $04 ; display list mode 4 +MODE8 EQU $08 ; display list mode 8 +MODEE EQU $0E ; display list mode E +MODEF EQU $0F ; display list mode F + +; --------------------------------------------------------------------------- +; KBCODEs +; --------------------------------------------------------------------------- +.enum @kbcode + _none = 255 + _esc = 28 + _1 = 31 + _2 = 30 + _3 = 26 + _4 = 24 + _5 = 29 + _6 = 27 + _7 = 51 + _8 = 53 + _9 = 48 + _0 = 50 + _lt = 54 + _gt = 55 + _del = 52 + _tab = 44 + _Q = 47 + _W = 46 + _E = 42 + _R = 40 + _T = 45 + _Y = 43 + _U = 11 + _I = 13 + _O = 8 + _P = 10 + _min = 14 + _up = 14 ; cursor function + _eq = 15 + _down = 15 ; cursor function + _ret = 12 + _A = 63 + _S = 62 + _D = 58 + _F = 56 + _G = 61 + _H = 57 + _J = 1 + _K = 5 + _L = 0 + _semicolon = 2 + _plus = 6 + _left = 6 ; cursor function + _asterisk = 7 + _right = 7 ; cursor function + _caps = 60 + _Z = 23 + _X = 22 + _C = 18 + _V = 16 + _B = 21 + _N = 36 + _M = 37 + _comma = 32 + _dot = 34 + _slash = 38 + _atari = 39 + _help = 17 + _F1 = 3 + _F2 = 4 + _F3 = 19 + _F4 = 20 + _space = 33 +.ende \ No newline at end of file diff --git a/C64/lib/MACRO.ASM b/C64/lib/MACRO.ASM new file mode 100644 index 0000000..92f8d13 --- /dev/null +++ b/C64/lib/MACRO.ASM @@ -0,0 +1,296 @@ + + + +.macro basic_start(addr) + + .word upstartEnd // link address + .word 10 // line num + .byte $9e // sys + + ?a=0 + ?b=0 + ?c=0 + ?d=0 + ?e=0 + + ?v = %%addr + + ift ?v>=10000 + ?a=?v/10000 + ?v=?v-(?a*10000) + eif + + ift ?v>=1000 + ?b=?v/1000 + ?v=?v-(?b*1000) + eif + + ift ?v>=100 + ?c=?v/100 + ?v=?v-(?c*100) + eif + + ift ?v>=10 + ?d=?v/10 + ?v=?v-(?d*10) + eif + + ?e=?v%10 + + dta ?a+$30,?b+$30,?c+$30,?d+$30,?e+$30 + + .byte 0 +upstartEnd + .word 0 // empty link signals the end of the program + +.endm + + +// +// Switch bank in VIC-II +// +// Args: +// bank: bank number to switch to. Valid values: 0-3. +// +.macro SwitchVICBank(bank) + // + // The VIC-II chip can only access 16K bytes at a time. In order to + // have it access all of the 64K available, we have to tell it to look + // at one of four banks. + // + // This is controller by bits 0 and 1 in $dd00 (PORT A of CIA #2). + // + // +------+-------+----------+-------------------------------------+ + // | BITS | BANK | STARTING | VIC-II CHIP RANGE | + // | | | LOCATION | | + // +------+-------+----------+-------------------------------------+ + // | 00 | 3 | 49152 | ($C000-$FFFF)* | + // | 01 | 2 | 32768 | ($8000-$BFFF) | + // | 10 | 1 | 16384 | ($4000-$7FFF)* | + // | 11 | 0 | 0 | ($0000-$3FFF) (DEFAULT VALUE) | + // +------+-------+----------+-------------------------------------+ + ?bits=%11 + + ift (%%bank==0) + ?bits=%11 + eli (%%bank==1) + ?bits=%10 + eli (%%bank==2) + ?bits=%01 + eli (%%bank==3) + ?bits=%00 + eif + + // + // Set Data Direction for CIA #2, Port A to output + // + lda $dd02 + and #%11111100 // Mask the bits were interested in. + ora #$03 // Set bits 0 and 1. + sta $dd02 + + // + // Tell VIC-II to switch to bank + // + lda $dd00 + and #%11111100 + ora #?bits + sta $dd00 +.endm + + +// +// Enter hires bitmap mode (a.k.a. standard bitmap mode) +// +.macro SetHiresBitmapMode + // + // Clear extended color mode (bit 6) and set bitmap mode (bit 5) + // + lda $d011 + and #%10111111 + ora #%00100000 + sta $d011 + + // + // Clear multi color mode (bit 4) + // + lda $d016 + and #%11101111 + sta $d016 +.endm + + +// +// Enter hires bitmap mode (a.k.a. standard bitmap mode) +// +.macro SetMulticolorBitmapMode + // + // Clear extended color mode (bit 6) and set bitmap mode (bit 5) + // + lda $d011 + and #%10111111 + ora #%00100000 + sta $d011 + + // + // Clear multi color mode (bit 4) + // + lda $d016 + ora #%00010000 + sta $d016 +.endm + + +// +// Switch location of screen memory. +// +// Args: +// address: Address relative to current VIC-II bank base address. +// Valid values: $0000-$3c00. Must be a multiple of $0400. +// +.macro SetScreenMemory(address) + // + // The most significant nibble of $D018 selects where the screen is + // located in the current VIC-II bank. + // + // +------------+-----------------------------+ + // | | LOCATION* | + // | BITS +---------+-------------------+ + // | | DECIMAL | HEX | + // +------------+---------+-------------------+ + // | 0000XXXX | 0 | $0000 | + // | 0001XXXX | 1024 | $0400 (DEFAULT) | + // | 0010XXXX | 2048 | $0800 | + // | 0011XXXX | 3072 | $0C00 | + // | 0100XXXX | 4096 | $1000 | + // | 0101XXXX | 5120 | $1400 | + // | 0110XXXX | 6144 | $1800 | + // | 0111XXXX | 7168 | $1C00 | + // | 1000XXXX | 8192 | $2000 | + // | 1001XXXX | 9216 | $2400 | + // | 1010XXXX | 10240 | $2800 | + // | 1011XXXX | 11264 | $2C00 | + // | 1100XXXX | 12288 | $3000 | + // | 1101XXXX | 13312 | $3400 | + // | 1110XXXX | 14336 | $3800 | + // | 1111XXXX | 15360 | $3C00 | + // +------------+---------+-------------------+ + // + ?bits = (%%address / $0400) << 4 + + lda $d018 + and #%00001111 + ora #?bits + sta $d018 +.endm + + +// +// Set location of bitmap. +// +// Args: +// address: Address relative to VIC-II bank address. +// Valid values: $0000 (bitmap at $0000-$1FFF) +// $2000 (bitmap at $2000-$3FFF) +// +.macro SetBitmapAddress(address) + // + // In standard bitmap mode the location of the bitmap area can + // be set to either BANK address + $0000 or BANK address + $2000 + // + // By setting bit 3, we can configure which of the locations to use. + // + + lda $d018 + + ift %%address == $0000 + and #%11110111 + eli %%address == $2000 + ora #%00001000 + eif + + sta $d018 +.endm + +// +// Once this is done, random values appear in location $D41B (RANDOM) +// +.macro InitializeSIDrnd + LDA #$FF ; maximum frequency value + STA $D40E ; voice 3 frequency low byte + STA $D40F ; voice 3 frequency high byte + LDA #$80 ; noise waveform, gate bit off + STA $D412 ; voice 3 control register +.endm + +;------------------------------------- + .MACRO rolw + ROL :1 + ROL :1+1 + .ENDM +;------------------------------------- + .MACRO aslw + ASL :1 + ROL :1+1 + .ENDM +;------------------------------------- + .MACRO rorw + ROR :1+1 + ROR :1 + .ENDM +;------------------------------------- + .MACRO lsrw + LSR :1+1 + ROR :1 + .ENDM +;------------------------------------- + .macro randomize + ;usage: randomize floor ceiling + ;returns (in A) a random .byte between "floor" and "ceiling" + .if :2 < :1 + .error "floor higher than ceiling" + .endif +?rand + lda random + cmp #:1 ;floor + bcc ?rand + cmp #:2+1 ;ceiling + bcs ?rand + .endm +;------------------------------------- + .macro phx + txa + pha + .endm +;------------------------------------- + .macro phy + tya + pha + .endm +;------------------------------------- + .macro plx + pla + tax + .endm +;------------------------------------- + .macro ply + pla + tay + .endm +;------------------------------------- + .MACRO WAIT +; WAIT +; waits one frame (1/50 s(PAL) or 1/60s(NTSC)) +?ze LDA $D012 + cmp #16 ; if line<16 then wait for line>15 (long VBI protection) + bcc ?ze + sbc #10 ; last lines correction +?wa cmp $D012 + bcc ?wa +?wf cmp $D012 + bcs ?wf + .ENDM +;------------------------------------- +.macro halt +?s jmp ?s +.endm \ No newline at end of file diff --git a/C64/textproc.asm b/C64/textproc.asm new file mode 100644 index 0000000..3c770bc --- /dev/null +++ b/C64/textproc.asm @@ -0,0 +1,333 @@ +; @com.wudsn.ide.asm.mainsourcefile=scorch.asm + + + .IF *>0 + +WeaponsListDL = 0 +NamesOfLevels = 0 +;---------------------------------------- +; this module contains routines used in text mode +; like shop and start-up options +;---------------------------------------- + +;-------------------------------------------------- +.proc Options +;-------------------------------------------------- +; start-up screen - options, etc. +; this function returns: +; - number of players (NumberOfPlayers) +; - money each player has on the beginning of the game (moneyL i moneyH) +; - and I am sure maxwind, gravity, no_of_rounds in a game, speed of shell flight + + + ldx #$08 +@ lda Autoplay_OptionsTable,x + sta OptionsTable,x + dex + bpl @- + + rts + +Autoplay_OptionsTable .by 4,4,2,2,4,1,3,2,4 + +.endp + +.proc SelectNextGradient + lda OptionsY ; if "Wind" option selected + cmp #$03 + bne NotWind + lda WindChangeInRound ; wind change after each turn (not round only) flag + eor #$1f ; '?' character + sta WindChangeInRound + rts +NotWind + ldy GradientNr + iny + cpy #$03 + bne NoGradientLoop + ldy #$00 +NoGradientLoop + sty GradientNr + lda GradientAddrL,y + sta GradientColors + lda GradientAddrH,y + sta GradientColors+1 + rts +.endp + +;------------------------------------------- +; call of the purchase (and activate) screens for each tank +.proc CallPurchaseForEveryTank + + mva #0 TankNr + sta isInventory +@ + ldx TankNr + lda SkillTable,x + beq ManualPurchase + jsr PurchaseAI ; remember to make ActivateAI :) !!! + jmp AfterManualPurchase +ManualPurchase + lda JoyNumber,x + sta JoystickNumber ; set joystick port for player + mva #0 isInventory + jsr Purchase ; purchase weapons + bit escFlag + spl:rts + jsr DefensivesActivate ; activate weapons + bit escFlag + spl:rts +AfterManualPurchase + inc:lda TankNr + cmp NumberOfPlayers + bne @- + rts +.endp +;-------------------------------------------------- +.proc DefensivesActivate +;-------------------------------------------------- +; This proc call Inventory and set Defensives activation first + + mwa #ListOfDefensiveWeapons WeaponsListDL ;switch to the list of offensive weapons + mva #$ff IsInventory + mva #%10000000 WhichList + ; offensive weapon - 0, defensive - %10000000 + jmp Purchase.GoToActivation +.endp + + +;-------------------------------------------------- +.proc Purchase ; +;-------------------------------------------------- +; In tanknr there is a number of the tank (player) +; that is buying weapons now (from 0). +; Rest of the data is taken from appropriate tables +; and during the purchase these tables are modified. + + +; we are clearing list of the weapons + mva #$00 WhichList + ; offensive weapon - 0, deffensive - %10000000 +GoToActivation + rts + +.endp + +; ----------------------------------------------------- +.proc EnterPlayerNames + ;entering names of players + + mva #0 TankNr + sta COLBAKS ; set color of background +@ tax + lda TankStatusColoursTable,x + sta COLOR2 ; set color of player name line + jsr EnterPlayerName + bit escFlag + spl:rts + jsr CheckTankCheat + inc TankNr + lda TankNr + cmp NumberOfPlayers + bne @- + rts +.endp +; ----------------------------------------------------- +.proc EnterPlayerName +; in: TankNr +; Out: TanksNames, SkillTable + +; this little thing is for choosing Player's skill (if computer) +; and entering his name +; If no name entered, there should be name "1st Tank", etc. +; Default tanks names are in table TanksNamesDefault +; ----------------------------------------------------- + +; + +EndOfNick + ; storing name of the player and its level + + ; level of the computer opponent goes to + ; the table of levels (difficulties) + ldx tanknr + lda #6 ; Spoiler + sta DifficultyLevel + sta skilltable,x + beq NotRobot + lda #$03 ; shape for robotanks + sta TankShape,x +NotRobot + ; storing name of the tank in the right space + ; (without cursor!) + ldy #$00 + txa ; ldx TankNr + asl + asl + asl ; 8 chars per name + tax ; in X where to put new name + + mva #sfx_next_player sfx_effect + + + ; check if all chars are empty (" ") + ldy #7 + lda #0 +@ ora #0 ; NameAdr,y + and #$7F ; remove inverse (Cursor) + dey + bpl @- + tay + beq MakeDefaultName + + ldy #0 +nextchar04 + lda #0 ; NameAdr,y + and #$7f ; remove inverse (Cursor) + sta tanksnames,x + inx + iny + cpy #$08 + bne nextchar04 + rts +MakeDefaultName +nextchar05 + lda tanksnamesDefault,x + sta tanksnames,x + inx + iny + cpy #$08 + bne nextchar05 + rts +.endp +;-------------------------------------------------- +.proc displaydec5 ;decimal (word), displayposition (word) +;-------------------------------------------------- +; displays decimal number as in parameters (in text mode) +; leading zeroes are removed +; the range is (00000..65565 - two bytes) + + ldy #4 ; there will be 5 digits +NextDigit + ldx #16 ; 16-bit dividee so Rotate 16 times + lda #$00 +Rotate000 + aslw decimal + rol ; scroll dividee + ; (as highest byte - additional - byte is A) + cmp #10 ; divider + bcc TooLittle000 ; if A is smaller than divider + ; there is nothing to substract + sbc #10 ; divider + inc decimal ; lowest bit set to 1 + ; because it is 0 and this is the fastest way +TooLittle000 dex + bne Rotate000 ; and Rotate 16 times, Result will be in decimal + tax ; and the rest in A + ; (and it goes to X because + ; it is our decimal digit) + lda digits,x + sta decimalresult,y + dey + bpl NextDigit ; Result again /10 and we have next digit + +;rightnumber + ; displaying without leading zeroes (if zeroes exist then display space at this position) + ldy #0 + ldx #0 ; digit flag (cut leading zeroes) +displayloop + lda decimalresult,y + cpx #0 + bne noleading0 + cpy #4 + beq noleading0 ; if 00000 - last 0 must stay + cmp zero + bne noleading0 + lda #space + beq displaychar ; space = 0 ! +noleading0 + inx ; set flag (no leading zeroes to cut) +displaychar + sta (displayposition),y +nexdigit + iny + cpy #5 + bne displayloop + + rts +.endp +;-------------------------------------------------- +.proc displaybyte ;decimal (byte), displayposition (word) +;-------------------------------------------------- +; displays decimal number as in parameters (in text mode) +; leading zeores are removed +; the range is (00..99 - one byte) + + ldy #1 ; there will be 2 digits +NextDigit2 + ldx #8 ; 8-bit dividee so Rotate 8 times + lda #$00 +Rotate001 + asl decimal + rol ; scroll dividee + ; (as highest byte - additional - byte is A) + cmp #10 ; divider + bcc TooLittle001 ; if A is smaller than divider + ; there is nothing to substract + sbc #10 ; divider + inc decimal ; because it is 0 and this is the fastest way +TooLittle001 dex + bne Rotate001 ; and Rotate 8 times, Result will be in decimal + tax ; and the rest in A + ; (and it goes to X because + ; it is our decimal digit) + lda digits,x + sta decimalresult,y + dey + bpl NextDigit2 ; Result again /10 and we have next digit + +; now cut leading zeroes (02 goes 2) + lda decimalresult + cmp zero + bne decimalend1 + lda #space + sta decimalresult + +decimalend1 + ; displaying + ldy #1 +displayloop1 + lda decimalresult,y + sta (displayposition),y + dey + bpl displayloop1 + + rts +.endp +;------------------------------------------------- +.proc RoundOverSprites + ; fill sprites with bytes + rts +.endp + +;-------------------------------------------------- +.proc GameOverScreen +;-------------------------------------------------- + rts +.endp +;------------------------------------------------- +.proc PutTankNameOnScreen +;------------------------------------------------- + +.endp +;------------------------------------------------- +.proc DisplayStatus +;------------------------------------------------- +DisplayAngle + ldx TankNr + rts +.endp +;------------------------------------------------- + + +.endif \ No newline at end of file diff --git a/MANUAL_EN.md b/Manuals/MANUAL_EN.md similarity index 91% rename from MANUAL_EN.md rename to Manuals/MANUAL_EN.md index f9e0dda..1fab3d9 100644 --- a/MANUAL_EN.md +++ b/Manuals/MANUAL_EN.md @@ -3,12 +3,18 @@ You can play using the keyboard (all functionality) or the joystick in the first port (all functionality necessary for gameplay). ## 1. Game Option Selection. +![Game options screen.](images/MainMenu.png) On the first screen, you can configure gameplay options: * number of players (2 - 6) includes both human and computer-controlled players * the initial amount of cash of each player (2K is the optimal value we chose, but for short games, it is worth choosing a higher value) * gravity -* maximum wind strength (wind is drawn at the beginning of each round or during the round between turns, here we can choose how strong it can be) +* maximum wind strength (wind is drawn at the beginning of each round or during the round between turns, here we can choose how strong it can be): + * 1B - maximum wind strength: 5 + * 3B - maximum wind strength: 20 + * 5B - maximum wind strength: 40 + * 7B - maximum wind strength: 70 + * 9B - maximum wind strength: 99 * number of rounds in a game * missile speed (does not affect the flight path - only changes the apparent missile speed - does not change anything in the gameplay itself) * frequency of suicides :) - if for a number of turns the game has not recorded hits (tanks are constantly shooting inaccurately), after one of such misses a tank commits suicide - here you determine how long they can "shooting for the stars" :) - if only people play the optimal setting is "norm", in the case of computer-controlled players ... you choose. @@ -29,6 +35,7 @@ The [TAB] or [SELECT] key, and on the Atari 5200 console, the [5] controller key The [RETURN] key or a joystick button moves to the next screen. ## 2. Entering the name of players and selecting the level of computer-controlled players +![Name of players and game level screen.](images/DiffMenu.png) The second screen is shown for each player. Here you can use the cursor keys or joystick to select whether the tank will be driven by a human (HUMAN option) or a computer (other options). The [TAB] or [SELECT] key, and on the Atari 5200 console the [5] controller key allow you to choose which joystick port the player will use. @@ -40,20 +47,27 @@ The player's name can also be entered with the joystick. After pressing and hold If the name is not entered, it will be supplemented with the default name. ## 3. Shopping screen (before each round) +![Shopping offensives screen.](images/PurOffensive.png) +![Shopping defensives screen.](images/PurDefensive.png) On this screen, you can make purchases of offensive and defensive weapons. Only those weapons that the player can afford are visible, along with information about the price and the number of units of a given weapon that will be obtained for that price. The information on the screen probably needs no more description. You move through the lists with the cursor keys (up and down) or with the joystick, the [TAB] key or the left arrow or the left joystick tilt change the screen to defensive or offensive weapons, the [SPACE] key or the right arrow and also the joystick to the right does the purchase of the indicated weapon. -The [RETURN] key or the joystick button press switches to the defensive weapon activation screen. Here you can activate previously bought defensive (or offensive after switching with [TAB], etc) weapons. This makes it possible to activate shields and others before the round starts. +The [RETURN] key or the joystick button press switches to the defensive weapon activation screen. Here you can activate previously bought defensive (or offensive after switching with [TAB], etc) weapons. + +![Defensives activation screen.](images/ActDefensive.png) + +This makes it possible to activate shields and others before the round starts. Another [RETURN] key or joystick button press switches to the next player's shopping screen. (For computer players this screen is not shown.) ## 4. The main screen of the game +![Main game screen.](images/StatusLine.png) The status line shows which player is currently allowed to take a shot and a set of other information: * player's tank name, -* active joystick number -* currently selected offensive weapon, +* active joystick number or difficulty level of computer-controlled player (1-**Moron** - 8-**Unknown**), +* currently selected offensive weapon (symbol quantity and name), * the player's remaining energy points and if he has an active defensive weapon that has its energy - in parentheses the energy level, * the angle and the direction of the barrel set by the player, * the shot strength set by the player (the maximum shot strength is limited by the player's energy - it can not exceed the energy * 10 . This means that you can fire weaker shots only when having a small amount of energy, @@ -208,13 +222,13 @@ The game has 8 difficulty levels of computer-controlled opponents. Or actually 7 * **Poolshark** - When attacking, he sets the nearest tank as his target, then selects the angle of the shot, and tries to select its strength by drawing it from the selected range. He always shoots with the best weapon he has. He uses defensive weapons. With a probability of 1:3, he activates the best defensive weapon he owns (the highest on the list of weapons he owns - that is, not necessarily the best) before firing. If his energy level drops below 30 units - he uses **Battery** (of course, if he bought it before), if the energy drops below 5 and he has no **Battery** he surrenders - **White Flag**. At the beginning of the round he makes 1 attemp to buy defensive weapons and 6 offensive weapons. -** **Tosser** - When attacking, he acts exactly like **Poolshark** however, he may have a "better" weapon inventory due to a different purchase tactic. He always activates the best defensive weapon he has before shooting. And just like **Poolshark** he uses **Battery** and **White Flag**. At the beginning of the round, he assesses how much money he has and depending on that, he makes (money/5100) attempts to buy defensive weapons and then checks again how much money he has left and makes (money/1250) attempts to buy offensive weapons. +* **Tosser** - When attacking, he acts exactly like **Poolshark** however, he may have a "better" weapon inventory due to a different purchase tactic. He always activates the best defensive weapon he has before shooting. And just like **Poolshark** he uses **Battery** and **White Flag**. At the beginning of the round, he assesses how much money he has and depending on that, he makes (money/5100) attempts to buy defensive weapons and then checks again how much money he has left and makes (money/1250) attempts to buy offensive weapons. -** **Chooser** - Takes as a target the weakest opponent (with the least amount of energy) and aims very precisely, but before the shot the energy of the shot is modified by the parameter of luck :) , that is, despite the precise aiming it does not always hit. He shoots with the best weapon he has unless the target is close. Then he changes his weapon to **Baby Missile** to avoid hitting himself. He always activates the best defensive weapon he has before shooting and, like **Poolshark**, uses **Battery** and **White Flag**. He purchases just like **Tosser**. +* **Chooser** - Takes as a target the weakest opponent (with the least amount of energy) and aims very precisely, but before the shot the energy of the shot is modified by the parameter of luck :) , that is, despite the precise aiming it does not always hit. He shoots with the best weapon he has unless the target is close. Then he changes his weapon to **Baby Missile** to avoid hitting himself. He always activates the best defensive weapon he has before shooting and, like **Poolshark**, uses **Battery** and **White Flag**. He purchases just like **Tosser**. * **Spoiler** - He shoots exactly like **Chooser** except that he has more luck :) , which means that even if he doesn't hit the target of his choice, it can be a more precise shot than **Chooser**. He uses defensive weapons exactly like **Chooser**. At the beginning of the round, he assesses how much money he has and depending on that, he makes (money/5100) attempts to buy defensive weapons and then checks again how much money he has left and makes (money/320) attempts to buy offensive weapons. When buying defensive weapons, he buys only strong and precise weapons - that is, weapons that won't accidentally hurt him. -** **Cyborg** - Takes aim at the weakest opponent (with the least amount of energy) but prefers human-controlled opponents. Aims very accurately and in the vast majority of cases hits on the first shot. He fires the shot with the best weapon he has unless the target is close. Then he changes his weapon to **Baby Missile** to avoid hitting himself. He uses defensive weapons exactly like **Chooser**. He shops exactly like **Spoiler**. +* **Cyborg** - Takes aim at the weakest opponent (with the least amount of energy) but prefers human-controlled opponents. Aims very accurately and in the vast majority of cases hits on the first shot. He fires the shot with the best weapon he has unless the target is close. Then he changes his weapon to **Baby Missile** to avoid hitting himself. He uses defensive weapons exactly like **Chooser**. He shops exactly like **Spoiler**. * **Unknown** - Before firing each shot, he randomly chooses a course of action from **Poolshark** to **Cyborg** and applies his tactics. However, the tactics of weapon purchases are always identical to **Tosser**. diff --git a/MANUAL_PL.md b/Manuals/MANUAL_PL.md similarity index 97% rename from MANUAL_PL.md rename to Manuals/MANUAL_PL.md index 86a33d0..4b5bce4 100644 --- a/MANUAL_PL.md +++ b/Manuals/MANUAL_PL.md @@ -3,11 +3,18 @@ Grać można przy użyciu klawiatury (wszystkie funkcjonalności) lub joysticka (wszystkie funkcjonalności niezbędne w rozgrywce). ## 1. Wybór opcji gry. +![Ekran wyboru opcji gry.](images/MainMenu.png) + Na pierwszym ekranie możemy skonfigurować opcje rozgrywki: * ilość graczy (2 - 6) obejmuje tak ludzi jak graczy sterowanych przez komputer * początkową ilość gotówki każdego z graczy (8k to wybrana przez nas wartość optymalna, lecz przy krótkich rozgrywkach warto wybrać większą wartość) * grawitacja -* maksymalna siła wiatru (wiatr jest losowany na początku każdej z rund lub w czasie rundy pomiędzy turami, tu możemy wybrać jak silny może być) +* maksymalna siła wiatru (wiatr jest losowany na początku każdej z rund lub w czasie rundy pomiędzy turami, tu możemy wybrać jak silny może być): + * 1B - maksymalna siła wiatru: 5 + * 3B - maksymalna siła wiatru: 20 + * 5B - maksymalna siła wiatru: 40 + * 7B - maksymalna siła wiatru: 70 + * 9B - maksymalna siła wiatru: 99 * liczba rozgrywanych rund * szybkość lotu pocisków (nie ma wpływu na tor lotu - zmienia jedynie widoczną prędkość rysowania - nie zmienia nic w samej rozgrywce) * częstotliwość samobójstw :) - jeśli przez ileś tur gra nie odnotowała trafień (czołgi ciągle strzelają niecelnie) jeden z takich pudłujących czołgów popełnia samobójstwo - tu określamy jak długo mogą “strzelać w próżnię” :) - jeśli grają tylko ludzie optymalne ustawienie to “norm”, w przypadku graczy sterowanych przez komputer… wedle uznania. @@ -28,6 +35,8 @@ Klawisz [TAB] lub [SELECT], a na konsoli Atari 5200 klawisz [5] kontrolera zmien Klawisz [RETURN] lub przycisk Joysticka przechodzi do następnego ekranu. ## 2. Wprowadzanie nazwy graczy i wybór poziomu graczy sterowanych przez komputer +![Ekran wyboru graczy i poziomu trudności.](images/DiffMenu.png) + Drugi ekran powtarza się dla każdego z graczy można na nim klawiszami kursora lub joystickiem wybrać czy danym czołgiem będzie kierował człowiek (opcja HUMAN) czy też komputer (pozostałe opcje). Klawisz [TAB] lub [SELECT], a na konsoli Atari 5200 klawisz [5] kontrolera pozwalają wybrać z którego portu joysticka będzie korzystał gracz. Klawisz [INVERSE] lub [OPTION] umożliwiają wybór jednego z 3 dostępnych kształtów czołgów. Na konsoli Atari 5200 uzyskuje się to poprzez cykliczne wybieranie kolejnych portów joysticka klawiszem [5]. @@ -38,21 +47,27 @@ Nazwę gracza można wprowadzać także przy pomocy joysticka. Po wciśnięciu i Jeśli nazwa nie zostanie wpisana, to zostanie uzupełniona nazwą domyślną. ## 3. Ekran zakupów (przed każdą rundą) +![Ekran zakupów broni ofensywnych.](images/PurOffensive.png) +![Ekran zakupów broni defensywnych.](images/PurDefensive.png) Na tym ekranie można dokonywać zakupów broni ofensywnych i defensywnych. Widoczne są tylko te bronie na które gracza stać wraz z informacją o cenie i ilości jednostek danej broni, którą za ten cenę otrzymamy. Informacje na ekranie nie wymagają chyba więcej opisu. Po listach poruszamy się klawiszami kursora (góra i dół) lub joystickiem, klawisz [TAB] lub strzałka w lewo czy też ruch joystickiem w lewo zmieniają ekran na bronie defensywne lub ofensywne, klawisz [SPACJA] lub strzałka w prawo a także joystick w prawo realizują zakup wskazanej broni. Klawisz [RETURN] lub przycisk joysticka przechodzi do ekranu aktywacji broni defensywnych. + +![Ekran aktywacji broni defensywnych.](images/ActDefensive.png) + Na ekranie tym można aktywować zakupione wcześniej bronie defensywne czy też ofensywne. Obsługiwany jest identycznie jak ekran zakupów, jednak [SPACJA] lub strzałka w prawo a także joystick w prawo realizują aktywacje wskazanej broni. Umożliwia to aktywowanie osłon jeszcze przed rozpoczęciem rundy. Klawisz [RETURN] lub przycisk joysticka przechodzi do ekranu zakupów następnego gracza. (oczywiście dla graczy komputerowych ten ekran się nie pojawia) ## 4. Główny ekran gry +![Główny ekran gry.](images/StatusLine.png) W linii statusowej widoczna jest informacja o tym który z graczy aktualnie może oddać strzał oraz zestaw innych informacji: * nazwa czołgu gracza -* numer aktywnego joysticka -* wybrana aktualnie broń ofensywna +* numer aktywnego joysticka lub poziom gracza sterowanego przez komputer (1-**Moron** - 8-**Unknown**), +* wybrana aktualnie broń ofensywna (symbol ilość nazwa), * pozostała ilość punktów energii gracza i jeśli ma on aktywną broń defensywną posiadającą swój zasób energii - w nawiasie ten zasób * ustawiony przez gracza kąt nachylenia lufy i kierunek jej nachylenia * ustawiona przez gracza siła strzału (maksymalna siła strzału jest ograniczana przez energię gracza - nie może przekroczyć energii * 10 . Oznacza to, że mając małą ilość energii możemy oddać słabsze strzały diff --git a/Manuals/images/ActDefensive.png b/Manuals/images/ActDefensive.png new file mode 100644 index 0000000..ce0b1f2 Binary files /dev/null and b/Manuals/images/ActDefensive.png differ diff --git a/Manuals/images/ActOffensive.png b/Manuals/images/ActOffensive.png new file mode 100644 index 0000000..155eeca Binary files /dev/null and b/Manuals/images/ActOffensive.png differ diff --git a/Manuals/images/DiffMenu.png b/Manuals/images/DiffMenu.png new file mode 100644 index 0000000..1c2dc21 Binary files /dev/null and b/Manuals/images/DiffMenu.png differ diff --git a/Manuals/images/MainMenu.png b/Manuals/images/MainMenu.png new file mode 100644 index 0000000..359c4e8 Binary files /dev/null and b/Manuals/images/MainMenu.png differ diff --git a/Manuals/images/PurDefensive.png b/Manuals/images/PurDefensive.png new file mode 100644 index 0000000..0adc32b Binary files /dev/null and b/Manuals/images/PurDefensive.png differ diff --git a/Manuals/images/PurOffensive.png b/Manuals/images/PurOffensive.png new file mode 100644 index 0000000..fa4653a Binary files /dev/null and b/Manuals/images/PurOffensive.png differ diff --git a/Manuals/images/StatusLine.png b/Manuals/images/StatusLine.png new file mode 100644 index 0000000..34fd203 Binary files /dev/null and b/Manuals/images/StatusLine.png differ diff --git a/README.md b/README.md index 0a2f2cd..9d5399b 100644 --- a/README.md +++ b/README.md @@ -27,33 +27,51 @@ You can contact us via [AtariAge](https://atariage.com) or [AtariOnLine](https:/ This source code was originally compiled with [OMC65 crossassembler](https://github.com/pkali/omc65) and on 2012-06-21 translated to [mads](https://github.com/tebe6502/Mad-Assembler). -Compilation: `mads scorch.asm -o:scorch.xex` +Compilation: +- `mads scorch.asm -o:scorch.xex -d:TARGET=800` for Atari800 version +- `mads scorch.asm -o:scorch.bin -d:TARGET=5200` for Atari 5200 version +- `mads scorchC64.asm -o:scorchC64.prg` for C64 version (WIP, not playable yet) Game source code is split into several parts: -- scorch.asm is the main game code (with many assorted routines) -- grafproc.asm - graphics routines like line or circle -- textproc.asm - text routines like list of weapons and shop -- variables.asm - all non-zero page variables -- constants.asm - various tables of constants -- display_*.asm - display lists and text screen definitions -- ai.asm - artificial stupidity of computer opponents -- weapons.asm - general arsenal of tankies -- definitions.asm - label definitions, moved to make it work better with Altirra debug (it doesn't). +- `scorch.asm` is the main game startup code +- `game.asm` - it all happens here +- `grafproc.asm` - graphics routines like line or circle +- `textproc.asm` - text routines like list of weapons and shop +- `variables.asm` - all non-zero page variables +- `constants.asm` - various tables of constants +- `display_*.asm` - display lists and text screen definitions +- `ai.asm` - artificial stupidity of computer opponents +- `weapons.asm` - general arsenal of tankies +- `definitions.asm` - label definitions, moved to make it work better with Altirra debug (it doesn't). -We were trying to use macros, pseudo-ops and simple graphics primitives as much as possible. -This way it should be relatively easy to port this code to e.g. C64 +We were trying to use macros, pseudo-ops, and simple graphics primitives as much as possible. This way, it should be relatively easy to port this code to, for example, the C64. -After those N years of working on this piece of code we are sure it would be much wiser to write it in C, Action! or MadPascal but on the other hand it is so much fun to type 150 chars where all you want to have y=a*x+b :) +After working on this piece of code for N years, we are sure it would be much wiser to write it in C, Action!, or MadPascal. On the other hand, it is so much fun to type 150 characters when all you want to have is y = a * x + b. :) -Originally most variables were in Polish, comments were sparse, but we wanted to release this piece of code to public. -Because of being always short of time/energy (to finish the game) we decided it must go in 'English' to let other people work on it. -It never happened, but we got some encouraging comments and we are still trying to do something from time to time. +Originally, most variables were in Polish, and comments were sparse. However, we wanted to release this piece of code to the public. Because we were always short of time and energy (to finish the game), we decided to translate it into English so that other people could work on it. This never happened, but we received some encouraging comments, and we are still trying to do something from time to time. With the advent of [fujinet](https://fujinet.online/) we are thinking about making the game interplanetary, err, with multiplayer over the net. We'll see. ## Changelog: +###### Version 1.30 +2023-05-21 + +Okay, okay, we promised that the single-machine game was done, and it was. However, some bug reports came in, and development of the C64 version unearthed some mostly peaceful and dormant pests. As a result, it appears that a new release is happening. + +The most important changes: +- Most machine-dependent code moved to appropriate folders (`Atari/` and `C64/`). +- Game Over results table improved by sorting all 3 values - points, hits and money earned. It was possible in the past to get a lower podium place with e.g., more money. +- Game Over screen now displays level of robo tanks and controller number for organic players. +- Gains calculations bug fixed. +- Manuals now include pictures! +- More than 6 tanks possible (not for Atari / 5200 where sprites and memory are the limiting factor) +- Shield stays up after White Flag bug fixed https://github.com/pkali/scorch_src/issues/138. Finally!!! +- Quit from game and quit to Game Over is now checked much more often, especially when robo tanks are fighting. +- Numerous binary size and source code clarity improvements, mainly to facilitate the above changes. + + ###### Version 1.28 2023-04-22 @@ -145,11 +163,11 @@ Other (dubious) improvements: We couldn't resist! This is the Senior Executive Director's Cut. By virtue of byte misering we squeezed in a few new features: -* new selectable tank shapes - change the controller enough times to get a different tank model -* lonely bad pixel after Liquid Dirt fixed -* mountain colors (or shades) possible, switch with [Tab] in the main menu -* active controller number display in the game, store, and inventory screens -* a very special terminator mode for Moron +- new selectable tank shapes - change the controller enough times to get a different tank model +- lonely bad pixel after Liquid Dirt fixed +- mountain colors (or shades) possible, switch with [Tab] in the main menu +- active controller number display in the game, store, and inventory screens +- a very special terminator mode for Moron ###### Version 1.20 @@ -158,72 +176,72 @@ By virtue of byte misering we squeezed in a few new features: It's the final cut. Director's Cut. We squeezed the code and saved some bytes to add the joystick/controller selection. No more fights for the stick, up to 4 players can have fun with their own manipulators. And the fifth one can still use the keyboard :). Our most prolific testers Arek and Alex called for a number of fixes. Thank you, guys! -* Players can select their controllers. -* Better Auto Defense symbol in the status line. -* Battery performance in AI and Auto Defense fixed. -* More accurate and faster Laser. -* Boost For Gifts includes a secret, quite powerful weapon. -* Points counting fix-up (edge cases eliminated). -* Long lists in inventory and shop were pointing to a weapon outside the screen. Fixed. -* Lazy Boys now remember the last weapon used. -* Especially for XEGS - SELECT key changes the joystick similarly to TAB. -* Rare P/M glitches fixed. -* ExplosionRange variable glitched (rarely) due to byte/word mix-up. Fixed. -* Bouncy Castle was bouncing the laser from inside. Fixed. -* Shielded tanks were autodestructing when shooting with angle 0. Fixed. -* Physics of bouncing off the walls was incorrect for some weapons. Fixed. +- Players can select their controllers. +- Better Auto Defense symbol in the status line. +- Battery performance in AI and Auto Defense fixed. +- More accurate and faster Laser. +- Boost For Gifts includes a secret, quite powerful weapon. +- Points counting fix-up (edge cases eliminated). +- Long lists in inventory and shop were pointing to a weapon outside the screen. Fixed. +- Lazy Boys now remember the last weapon used. +- Especially for XEGS - SELECT key changes the joystick similarly to TAB. +- Rare P/M glitches fixed. +- ExplosionRange variable glitched (rarely) due to byte/word mix-up. Fixed. +- Bouncy Castle was bouncing the laser from inside. Fixed. +- Shielded tanks were autodestructing when shooting with angle 0. Fixed. +- Physics of bouncing off the walls was incorrect for some weapons. Fixed. ###### Version 1.19 2022-11-04 This is the final round of weapon additions! Also. our beloved testers and players found a number of issues and we were extremely happy to address them. -* New defensive weapon "Lazy Boy" - aims at the closest enemy. -* New defensive weapon "Lazy Darwin" - aims at the weakest link, an enemy I mean. -* New defensive weapon "Auto Defense" - activate it to be automatically protected by shields and stuff (where available) -* New defensive weapon "Spy Hard" - quickly view energies, weapons and shields of your opponents. -* New SFXes, improvements in SFX, and music by @mikerro -* Shooting with angle 0 caused the sudden death of the operator. Fixed. -* Angles were asymmetrical, now you can go from 0 to 90 and to 0 again (181 degrees of freedom). Fixed with an improved arithmetic rounding of our sub-pixel accuracy. -* Drawing a barrel when a tank was on the edge of X==256 pixels caused a lonely pixel to appear randomly. Fixed. -* Liquid Dirt was overflowing from the right edge of the screen to the left. Fixed. -* Liquid Dirt volume increased significantly, it is now a formidable attack! -* A single pixel was erroneously plotted when measuring distance (was visible in e.g., Death's Head). Fixed. -* Not all traces were correctly erased after Funky Bomb, fixed again (for the 3rt time I guess). -* Soil sedimentation speed after Funky Bomb improved. -* Pressing [ESC] when in inventory/store was quitting the game, now it quits the menu only. -* A bug in MADS optimization was causing parts of SEPPUKU message to stay on screen. -* BIGGEST OF ALL: the lonely pixel after Nuclear Winter was eliminated. https://github.com/pkali/scorch_src/issues/103 We have spent a disproportionately large amount of time trying to slap this bug. It is still there, but is not manifesting itself ;) +- New defensive weapon "Lazy Boy" - aims at the closest enemy. +- New defensive weapon "Lazy Darwin" - aims at the weakest link, an enemy I mean. +- New defensive weapon "Auto Defense" - activate it to be automatically protected by shields and stuff (where available) +- New defensive weapon "Spy Hard" - quickly view energies, weapons and shields of your opponents. +- New SFXes, improvements in SFX, and music by @mikerro +- Shooting with angle 0 caused the sudden death of the operator. Fixed. +- Angles were asymmetrical, now you can go from 0 to 90 and to 0 again (181 degrees of freedom). Fixed with an improved arithmetic rounding of our sub-pixel accuracy. +- Drawing a barrel when a tank was on the edge of X==256 pixels caused a lonely pixel to appear randomly. Fixed. +- Liquid Dirt was overflowing from the right edge of the screen to the left. Fixed. +- Liquid Dirt volume increased significantly, it is now a formidable attack! +- A single pixel was erroneously plotted when measuring distance (was visible in e.g., Death's Head). Fixed. +- Not all traces were correctly erased after Funky Bomb, fixed again (for the 3rt time I guess). +- Soil sedimentation speed after Funky Bomb improved. +- Pressing [ESC] when in inventory/store was quitting the game, now it quits the menu only. +- A bug in MADS optimization was causing parts of SEPPUKU message to stay on screen. +- BIGGEST OF ALL: the lonely pixel after Nuclear Winter was eliminated. https://github.com/pkali/scorch_src/issues/103 We have spent a disproportionately large amount of time trying to slap this bug. It is still there, but is not manifesting itself ;) ###### Version 1.18 2022-11-07 Possibly the final single-player version of the game, unless our dear players find another breaking issue! -* 5200 keypad works as it should. You can now press these finicky foils to your heart's desire. -* "Unknown" type Robotanks were attacking with Nuclear Winter every time. Fixed! -* One of the variables was declared as a byte but used as a word that might cause some rare instabilities. -* Page zero variables are cleared prior to the game start to eliminate rare issues in some software/hardware configurations. -* The new version of music in NTSC eliminates issues with tempo (not that anyone but the artist noticed that, but still it is an improvement!) -* You can now wrap around inventory and shop to faster access these options far down below. -* Visual improvement of the main menu and fixed some color issues with the title headers. -* Hovercraft was always flying to the top of the screen, it was not intended, it is now hovering just above the mountains! -* The main menu does not blink now when changing options. This was a very minor thing but it bothered me to some extent. Fixing it required a complete rewrite of this portion of the menu. +- 5200 keypad works as it should. You can now press these finicky foils to your heart's desire. +- "Unknown" type Robotanks were attacking with Nuclear Winter every time. Fixed! +- One of the variables was declared as a byte but used as a word that might cause some rare instabilities. +- Page zero variables are cleared prior to the game start to eliminate rare issues in some software/hardware configurations. +- The new version of music in NTSC eliminates issues with tempo (not that anyone but the artist noticed that, but still it is an improvement!) +- You can now wrap around inventory and shop to faster access these options far down below. +- Visual improvement of the main menu and fixed some color issues with the title headers. +- Hovercraft was always flying to the top of the screen, it was not intended, it is now hovering just above the mountains! +- The main menu does not blink now when changing options. This was a very minor thing but it bothered me to some extent. Fixing it required a complete rewrite of this portion of the menu. ###### Version 1.17 2022-10-31 Mostly 5200 console port and NTSC improvements. -* Updated songs from Miker do not require skipping frames on NTSC machines. Crucial for the next point. -* Bouncy Castle bouncing of Funky Bomb fixed https://github.com/pkali/scorch_src/issues/129 -* 5200 version had various graphical and sound glitches. Although mostly harmless, it hurt our sense of aesthetics. First of all the flickering credits roll is all good now. -* Rare hang-ups on NTSC machines fixed -* Screen lowered down by 7 scan lines to help top status line on NTSC CRTs. -* 5200 ATTRACT mode not going away fixed -* Autorepeat added to menus what should help 5200 users with their non-centering abomination of a controller. -* DLI interrupts optimized, few cycles saved. -* 5200 keypad sort-of-works. Please refer to manual for key bindings. +- Updated songs from Miker do not require skipping frames on NTSC machines. Crucial for the next point. +- Bouncy Castle bouncing of Funky Bomb fixed https://github.com/pkali/scorch_src/issues/129 +- 5200 version had various graphical and sound glitches. Although mostly harmless, it hurt our sense of aesthetics. First of all the flickering credits roll is all good now. +- Rare hang-ups on NTSC machines fixed +- Screen lowered down by 7 scan lines to help top status line on NTSC CRTs. +- 5200 ATTRACT mode not going away fixed +- Autorepeat added to menus what should help 5200 users with their non-centering abomination of a controller. +- DLI interrupts optimized, few cycles saved. +- 5200 keypad sort-of-works. Please refer to manual for key bindings. ###### Version 1.16 @@ -236,7 +254,7 @@ Cramming the game into a 32KiB cart and 16KiB RAM was a big task - it required a The release is not perfect - we have a number of glitches and improvements to the 5200 controller procedures to work on, but the game is playable. Changes: -* numerous, but not very visible +- numerous, but not very visible ###### Version 1.14 @@ -246,12 +264,12 @@ Minor bugfixes and optimizations. Just a small update to allow for more testing and having fun before the bigger release. Changes: -* Numerous optimizations that require a solid test. Please have fun and report issues! -* Small DrawTanks fix. -* Bouncy Castle bounces like it should. -* Tracer and Smoke Tracer are not causing defense weapons to trigger anymore. -* In rare cases direct hit was not accounted for correctly. -* Manuals updated. https://github.com/pkali/scorch_src/releases/tag/v1.16 +- Numerous optimizations that require a solid test. Please have fun and report issues! +- Small DrawTanks fix. +- Bouncy Castle bounces like it should. +- Tracer and Smoke Tracer are not causing defense weapons to trigger anymore. +- In rare cases direct hit was not accounted for correctly. +- Manuals updated. https://github.com/pkali/scorch_src/releases/tag/v1.16 ###### Version 1.13 @@ -262,13 +280,13 @@ Getting ready for porting the game! Several heavy optimizations and code cleanups in preparation for an unexpected port. Changes: -* Overhaul of AI - Cyborgs, Spoilers, and Choosers aim much better. -* Cyborgs prefer to kill humans. -* Fine tuning of AI purchases makes the difficulty level aligned with the robot level. -* Fixed a very difficult and elusive bug that was causing tanks to freeze when falling close to the right edge of the screen fixed. -* Updated music by @Miker -* It is now possible to enter tank names with a joystick - all essential game functions are available without touching the keyboard! -* Manuals updated with AI strategy information and more. +- Overhaul of AI - Cyborgs, Spoilers, and Choosers aim much better. +- Cyborgs prefer to kill humans. +- Fine tuning of AI purchases makes the difficulty level aligned with the robot level. +- Fixed a very difficult and elusive bug that was causing tanks to freeze when falling close to the right edge of the screen fixed. +- Updated music by @Miker +- It is now possible to enter tank names with a joystick - all essential game functions are available without touching the keyboard! +- Manuals updated with AI strategy information and more. ###### Version 1.12 @@ -277,12 +295,12 @@ Changes: What is going on? Are we getting crazy or what? Changes: -* Background color indicates the type of walls. This is very useful when the rand option is selected. -* XEGS users requested that console keys are used when no keyboard is attached! We delivered! [SELECT] to select an offensive weapon, [OPTION] to jump into inventory, defensive section, [START] + [OPTION] - immediate Game Over (no confirmation for you keyboardless folks) -* A very silly bug detected by our young testers fixed - the game crashed when you built a very high mountain using Dirt Balls :) -* Boxy infinite bounce bug fixed. -* Funky bombs bounce off the walls! -* The first letter entered for a tank name was inserted in the wrong spot. How did it work at all? Magic. +- Background color indicates the type of walls. This is very useful when the rand option is selected. +- XEGS users requested that console keys are used when no keyboard is attached! We delivered! [SELECT] to select an offensive weapon, [OPTION] to jump into inventory, defensive section, [START] + [OPTION] - immediate Game Over (no confirmation for you keyboardless folks) +- A very silly bug detected by our young testers fixed - the game crashed when you built a very high mountain using Dirt Balls :) +- Boxy infinite bounce bug fixed. +- Funky bombs bounce off the walls! +- The first letter entered for a tank name was inserted in the wrong spot. How did it work at all? Magic. [ESC] now correctly exits the purchase screen. @@ -294,8 +312,8 @@ A release lollapalooza. The silliness indicator crashed. What are we doing? Changes: -* A very silly buffer overflow bug fixed - it allowed for infinite (well... to the point) lengths of tank names, or rather for overwriting code with arbitrary values. -* Gamefield walls added https://github.com/pkali/scorch_src/issues/50. Choosing a different wall effect from the main options menu allows for a sophisticated tactics change. +- A very silly buffer overflow bug fixed - it allowed for infinite (well... to the point) lengths of tank names, or rather for overwriting code with arbitrary values. +- Gamefield walls added https://github.com/pkali/scorch_src/issues/50. Choosing a different wall effect from the main options menu allows for a sophisticated tactics change. ###### Version 1.10 2022-08-21 @@ -307,22 +325,22 @@ This release brings a swath of gameplay updates and a generous dose of a new sil Version number bump reflects number of unreleased versions and amount of changes. Changes: -* Defensive weapons can be activated before the round to make for the unbeatable aiming precision of the robotanks. -* Fixed bug with Long Schlong activation taking one Schlong too many. -* Smoke Tracer not disappearing smoke fixed. -* Bug allowing for infinite shooting outside the screen fixed. -* Tank colors and P/M sequence as devised by Adam, the gfx artist. Tanks differ more and look better. https://github.com/pkali/scorch_src/issues/119 -* New item in the shop - loot box "Buy me!" with a surprise inside. https://github.com/pkali/scorch_src/issues/97 -* Tank names can have s p a c e s now! https://github.com/pkali/scorch_src/issues/120 -* Tanks are mobile now thanks to the new defensive option - Hovercraft https://github.com/pkali/scorch_src/issues/52 -* Main atari library switched to a more standard version based on Mapping the Atari -* Huge memory optimizations to allow for the new features. -* Narrow screen in shop / inventory (many bytes saved). -* Explosion range corrections for a rare event of non-lethal Nuke explosions. -* Pressing [A] jumps into defensive weapons activation directly. -* Elusive randomize force error causing rare hangups for Tosser fixed. -* Activation of defensive weapons moved to front. -* Additional SFX for new weapons. +- Defensive weapons can be activated before the round to make for the unbeatable aiming precision of the robotanks. +- Fixed bug with Long Schlong activation taking one Schlong too many. +- Smoke Tracer not disappearing smoke fixed. +- Bug allowing for infinite shooting outside the screen fixed. +- Tank colors and P/M sequence as devised by Adam, the gfx artist. Tanks differ more and look better. https://github.com/pkali/scorch_src/issues/119 +- New item in the shop - loot box "Buy me!" with a surprise inside. https://github.com/pkali/scorch_src/issues/97 +- Tank names can have s p a c e s now! https://github.com/pkali/scorch_src/issues/120 +- Tanks are mobile now thanks to the new defensive option - Hovercraft https://github.com/pkali/scorch_src/issues/52 +- Main atari library switched to a more standard version based on Mapping the Atari +- Huge memory optimizations to allow for the new features. +- Narrow screen in shop / inventory (many bytes saved). +- Explosion range corrections for a rare event of non-lethal Nuke explosions. +- Pressing [A] jumps into defensive weapons activation directly. +- Elusive randomize force error causing rare hangups for Tosser fixed. +- Activation of defensive weapons moved to front. +- Additional SFX for new weapons. ###### Version 1.00 2022-08-13 @@ -336,18 +354,18 @@ All 48KB+ 8-bit Atari computers are supported. Thank you @Pecusx and @Miker for your hard work over the last few weeks - I was almost entirely absent because of the real-world attack. Most important changes: -* New Game Over screen with a summary of wins, direct hits and earned cash. https://github.com/pkali/scorch_src/issues/9 -* Tank barrels are drawn procedurally to make aiming easier.. -* Various SFX and music updates with new tunes for all parts of the game. https://github.com/pkali/scorch_src/issues/112 -* AI can use White Flag. -* 3 different tank shapes https://github.com/pkali/scorch_src/issues/64. -* All AI levels are programmed. Cyborg is tough! https://github.com/pkali/scorch_src/issues/40 -* New weapon - Long Schlong! -* New splash screen. -* Game mechanics improved. -* [O] key skips to the Game Over screen. -* The game works on Atari 800. -* Huge amount of optimizations to squeeze the game into 48K. +- New Game Over screen with a summary of wins, direct hits and earned cash. https://github.com/pkali/scorch_src/issues/9 +- Tank barrels are drawn procedurally to make aiming easier.. +- Various SFX and music updates with new tunes for all parts of the game. https://github.com/pkali/scorch_src/issues/112 +- AI can use White Flag. +- 3 different tank shapes https://github.com/pkali/scorch_src/issues/64. +- All AI levels are programmed. Cyborg is tough! https://github.com/pkali/scorch_src/issues/40 +- New weapon - Long Schlong! +- New splash screen. +- Game mechanics improved. +- [O] key skips to the Game Over screen. +- The game works on Atari 800. +- Huge amount of optimizations to squeeze the game into 48K. And now the new adventure begins! @@ -423,10 +441,10 @@ The new inventory system has been added. Call it by pressing the "I" key or shor Another significant playability change is #54 - it is not finished yet, but keeping the joystick up or down makes force increase/decrease faster. Also - short press of fire calls Inventory, long press fires the shell. The timings are experimental, please let me know if this needs a modification/improvement. Tickets closed: -* https://github.com/pkali/scorch_src/issues/92 - less unnecessary cleaning of the offensive texts -* https://github.com/pkali/scorch_src/issues/89 - improved collisions with tank -* https://github.com/pkali/scorch_src/issues/71 - ditto -* https://github.com/pkali/scorch_src/issues/11, https://github.com/pkali/scorch_src/issues/26, https://github.com/pkali/scorch_src/issues/8, https://github.com/pkali/scorch_src/issues/20 - new inventory system +- https://github.com/pkali/scorch_src/issues/92 - less unnecessary cleaning of the offensive texts +- https://github.com/pkali/scorch_src/issues/89 - improved collisions with tank +- https://github.com/pkali/scorch_src/issues/71 - ditto +- https://github.com/pkali/scorch_src/issues/11, https://github.com/pkali/scorch_src/issues/26, https://github.com/pkali/scorch_src/issues/8, https://github.com/pkali/scorch_src/issues/20 - new inventory system ###### Build 143 2022-06-05 diff --git a/ai.asm b/ai.asm index f13da31..44b70df 100644 --- a/ai.asm +++ b/ai.asm @@ -1,4 +1,4 @@ -; @com.wudsn.ide.asm.mainsourcefile=scorch.asm +; @com.wudsn.ide.asm.mainsourcefile=scorch.asm ; artificial intelligence of tanks goes here! ; in A there is a level of tank's intelligence @@ -22,26 +22,26 @@ pha lda AIRoutines,y pha -; it's no necessary - PrepareAIShoot is next proc :) -; jsr PrepareAIShoot -; rts -.endp +; it's no necessary - PrepareAIShoot is next proc :) +; jsr PrepareAIShoot +; rts +.endp ;---------------------------------------------- -.proc PrepareAIShoot - ; create low precision table of positions - ; by dividing positions by 4 - ldy #MaxPlayers-1 +.proc PrepareAIShoot + ; create low precision table of positions + ; by dividing positions by 4 + ldy #MaxPlayers-1 loop - lda xtankstableL,y - sta temp - lda xtankstableH,y - sta temp+1 - ;= /4 - :2 lsrw temp - lda temp - sta LowResDistances,y - dey - bpl loop + lda xtankstableL,y + sta temp + lda xtankstableH,y + sta temp+1 + ;= /4 + :2 lsrw temp + lda temp + sta LowResDistances,y + dey + bpl loop ; common values used in AI routines ; address of weapons table (for future use) @@ -50,7 +50,7 @@ WepTableToTemp sta temp lda TanksWeaponsTableH,x sta temp+1 - rts + rts .endp ;---------------- AIRoutines @@ -65,343 +65,345 @@ AIRoutines ;---------------------------------------------- .proc Unknown - ; random robotank (from Poolshark to Cyborg) - randomize 4 13 - and #%11111110 - tay + ; random robotank (from Poolshark to Cyborg) + randomize 4 13 + and #%11111110 + tay lda AIRoutines+1,y pha lda AIRoutines,y pha - rts + rts .endp ;---------------------------------------------- -.proc Moron +.proc Moron jsr RandomizeAngle sta NewAngle mwa #80 RandBoundaryLow - mwa #800 RandBoundaryHigh + mwa #800 RandBoundaryHigh jsr RandomizeForce - ; choose the best weapon - ldy #ind_Buy_me_________+1 ; if the cheat is active it will fire the BFG :) - jmp ChooseBestOffensive.NotFromAll + ; choose the best weapon + ldy #ind_Buy_me +1 ; if the cheat is active it will fire the BFG :) + jmp ChooseBestOffensive.NotFromAll ;rts .endp ;---------------------------------------------- -.proc Shooter +.proc Shooter lda PreviousAngle,x ora PreviousEnergyL,x ora PreviousEnergyH,x beq firstShoot - - lda PreviousAngle,x - cmp #90 - bcs shootingLeftAtThisMomentOfTime - ; shooting right at this moment of time + + lda PreviousAngle,x + cmp #90 + bcs shootingLeftAtThisMomentOfTime + ; shooting right at this moment of time sec sbc #5 cmp #10 bcs @+ ;not smaller than 10 bcc firstShoot ; GET THE aim againg - + shootingLeftAtThisMomentOfTime - - clc - adc #5 - cmp #170 ; maximum shooter angle + + clc + adc #5 + cmp #170 ; maximum shooter angle bcs firstShoot @ - sta NewAngle + sta NewAngle - sec - lda PreviousEnergyL,x - sbc #5 - sta ForceTableL,x - lda PreviousEnergyH,x - sbc #0 - sta ForceTableH,x - jmp endo + sec + lda PreviousEnergyL,x + sbc #5 + sta ForceTableL,x + lda PreviousEnergyH,x + sbc #0 + sta ForceTableH,x + jmp endo firstShoot - ; compare the x position with the middle of the screen + ; compare the x position with the middle of the screen lda xTanksTableH,x cmp #>(screenwidth/2) bne @+ - lda xTanksTableL,x - cmp #<(screenwidth/2) -@ bcc tankIsOnTheRight + lda xTanksTableL,x + cmp #<(screenwidth/2) +@ bcc tankIsOnTheRight ; enemy tank is on the left - randomize 95 125 - sta NewAngle - bne forceNow + randomize 95 125 + sta NewAngle + bne forceNow tankIsOnTheRight randomize 55 85 sta NewAngle - + forceNow mwa #100 RandBoundaryLow - mwa #800 RandBoundaryHigh + mwa #800 RandBoundaryHigh ;ldx TankNr ;this is possibly not necessary jsr RandomizeForce endo - ;ldx TankNr ;this is possibly not necessary + ;ldx TankNr ;this is possibly not necessary jsr RandomizeForce.LimitForce - lda NewAngle - sta PreviousAngle,x - lda ForceTableL,x - sta PreviousEnergyL,x - lda ForceTableH,x - sta PreviousEnergyH,x - - ; choose the best weapon - - jmp ChooseBestOffensive + lda NewAngle + sta PreviousAngle,x + lda ForceTableL,x + sta PreviousEnergyL,x + lda ForceTableH,x + sta PreviousEnergyH,x + + ; choose the best weapon + + jmp ChooseBestOffensive ;rts .endp ;---------------------------------------------- .proc Poolshark - jsr UseBatteryOrFlag - ; defensives - jsr PoolsharkDefensives + jsr UseBatteryOrFlag + ; defensives + jsr PoolsharkDefensives firstShoot - ;find nearest tank neighbour - jsr FindBestTarget2 - beq EnemyOnLeft - ; calculate index to shotangle table - ; in temp2 we have x distance divided by 8 - lda temp2 - :3 lsr @ - and #%00000111 - clc - adc #8 - sta AngleTablePointer - bne AngleIsSet + ;find nearest tank neighbour + jsr FindBestTarget2 + beq EnemyOnLeft + ; calculate index to shotangle table + ; in temp2 we have x distance divided by 8 + lda temp2 + :3 lsr @ + and #%00000111 + clc + adc #8 + sta AngleTablePointer + bne AngleIsSet EnemyOnLeft - lda temp2 - :3 lsr @ - and #%00000111 - eor #%00000111 - sta AngleTablePointer + lda temp2 + :3 lsr @ + and #%00000111 + eor #%00000111 + sta AngleTablePointer AngleIsSet - - randomize 0 8 - ldy AngleTablePointer - clc - adc AngleTable,y - sta NewAngle - + + randomize 0 8 + ldy AngleTablePointer + clc + adc AngleTable,y + sta NewAngle + forceNow mwa #300 RandBoundaryLow - mwa #700 RandBoundaryHigh + mwa #700 RandBoundaryHigh ldx TankNr jsr RandomizeForce -endo - ; choose the best weapon - - jsr ChooseBestOffensive - rts - +endo + ; choose the best weapon + + jmp ChooseBestOffensive + ; rts + ;---------------------------------------------- -AngleTable ; 16 bytes ;ba w $348b L$3350 - .by 106,114,122,130,138,146,154,162 - .by 18,26,34,43,50,58,66,74 +AngleTable ; 16 bytes ;ba w $348b L$3350 + .by 106,114,122,130,138,146,154,162 + .by 18,26,34,43,50,58,66,74 .endp ;---------------------------------------------- .proc UseBatteryOrFlag - jsr UseBattery ; as subroutine for reuse in AutoDefense - ; if very low energy and no battery then use White Flag - lda Energy,x - cmp #5 - bcs EnoughEnergy - ; lower than 5 units - white flag - lda #ind_White_Flag_____ - sta ActiveDefenceWeapon,x + jsr UseBattery ; as subroutine for reuse in AutoDefense + ; if very low energy and no battery then use White Flag + lda Energy,x + cmp #5 + bcs EnoughEnergy + ; lower than 5 units - white flag + jsr ClearTankNr ; we must hide tank to erase shields (issue #138) + lda #ind_White_Flag + sta ActiveDefenceWeapon,x + jsr PutTankNr ; and draw tank witch Flag EnoughEnergy - rts + rts .endp ; .proc UseBattery - ; if low energy ten use battery - lda Energy,x - cmp #30 - bcs EnoughEnergy - ; lower than 30 units - check battery - ldy #ind_Battery________ - lda (temp),y ; has address of TanksWeaponsTable - beq NoBatteries - ; we have batteries - use one - sec - sbc #1 - sta (temp),y - lda #99 - sta Energy,x - jsr MaxForceCalculate + ; if low energy ten use battery + lda Energy,x + cmp #30 + bcs EnoughEnergy + ; lower than 30 units - check battery + ldy #ind_Battery + lda (temp),y ; has address of TanksWeaponsTable + beq NoBatteries + ; we have batteries - use one + sec + sbc #1 + sta (temp),y + lda #99 + sta Energy,x + jsr MaxForceCalculate EnoughEnergy NoBatteries - rts + rts .endp ;---------------------------------------------- .proc PoolsharkDefensives - ; use best defensive :) - ; but not allways - randomize 1 3 - cmp #1 - bne NoUseDefensive - ; first check check if any is in use - lda ActiveDefenceWeapon,x - bne DefensiveInUse - ldy #last_real_defensive+1 ;the last defensive weapon + ; use best defensive :) + ; but not allways + randomize 1 3 + cmp #1 + bne NoUseDefensive + ; first check check if any is in use + lda ActiveDefenceWeapon,x + bne DefensiveInUse + ldy #last_real_defensive+1 ;the last defensive weapon @ - dey - cpy #ind_Hovercraft_____ ;first defensive weapon (White Flag, Battery and Hovercraft - never use) - beq NoUseDefensive - lda (temp),y ; has address of TanksWeaponsTable - beq @- - ; decrease in inventory - sec - sbc #1 - sta (temp),y ; has address of TanksWeaponsTable - ; activate defensive weapon - tya ; number of selectet defensive weapon - sta ActiveDefenceWeapon,x + dey + cpy #ind_Hovercraft ;first defensive weapon (White Flag, Battery and Hovercraft - never use) + beq NoUseDefensive + lda (temp),y ; has address of TanksWeaponsTable + beq @- + ; decrease in inventory + sec + sbc #1 + sta (temp),y ; has address of TanksWeaponsTable + ; activate defensive weapon + tya ; number of selectet defensive weapon + sta ActiveDefenceWeapon,x lda DefensiveEnergy,y sta ShieldEnergy,x NoUseDefensive DefensiveInUse - rts + rts .endp ;---------------------------------------------- .proc Tosser - jsr UseBatteryOrFlag - ; use best defensive :) - jsr TosserDefensives - ; Toosser is like Poolshark but allways uses defensives - jmp Poolshark.firstShoot + jsr UseBatteryOrFlag + ; use best defensive :) + jsr TosserDefensives + ; Toosser is like Poolshark but allways uses defensives + jmp Poolshark.firstShoot .endp ;---------------------------------------------- .proc TosserDefensives - ; use best defensive :) - ; allways - ; first check check if any is in use - lda ActiveDefenceWeapon,x - bne DefensiveInUse - ldy #last_real_defensive+1 ;the last defensive weapon + ; use best defensive :) + ; allways + ; first check check if any is in use + lda ActiveDefenceWeapon,x + bne DefensiveInUse + ldy #last_real_defensive+1 ;the last defensive weapon @ - dey - cpy #ind_Hovercraft_____ ;first defensive weapon (White Flag, Battery and Hovercraft - never use) - beq NoUseDefensive - lda (temp),y ; has address of TanksWeaponsTable - beq @- - ; decrease in inventory - sec - sbc #1 - sta (temp),y ; has address of TanksWeaponsTable - ; activate defensive weapon - tya ; number of selectet defensive weapon - sta ActiveDefenceWeapon,x + dey + cpy #ind_Hovercraft ;first defensive weapon (White Flag, Battery and Hovercraft - never use) + beq NoUseDefensive + lda (temp),y ; has address of TanksWeaponsTable + beq @- + ; decrease in inventory + sec + sbc #1 + sta (temp),y ; has address of TanksWeaponsTable + ; activate defensive weapon + tya ; number of selectet defensive weapon + sta ActiveDefenceWeapon,x lda DefensiveEnergy,y sta ShieldEnergy,x DefensiveInUse NoUseDefensive - rts + rts .endp ;---------------------------------------------- .proc Chooser - ; like cyborg but more randomizing force - jsr UseBatteryOrFlag - ; use defensives like Tosser - jsr TosserDefensives - ; now select best target - lda #$00 ; no prefer humans - jsr FindBestTarget3 - sty TargetTankNr - ; aiming - jsr TakeAim ; direction still in A (0 - left, >0 - right) - - ; choose the best weapon - jsr ChooseBestOffensive + ; like cyborg but more randomizing force + jsr UseBatteryOrFlag + ; use defensives like Tosser + jsr TosserDefensives + ; now select best target + lda #$00 ; no prefer humans + jsr FindBestTarget3 + sty TargetTankNr + ; aiming + jsr TakeAim ; direction still in A (0 - left, >0 - right) - ; randomizing force +-100 - sbw Force #100 RandBoundaryLow - bpl NotNegativeEnergy - mwa #1 RandBoundaryLow + ; choose the best weapon + jsr ChooseBestOffensive + + ; randomizing force +-100 + sbw Force #100 RandBoundaryLow + bpl NotNegativeEnergy + mwa #1 RandBoundaryLow NotNegativeEnergy - adw Force #100 RandBoundaryHigh + adw Force #100 RandBoundaryHigh jsr RandomizeForce - ; if target distance lower than 24 - set weapon to Baby Missile (for security :) - jsr GetDistance - cmp #6 ; 24/4 - bcs HighForce - lda #ind_Baby_Missile___ - sta ActiveWeapon,x + ; if target distance lower than 24 - set weapon to Baby Missile (for security :) + jsr GetDistance + cmp #6 ; 24/4 + bcs HighForce + lda #ind_Baby_Missile + sta ActiveWeapon,x HighForce - rts + rts .endp ;---------------------------------------------- .proc Spoiler - ; like cyborg but little randomizing force - jsr UseBatteryOrFlag - ; use defensives like Tosser - jsr TosserDefensives - ; now select best target - lda #$00 ; no prefer humans - jsr FindBestTarget3 - sty TargetTankNr - ; aiming - jsr TakeAim ; direction still in A (0 - left, >0 - right) - - ; choose the best weapon - jsr ChooseBestOffensive + ; like cyborg but little randomizing force + jsr UseBatteryOrFlag + ; use defensives like Tosser + jsr TosserDefensives + ; now select best target + lda #$00 ; no prefer humans + jsr FindBestTarget3 + sty TargetTankNr + ; aiming + jsr TakeAim ; direction still in A (0 - left, >0 - right) - ; randomizing force +-50 - sbw Force #50 RandBoundaryLow - bpl NotNegativeEnergy - mwa #1 RandBoundaryLow + ; choose the best weapon + jsr ChooseBestOffensive + + ; randomizing force +-50 + sbw Force #50 RandBoundaryLow + bpl NotNegativeEnergy + mwa #1 RandBoundaryLow NotNegativeEnergy - adw Force #50 RandBoundaryHigh + adw Force #50 RandBoundaryHigh jsr RandomizeForce - ; if target distance lower than 24 - set weapon to Baby Missile (for security :) - jsr GetDistance - cmp #6 ; 24/4 - bcs HighForce - lda #ind_Baby_Missile___ - sta ActiveWeapon,x + ; if target distance lower than 24 - set weapon to Baby Missile (for security :) + jsr GetDistance + cmp #6 ; 24/4 + bcs HighForce + lda #ind_Baby_Missile + sta ActiveWeapon,x HighForce - rts + rts .endp ;---------------------------------------------- .proc Cyborg - jsr UseBatteryOrFlag - ; use defensives like Tosser - jsr TosserDefensives - ; now select best target - lda #100 ; prefer humans - jsr FindBestTarget3 - sty TargetTankNr - ; aiming - jsr TakeAim ; direction still in A (0 - left, >0 - right) - - ; choose the best weapon - ldy #ind_Nuke___________+1 - jsr ChooseBestOffensive.NotFromAll + jsr UseBatteryOrFlag + ; use defensives like Tosser + jsr TosserDefensives + ; now select best target + lda #100 ; prefer humans + jsr FindBestTarget3 + sty TargetTankNr + ; aiming + jsr TakeAim ; direction still in A (0 - left, >0 - right) - lda Force - sta ForceTableL,x - lda Force+1 - sta ForceTableH,x - ; if target distance lower than 32 - set weapon to Baby Missile (for security :) - jsr GetDistance - cmp #8 ;32/4 - bcs HighForce - lda #ind_Baby_Missile___ - sta ActiveWeapon,x + ; choose the best weapon + ldy #ind_Nuke +1 + jsr ChooseBestOffensive.NotFromAll + + lda Force + sta ForceTableL,x + lda Force+1 + sta ForceTableH,x + ; if target distance lower than 32 - set weapon to Baby Missile (for security :) + jsr GetDistance + cmp #8 ;32/4 + bcs HighForce + lda #ind_Baby_Missile + sta ActiveWeapon,x HighForce - rts + rts .endp ;---------------------------------------------- @@ -412,51 +414,51 @@ HighForce ; returns target tank number in Y and ; direcion of shoot in A (0 - left, >0 - right) ;---------------------------------------------- - sta PreferHumansFlag -; jsr MakeLowResDistances - lda #202 - sta temp2 ; max possible energy - lda #0 - sta tempor2 ; direction of shoot - ;ldx TankNr - ldy NumberOfPlayers - dey - -loop01 - cpy TankNr - beq skipThisPlayer - lda eXistenZ,y - beq skipThisPlayer + sta PreferHumansFlag +; jsr MakeLowResDistances + lda #202 + sta temp2 ; max possible energy + lda #0 + sta tempor2 ; direction of shoot + ;ldx TankNr + ldy NumberOfPlayers + dey - lda skilltable,y - beq ItIsHuman - lda PreferHumansFlag +loop01 + cpy TankNr + beq skipThisPlayer + lda eXistenZ,y + beq skipThisPlayer + + lda skilltable,y + beq ItIsHuman + lda PreferHumansFlag ItIsHuman - clc - adc Energy,y ; if robotank energy=energy+100 (100 or 0 from PreferHumansFlag) - cmp temp2 ; lowest - bcs lowestIsLower - sta temp2 - sty temp2+1 ; number of the closest tank - mva #0 tempor2 - lda LowResDistances,x - cmp LowResDistances,y - bcs EnemyOnTheLeft - ; enemy on right - inc tempor2 ; set direction to right - -EnemyOnTheLeft + clc + adc Energy,y ; if robotank energy=energy+100 (100 or 0 from PreferHumansFlag) + cmp temp2 ; lowest + bcs lowestIsLower + sta temp2 + sty temp2+1 ; number of the closest tank + mva #0 tempor2 + lda LowResDistances,x + cmp LowResDistances,y + bcs EnemyOnTheLeft + ; enemy on right + inc tempor2 ; set direction to right + +EnemyOnTheLeft lowestIsLower skipThisPlayer - dey - bpl loop01 - ; now we have number of the farthest tank in temp2+1 - ; and direction (0 - left, >0 - right) in tempor2 - ; let's move them to registers - ; in temp2 we have energy of target - ldy temp2+1 - lda tempor2 - rts + dey + bpl loop01 + ; now we have number of the farthest tank in temp2+1 + ; and direction (0 - left, >0 - right) in tempor2 + ; let's move them to registers + ; in temp2 we have energy of target + ldy temp2+1 + lda tempor2 + rts .endp ;---------------------------------------------- .proc FindBestTarget2 @@ -465,54 +467,54 @@ skipThisPlayer ; returns target tank number in Y and ; direcion of shoot in A (0 - left, >0 - right) ;---------------------------------------------- -; jsr MakeLowResDistances - mva #$ff temp2 ; min possible distance - mva #0 tempor2 ; direction of shoot +; jsr MakeLowResDistances + mva #$ff temp2 ; min possible distance + mva #0 tempor2 ; direction of shoot + + ;ldx TankNr + ldy NumberOfPlayers + dey - ;ldx TankNr - ldy NumberOfPlayers - dey - loop01 - cpy TankNr - beq skipThisPlayer - lda eXistenZ,y - beq skipThisPlayer - - lda LowResDistances,x - cmp LowResDistances,y - bcs EnemyOnTheLeft - ;enemy on the right - sec - lda LowResDistances,y - sbc LowResDistances,x - cmp temp2 ; lowest - bcs lowestIsLower - sta temp2 - sty temp2+1 ; number of the closest tank - inc tempor2 ; set direction to right - bne lowestIsLower + cpy TankNr + beq skipThisPlayer + lda eXistenZ,y + beq skipThisPlayer + + lda LowResDistances,x + cmp LowResDistances,y + bcs EnemyOnTheLeft + ;enemy on the right + sec + lda LowResDistances,y + sbc LowResDistances,x + cmp temp2 ; lowest + bcs lowestIsLower + sta temp2 + sty temp2+1 ; number of the closest tank + inc tempor2 ; set direction to right + bne lowestIsLower EnemyOnTheLeft - sec - lda LowResDistances,x - sbc LowResDistances,y - cmp temp2 ; lowest - bcs lowestIsLower - sta temp2 - sty temp2+1 ; number of the closest tank - + sec + lda LowResDistances,x + sbc LowResDistances,y + cmp temp2 ; lowest + bcs lowestIsLower + sta temp2 + sty temp2+1 ; number of the closest tank + lowestIsLower skipThisPlayer - dey - bpl loop01 - ; now we have number of the closest tank in temp2+1 - ; and direction (0 - left, >0 - right) in tempor2 - ; let's move them to registers - ; in temp2 we have x distance divided by 8 - ldy temp2+1 - lda tempor2 - rts + dey + bpl loop01 + ; now we have number of the closest tank in temp2+1 + ; and direction (0 - left, >0 - right) in tempor2 + ; let's move them to registers + ; in temp2 we have x distance divided by 8 + ldy temp2+1 + lda tempor2 + rts .endp ;---------------------------------------------- @@ -522,242 +524,242 @@ skipThisPlayer ; returns angle and power of shoot tank X (TankNr) ; in the appropriate variables (Angle and Force) ;---------------------------------------------- - lda ActiveWeapon,x - pha ; store active weapon - mva #$ff SecondTryFlag - ; set initial Angle and Force values - lda OptionsTable+2 ; selected gravity - asl - tay - ; force correction - lower tank Y position - higher possible force - sec - lda #screenheight - sbc Ytankstable,x - sta temp2 - clc - lda AIForceTable,y - sta RandBoundaryLow - adc temp2 - sta RandBoundaryHigh - lda AIForceTable+1,y - sta RandBoundaryLow+1 - adc #0 - sta RandBoundaryHigh+1 + lda ActiveWeapon,x + pha ; store active weapon + mva #$ff SecondTryFlag + ; set initial Angle and Force values + lda OptionsTable+2 ; selected gravity + asl + tay + ; force correction - lower tank Y position - higher possible force + sec + lda #screenheight + sbc Ytankstable,x + sta temp2 + clc + lda AIForceTable,y + sta RandBoundaryLow + adc temp2 + sta RandBoundaryHigh + lda AIForceTable+1,y + sta RandBoundaryLow+1 + adc #0 + sta RandBoundaryHigh+1 jsr RandomizeForce RepeatAim - jsr Table2Force - ; wind correction 90+(wind/8) - mwa Wind temp2 - :7 lsrw temp2 - clc - lda #90 - adc temp2 - sta NewAngle - ; set virtual weapon :) - lda #ind_Baby_Missile___ - sta ActiveWeapon,x - ; now we have initial valuses - mva #%11000000 TestFlightFlag - ; check targeting direction - lda tempor2 - jne AimingLeft + jsr Table2Force + ; wind correction 90+(wind/8) + mwa Wind temp2 + :7 lsrw temp2 + clc + lda #90 + adc temp2 + sta NewAngle + ; set virtual weapon :) + lda #ind_Baby_Missile + sta ActiveWeapon,x + ; now we have initial valuses + mva #%11000000 TestFlightFlag + ; check targeting direction + lda tempor2 + jne AimingLeft AimingRight - ; make test Shoot (Flight) - jsr SetStartAndFlight - lda HitFlag - beq NoHitInFirstLoopR ; impossible :) - bmi GroundHitInFirstLoopR + ; make test Shoot (Flight) + jsr SetStartAndFlight + lda HitFlag + beq NoHitInFirstLoopR ; impossible :) + bmi GroundHitInFirstLoopR TankHitInFirstLoopR - ; tank hit, but which tank? - ; it's our target or not? - ldy HitFlag - dey - cpy TargetTankNr - beq EndOfFirstLoopR ; it's our target! - ; if it's another tank then check position like ground hit + ; tank hit, but which tank? + ; it's our target or not? + ldy HitFlag + dey + cpy TargetTankNr + beq EndOfFirstLoopR ; it's our target! + ; if it's another tank then check position like ground hit GroundHitInFirstLoopR - ; checking only x position of hit - ldy TargetTankNr - lda xTanksTableH,y - cmp XHit+1 - bne @+ - lda xTanksTableL,y - cmp XHit + ; checking only x position of hit + ldy TargetTankNr + lda xTanksTableH,y + cmp XHit+1 + bne @+ + lda xTanksTableL,y + cmp XHit @ - bcs HitOnRightSideOfTargetR - ; continue targeting - clc - lda NewAngle - adc #5 ; 5 deg to right - cmp #(180-20) -; bcs EndOfFirstLoopR ; if angle 180-20 or higher - bcs AimSecondTry - sta NewAngle - jmp AimingRight + bcs HitOnRightSideOfTargetR + ; continue targeting + clc + lda NewAngle + adc #5 ; 5 deg to right + cmp #(180-20) +; bcs EndOfFirstLoopR ; if angle 180-20 or higher + bcs AimSecondTry + sta NewAngle + jmp AimingRight NoHitInFirstLoopR - ; Angle 5 deg to left and end loop - sec - lda NewAngle - sbc #5 - sta NewAngle + ; Angle 5 deg to left and end loop + sec + lda NewAngle + sbc #5 + sta NewAngle HitOnRightSideOfTargetR - dec NewAngle + dec NewAngle EndOfFirstLoopR - mva #5 modify ; set counter (5 turns) + mva #5 modify ; set counter (5 turns) SecondLoopR - ; make test Shoot (Flight) - jsr SetStartAndFlight - lda HitFlag - beq NoHitInSecondLoopR ; impossible :) - bmi GroundHitInSecondLoopR + ; make test Shoot (Flight) + jsr SetStartAndFlight + lda HitFlag + beq NoHitInSecondLoopR ; impossible :) + bmi GroundHitInSecondLoopR TankHitInSecondLoopR - ; tank hit, but which tank? - ; it's our target or not? - ldy HitFlag - dey - cpy TargetTankNr - beq EndOfSecondLoopR ; it's our target! - ; if it's another tank then check position like ground hit + ; tank hit, but which tank? + ; it's our target or not? + ldy HitFlag + dey + cpy TargetTankNr + beq EndOfSecondLoopR ; it's our target! + ; if it's another tank then check position like ground hit GroundHitInSecondLoopR - ; checking only x position of hit - ldy TargetTankNr - lda xTanksTableH,y - cmp XHit+1 - bne @+ - lda xTanksTableL,y - cmp XHit + ; checking only x position of hit + ldy TargetTankNr + lda xTanksTableH,y + cmp XHit+1 + bne @+ + lda xTanksTableL,y + cmp XHit @ - bcc HitOnLeftSideOfTargetR - ; continue targeting - dec NewAngle ; 1 deg to left - dec modify ; max 5 turns - beq EndOfSecondLoopR - jmp SecondLoopR + bcc HitOnLeftSideOfTargetR + ; continue targeting + dec NewAngle ; 1 deg to left + dec modify ; max 5 turns + beq EndOfSecondLoopR + jmp SecondLoopR HitOnLeftSideOfTargetR - ; decrease energy (a little) - sbw Force #5 + ; decrease energy (a little) + sbw Force #5 NoHitInSecondLoopR - ; Angle 1 deg to right and end loop - inc NewAngle + ; Angle 1 deg to right and end loop + inc NewAngle EndOfSecondLoopR EndOfAim - pla ; and restore active weapon - sta ActiveWeapon,x - rts + pla ; and restore active weapon + sta ActiveWeapon,x + rts AimSecondTry - bit SecondTryFlag - bpl EndOfAim ; closest RTS - inc SecondTryFlag - lda #<1000 - sta ForceTableL,x - lda #>1000 - sta ForceTableH,x - jsr RandomizeForce.LimitForce - jmp RepeatAim - + bit SecondTryFlag + bpl EndOfAim ; closest RTS + inc SecondTryFlag + lda #<1000 + sta ForceTableL,x + lda #>1000 + sta ForceTableH,x + jsr RandomizeForce.LimitForce + jmp RepeatAim + AimingLeft - ; make test Shoot (Flight) - jsr SetStartAndFlight - lda HitFlag - beq NoHitInFirstLoopL ; impossible :) - bmi GroundHitInFirstLoopL + ; make test Shoot (Flight) + jsr SetStartAndFlight + lda HitFlag + beq NoHitInFirstLoopL ; impossible :) + bmi GroundHitInFirstLoopL TankHitInFirstLoopL - ; tank hit, but which tank? - ; it's our target or not? - ldy HitFlag - dey - cpy TargetTankNr - beq EndOfFirstLoopL ; it's our target! - ; if it's another tank then check position like ground hit + ; tank hit, but which tank? + ; it's our target or not? + ldy HitFlag + dey + cpy TargetTankNr + beq EndOfFirstLoopL ; it's our target! + ; if it's another tank then check position like ground hit GroundHitInFirstLoopL - ; checking only x position of hit - ldy TargetTankNr - lda xTanksTableH,y - cmp XHit+1 - bne @+ - lda xTanksTableL,y - cmp XHit + ; checking only x position of hit + ldy TargetTankNr + lda xTanksTableH,y + cmp XHit+1 + bne @+ + lda xTanksTableL,y + cmp XHit @ - bcc HitOnLeftSideOfTargetL - ; continue targeting - sec - lda NewAngle - sbc #5 ; 5 deg to left - cmp #21 -; bcc EndOfFirstLoopL ; if angle 20 or lower - bcc AimSecondTry - sta NewAngle - jmp AimingLeft + bcc HitOnLeftSideOfTargetL + ; continue targeting + sec + lda NewAngle + sbc #5 ; 5 deg to left + cmp #21 +; bcc EndOfFirstLoopL ; if angle 20 or lower + bcc AimSecondTry + sta NewAngle + jmp AimingLeft NoHitInFirstLoopL - ; Angle 5 deg to right and end loop - clc - lda NewAngle - adc #5 - sta NewAngle + ; Angle 5 deg to right and end loop + clc + lda NewAngle + adc #5 + sta NewAngle HitOnLeftSideOfTargetL - inc NewAngle + inc NewAngle EndOfFirstLoopL - mva #5 modify ; set counter (5 turns) + mva #5 modify ; set counter (5 turns) SecondLoopL - ; make test Shoot (Flight) - jsr SetStartAndFlight - lda HitFlag - beq NoHitInSecondLoopL ; impossible :) - bmi GroundHitInSecondLoopL + ; make test Shoot (Flight) + jsr SetStartAndFlight + lda HitFlag + beq NoHitInSecondLoopL ; impossible :) + bmi GroundHitInSecondLoopL TankHitInSecondLoopL - ; tank hit, but which tank? - ; it's our target or not? - ldy HitFlag - dey - cpy TargetTankNr - beq EndOfSecondLoopL ; it's our target! - ; if it's another tank then check position like ground hit + ; tank hit, but which tank? + ; it's our target or not? + ldy HitFlag + dey + cpy TargetTankNr + beq EndOfSecondLoopL ; it's our target! + ; if it's another tank then check position like ground hit GroundHitInSecondLoopL - ; checking only x position of hit - ldy TargetTankNr - lda xTanksTableH,y - cmp XHit+1 - bne @+ - lda xTanksTableL,y - cmp XHit + ; checking only x position of hit + ldy TargetTankNr + lda xTanksTableH,y + cmp XHit+1 + bne @+ + lda xTanksTableL,y + cmp XHit @ - bcs HitOnRightSideOfTargetL - ; continue targeting - inc NewAngle ; 1 deg to right - dec modify ; max 5 turns - beq EndOfSecondLoopL - jmp SecondLoopL + bcs HitOnRightSideOfTargetL + ; continue targeting + inc NewAngle ; 1 deg to right + dec modify ; max 5 turns + beq EndOfSecondLoopL + jmp SecondLoopL HitOnRightSideOfTargetL - ; decrease energy (a little) - sbw Force #5 + ; decrease energy (a little) + sbw Force #5 NoHitInSecondLoopL - ; Angle 1 deg to left and end loop - dec NewAngle + ; Angle 1 deg to left and end loop + dec NewAngle EndOfSecondLoopL - jmp EndOfAim - -SetStartAndFlight ; set start point (virtual barrel end :) ) and make test flight - ; xtraj+1 and ytraj+1 set - clc - lda xTanksTableL,x - adc #4 - sta xtraj+1 - lda xTanksTableH,x - adc #0 - sta xtraj+2 - sec - lda yTanksTable,x - sbc #4 - sta ytraj+1 - mva #0 ytraj+2 - mva NewAngle Angle - jsr Flight - ldx TankNr - rts + jmp EndOfAim + +SetStartAndFlight ; set start point (virtual barrel end :) ) and make test flight + ; xtraj+1 and ytraj+1 set + clc + lda xTanksTableL,x + adc #4 + sta xtraj+1 + lda xTanksTableH,x + adc #0 + sta xtraj+2 + sec + lda yTanksTable,x + sbc #4 + sta ytraj+1 + mva #0 ytraj+2 + mva NewAngle Angle + jsr Flight + ldx TankNr + rts .endp ;---------------------------------------------- -.proc PurchaseAI ; +.proc PurchaseAI ; ; A - skill of the TankNr ; makes purchase for AI opponents ; results of this routine are not visible on the screen @@ -769,8 +771,8 @@ SetStartAndFlight ; set start point (virtual barrel end :) ) and make test fligh pha lda PurchaseAIRoutines,x pha - rts - .endp + rts + .endp ;---------------- PurchaseAIRoutines @@ -789,125 +791,125 @@ PurchaseAIRoutines rts .endp ;------- -.proc TryToPurchaseOnePiece2 ; for Cyborg - ; A - weapon number, better it will be in range(1,32) - ; TankNr in X +.proc TryToPurchaseOnePiece2 ; for Cyborg + ; A - weapon number, better it will be in range(1,32) + ; TankNr in X ; DOES NOT CHANGE X - tay - sta temp+1 - :3 lsr ; A=A/8 - sta temp - tya - and #%00000111 - tay - lda bittable,y - ldy temp - and PurchaseMeTable2,y - beq TryToPurchaseOnePiece.SorryNoPurchase - jmp TryToPurchaseOnePiece.PurchaseIt + tay + sta temp+1 + :3 lsr ; A=A/8 + sta temp + tya + and #%00000111 + tay + lda bittable,y + ldy temp + and PurchaseMeTable2,y + beq TryToPurchaseOnePiece.SorryNoPurchase + jmp TryToPurchaseOnePiece.PurchaseIt .endp ;------- .proc TryToPurchaseOnePiece - ; A - weapon number, better it will be in range(1,32) - ; TankNr in X + ; A - weapon number, better it will be in range(1,32) + ; TankNr in X ; DOES NOT CHANGE X - tay - sta temp+1 - :3 lsr ; A=A/8 - sta temp - tya - and #%00000111 - tay - lda bittable,y - ldy temp - and PurchaseMeTable,y - beq SorryNoPurchase + tay + sta temp+1 + :3 lsr ; A=A/8 + sta temp + tya + and #%00000111 + tay + lda bittable,y + ldy temp + and PurchaseMeTable,y + beq SorryNoPurchase PurchaseIt - ldy temp+1 - lda WeaponPriceL,y - sta temp - lda WeaponPriceH,y - sta temp+1 - ;price of the weapon in temp - lda MoneyL,x - sta temp2 - lda MoneyH,x - sta temp2+1 - ;current monies in temp2 - cpw temp2 temp - bcc SorryNoPurchase - ; deduct monies from the bank account - sec - lda temp2 - sbc temp - sta MoneyL,x - lda temp2+1 - sbc temp+1 - sta MoneyH,x - - lda TanksWeaponsTableL,x - sta temp - lda TanksWeaponsTableH,x - sta temp+1 + ldy temp+1 + lda WeaponPriceL,y + sta temp + lda WeaponPriceH,y + sta temp+1 + ;price of the weapon in temp + lda MoneyL,x + sta temp2 + lda MoneyH,x + sta temp2+1 + ;current monies in temp2 + cpw temp2 temp + bcc SorryNoPurchase + ; deduct monies from the bank account + sec + lda temp2 + sbc temp + sta MoneyL,x + lda temp2+1 + sbc temp+1 + sta MoneyH,x - lda WeaponUnits,y - clc - adc (temp),y - cmp #99 ;max number of weapon units - bcc NotExceeded - lda #99 + lda TanksWeaponsTableL,x + sta temp + lda TanksWeaponsTableH,x + sta temp+1 + + lda WeaponUnits,y + clc + adc (temp),y + cmp #99 ;max number of weapon units + bcc NotExceeded + lda #99 NotExceeded - sta (temp),y - - + sta (temp),y + + SorryNoPurchase - rts - .endp - + rts + .endp + ;---------------------------------------------- .proc ShooterPurchase - ; first try to buy defensives -; mva #2 tempXroller; number of offensive purchases to perform - ldx TankNr + ; first try to buy defensives +; mva #2 tempXroller; number of offensive purchases to perform + ldx TankNr @ - randomize ind_Battery________ ind_StrongParachute - jsr TryToPurchaseOnePiece -; dec tempXroller -; bne @- - - ; and now offensives - mva #4 tempXroller; number of offensive purchases to perform - ;ldx TankNr -@ - randomize ind_Missile________ ind_Heavy_Roller___ - jsr TryToPurchaseOnePiece - dec tempXroller - bne @- + randomize ind_Battery ind_StrongParachute + jsr TryToPurchaseOnePiece +; dec tempXroller +; bne @- - rts + ; and now offensives + mva #4 tempXroller; number of offensive purchases to perform + ;ldx TankNr +@ + randomize ind_Missile ind_Heavy_Roller + jsr TryToPurchaseOnePiece + dec tempXroller + bne @- + + rts .endp ;---------------------------------------------- .proc PoolsharkPurchase - ; first try to buy defensives -; mva #2 tempXroller; number of offensive purchases to perform - ldx TankNr + ; first try to buy defensives +; mva #2 tempXroller; number of offensive purchases to perform + ldx TankNr @ - randomize ind_Battery________ ind_Bouncy_Castle__ - jsr TryToPurchaseOnePiece - dec tempXroller -; bpl @- - - ; and now offensives - mva #6 tempXroller; number of purchases to perform - ;ldx TankNr -@ - randomize ind_Missile________ ind_Dirt_Charge____ - jsr TryToPurchaseOnePiece - dec tempXroller - bne @- + randomize ind_Battery ind_Bouncy_Castle + jsr TryToPurchaseOnePiece + dec tempXroller +; bpl @- - rts + ; and now offensives + mva #6 tempXroller; number of purchases to perform + ;ldx TankNr +@ + randomize ind_Missile ind_Dirt_Charge + jsr TryToPurchaseOnePiece + dec tempXroller + bne @- + + rts .endp ;---------------------------------------------- .proc TosserPurchase @@ -915,27 +917,27 @@ SorryNoPurchase ; what is my money level ldx TankNr lda MoneyH,x ; money / 256 - lsr ; /2 + lsr ; /2 sta tempXroller ; perform this many purchase attempts ; first try to buy defensives ; mva #1 tempXroller; number of defensive purchases to perform @ - randomize ind_Battery________ ind_Bouncy_Castle__ + randomize ind_Battery ind_Bouncy_Castle jsr TryToPurchaseOnePiece dec tempXroller bpl @- - + ; and now offensives lda MoneyH,x ; money / 256 asl ;*2 sta tempXroller ; perform this many purchase attempts @ - randomize ind_Missile________ ind_Dirt_Charge____ + randomize ind_Missile ind_Dirt_Charge jsr TryToPurchaseOnePiece dec tempXroller bpl @- - rts + rts .endp ;---------------------------------------------- .proc CyborgPurchase @@ -943,63 +945,63 @@ SorryNoPurchase ; what is my money level ldx TankNr lda MoneyH,x ; money / 256 - lsr ; /2 + lsr ; /2 sta tempXroller ; perform this many purchase attempts ; first try to buy defensives ; mva #1 tempXroller; number of defensive purchases to perform @ - randomize ind_Battery________ ind_Bouncy_Castle__ + randomize ind_Battery ind_Bouncy_Castle jsr TryToPurchaseOnePiece2 dec tempXroller bpl @- - + ; and now offensives lda MoneyH,x ; money / 256 :3 asl ;*8 sta tempXroller ; perform this many purchase attempts @ - randomize first_offensive____ last_offensive_____ + randomize first_offensive last_offensive jsr TryToPurchaseOnePiece2 dec tempXroller bpl @- - rts + rts .endp ;---------------------------------------------- .proc ChooseBestOffensive ; choose the best weapon ; X - TankNr ;---------------------------------------------- - ldy #ind_Dirt_Charge____+1 ;the last weapon to choose +1 (not BFG or Laser :) ) -NotFromAll + ldy #ind_Dirt_Charge +1 ;the last weapon to choose +1 (not BFG or Laser :) ) +NotFromAll ; Y - the last offensive weapon to use + 1 - lda TanksWeaponsTableL,x - sta temp - lda TanksWeaponsTableH,x - sta temp+1 + lda TanksWeaponsTableL,x + sta temp + lda TanksWeaponsTableH,x + sta temp+1 loop - dey - lda (temp),y - beq loop - tya - sta ActiveWeapon,x - rts + dey + lda (temp),y + beq loop + tya + sta ActiveWeapon,x + rts .endp ;---------------------------------------------- .proc GetDistance ; calculates lores ( /4 ) distance from tank X to TargetTankNr(Y) ; result in A ;---------------------------------------------- - ldy TargetTankNr - lda LowResDistances,x - cmp LowResDistances,y -@ bcs YisLower - sec - lda LowResDistances,y - sbc LowResDistances,x - rts + ldy TargetTankNr + lda LowResDistances,x + cmp LowResDistances,y +@ bcs YisLower + sec + lda LowResDistances,y + sbc LowResDistances,x + rts YisLower - lda LowResDistances,x - sbc LowResDistances,y - rts + lda LowResDistances,x + sbc LowResDistances,y + rts .endp \ No newline at end of file diff --git a/artwork/joytest.asm b/artwork/joytest.asm index 0dbf434..0bd66ce 100644 --- a/artwork/joytest.asm +++ b/artwork/joytest.asm @@ -1,10 +1,10 @@ icl '../lib/atari.hea' - + org $2000 -joytest +joytest mva #0 dmactls - + @ lda trig0 beq pressed @@ -15,6 +15,5 @@ pressed ;ora jstick0 sta colbak jmp @- - - run joytest - \ No newline at end of file + + run joytest diff --git a/artwork/sfx/rmtplayr_modified.asm b/artwork/sfx/rmtplayr_modified.asm index 506b580..0ba35d0 100644 --- a/artwork/sfx/rmtplayr_modified.asm +++ b/artwork/sfx/rmtplayr_modified.asm @@ -8,7 +8,7 @@ ; 1. RMT player routine needs 19 itself reserved bytes in zero page (no accessed ; from any other routines) as well as cca 1KB of memory before the "PLAYER" ; address for frequency tables and functionary variables. It's: -; a) from PLAYER-$03c0 to PLAYER for stereo RMTplayer +; a) from PLAYER-$03c0 to PLAYER for stereo RMTplayer ; b) from PLAYER-$0320 to PLAYER for mono RMTplayer ; ; 2. RMT player routine MUST (!!!) be compiled from the begin of the memory page. @@ -16,15 +16,15 @@ ; ; 3. Because of RMTplayer provides a lot of effects, it spent a lot of CPU time. ; -; STEREOMODE equ 0..3 ;0 => compile RMTplayer for 4 tracks mono -; ;1 => compile RMTplayer for 8 tracks stereo -; ;2 => compile RMTplayer for 4 tracks stereo L1 R2 R3 L4 -; ;3 => compile RMTplayer for 4 tracks stereo L1 L2 R3 R4 +; STEREOMODE equ 0..3 ;0 => compile RMTplayer for 4 tracks mono +; ;1 => compile RMTplayer for 8 tracks stereo +; ;2 => compile RMTplayer for 4 tracks stereo L1 R2 R3 L4 +; ;3 => compile RMTplayer for 4 tracks stereo L1 L2 R3 R4 -TRACKS equ 4 +TRACKS equ 4 ; RMT FEATures definitions file ; For optimizations of RMT player routine to concrete RMT modul only! - icl "feat.txt" + icl "feat.txt" ;FEAT_EFFECTS equ FEAT_EFFECTVIBRATO||FEAT_EFFECTFSHIFT ; ; RMT ZeroPage addresses @@ -37,7 +37,7 @@ p_instrstable = p_tis .zpvar nr .word .zpvar nt .byte .zpvar reg1 .byte -.zpvar reg2 .byte +.zpvar reg2 .byte .zpvar reg3 .byte .zpvar tmp .byte .zpvar v_audctl .byte ; de-self-modification vars @@ -49,43 +49,43 @@ p_instrstable = p_tis .zpvar RMTSFXVOLUME .byte ; MOVED TO variables.asm -; org PLAYER-$400+$e0 +; org PLAYER-$400+$e0 ;track_variables -;trackn_db .ds TRACKS -;trackn_hb .ds TRACKS -;trackn_idx .ds TRACKS -;trackn_pause .ds TRACKS -;trackn_note .ds TRACKS -;trackn_volume .ds TRACKS -;trackn_distor .ds TRACKS -;trackn_shiftfrq .ds TRACKS -;trackn_instrx2 .ds TRACKS -;trackn_instrdb .ds TRACKS -;trackn_instrhb .ds TRACKS -;trackn_instridx .ds TRACKS -;trackn_instrlen .ds TRACKS -;trackn_instrlop .ds TRACKS -;trackn_instrreachend .ds TRACKS +;trackn_db .ds TRACKS +;trackn_hb .ds TRACKS +;trackn_idx .ds TRACKS +;trackn_pause .ds TRACKS +;trackn_note .ds TRACKS +;trackn_volume .ds TRACKS +;trackn_distor .ds TRACKS +;trackn_shiftfrq .ds TRACKS +;trackn_instrx2 .ds TRACKS +;trackn_instrdb .ds TRACKS +;trackn_instrhb .ds TRACKS +;trackn_instridx .ds TRACKS +;trackn_instrlen .ds TRACKS +;trackn_instrlop .ds TRACKS +;trackn_instrreachend .ds TRACKS ;trackn_volumeslidedepth .ds TRACKS ;trackn_volumeslidevalue .ds TRACKS -;trackn_effdelay .ds TRACKS -;trackn_effvibratoa .ds TRACKS -;trackn_effshift .ds TRACKS +;trackn_effdelay .ds TRACKS +;trackn_effvibratoa .ds TRACKS +;trackn_effshift .ds TRACKS ;trackn_tabletypespeed .ds TRACKS -;trackn_tablenote .ds TRACKS -;trackn_tablea .ds TRACKS -;trackn_tableend .ds TRACKS -;trackn_tablelop .ds TRACKS -;trackn_tablespeeda .ds TRACKS -;trackn_command .ds TRACKS -;trackn_filter .ds TRACKS -;trackn_audf .ds TRACKS -;trackn_audc .ds TRACKS -;trackn_audctl .ds TRACKS -;v_aspeed .ds 1 +;trackn_tablenote .ds TRACKS +;trackn_tablea .ds TRACKS +;trackn_tableend .ds TRACKS +;trackn_tablelop .ds TRACKS +;trackn_tablespeeda .ds TRACKS +;trackn_command .ds TRACKS +;trackn_filter .ds TRACKS +;trackn_audf .ds TRACKS +;trackn_audc .ds TRACKS +;trackn_audctl .ds TRACKS +;v_aspeed .ds 1 ;track_endvariables -INSTRPAR equ 12 +INSTRPAR equ 12 tabbeganddistor dta frqtabpure-frqtab,$00 dta frqtabpure-frqtab,$20 @@ -96,451 +96,451 @@ tabbeganddistor dta frqtabbass1-frqtab,$c0 dta frqtabbass2-frqtab,$c0 vibtabbeg dta 0,vib1-vib0,vib2-vib0,vib3-vib0 -vib0 dta 0 -vib1 dta 1,-1,-1,1 -vib2 dta 1,0,-1,-1,0,1 -vib3 dta 1,1,0,-1,-1,-1,-1,0,1,1 +vib0 dta 0 +vib1 dta 1,-1,-1,1 +vib2 dta 1,0,-1,-1,0,1 +vib3 dta 1,1,0,-1,-1,-1,-1,0,1,1 vibtabnext - dta vib0-vib0+0 - dta vib1-vib0+1,vib1-vib0+2,vib1-vib0+3,vib1-vib0+0 - dta vib2-vib0+1,vib2-vib0+2,vib2-vib0+3,vib2-vib0+4,vib2-vib0+5,vib2-vib0+0 - dta vib3-vib0+1,vib3-vib0+2,vib3-vib0+3,vib3-vib0+4,vib3-vib0+5,vib3-vib0+6,vib3-vib0+7,vib3-vib0+8,vib3-vib0+9,vib3-vib0+0 + dta vib0-vib0+0 + dta vib1-vib0+1,vib1-vib0+2,vib1-vib0+3,vib1-vib0+0 + dta vib2-vib0+1,vib2-vib0+2,vib2-vib0+3,vib2-vib0+4,vib2-vib0+5,vib2-vib0+0 + dta vib3-vib0+1,vib3-vib0+2,vib3-vib0+3,vib3-vib0+4,vib3-vib0+5,vib3-vib0+6,vib3-vib0+7,vib3-vib0+8,vib3-vib0+9,vib3-vib0+0 .align $100 frqtab - ERT [255 -; ldy #0 -; tya -;ri0 sta track_variables,y -; sta track_endvariables-$100,y -; iny -; bne ri0 -; ELS - ldy #track_endvariables-track_variables - lda #0 -ri0 sta track_variables-1,y - dey - bne ri0 -; EIF - ldy #4 - lda (ns),y - sta v_maxtracklen - iny - lda (ns),y - sta v_speed - ldy #8 -ri1 lda (ns),y - sta p_tis-8,y - iny - cpy #8+8 - bne ri1 - pla - pha - asl @ - asl @ - clc - adc p_song - sta p_song - pla - php - and #$c0 - asl @ - rol @ - rol @ - plp - adc p_song+1 - sta p_song+1 - jsr GetSongLineTrackLineInitOfNewSetInstrumentsOnlyRmtp3 + stx ns + sty ns+1 + pha +; IFT track_endvariables-track_variables>255 +; ldy #0 +; tya +;ri0 sta track_variables,y +; sta track_endvariables-$100,y +; iny +; bne ri0 +; ELS + ldy #track_endvariables-track_variables + lda #0 +ri0 sta track_variables-1,y + dey + bne ri0 +; EIF + ldy #4 + lda (ns),y + sta v_maxtracklen + iny + lda (ns),y + sta v_speed + ldy #8 +ri1 lda (ns),y + sta p_tis-8,y + iny + cpy #8+8 + bne ri1 + pla + pha + asl @ + asl @ + clc + adc p_song + sta p_song + pla + php + and #$c0 + asl @ + rol @ + rol @ + plp + adc p_song+1 + sta p_song+1 + jsr GetSongLineTrackLineInitOfNewSetInstrumentsOnlyRmtp3 rmt_silence - lda #0 - sta $d208 - ldy #3 - sty $d20f - ldy #8 -si1 sta $d200,y - dey - bpl si1 - lda #FEAT_INSTRSPEED - rts + lda #0 + sta $d208 + ldy #3 + sty $d20f + ldy #8 +si1 sta $d200,y + dey + bpl si1 + lda #FEAT_INSTRSPEED + rts GetSongLineTrackLineInitOfNewSetInstrumentsOnlyRmtp3 GetSongLine - ldx #0 - stx v_abeat + ldx #0 + stx v_abeat nn0 -nn1 txa - tay - lda (p_song),y - cmp #$fe - bcs nn2 - tay - lda (p_trackslbstable),y - sta trackn_db,x - lda (p_trackshbstable),y +nn1 txa + tay + lda (p_song),y + cmp #$fe + bcs nn2 + tay + lda (p_trackslbstable),y + sta trackn_db,x + lda (p_trackshbstable),y nn1a sta trackn_hb,x - lda #0 - sta trackn_idx,x - lda #1 + lda #0 + sta trackn_idx,x + lda #1 nn1a2 sta trackn_pause,x - lda #$80 - sta trackn_instrx2,x - inx -xtracks01 cpx #TRACKS - bne nn1 - lda p_song - clc -xtracks02 adc #TRACKS - sta p_song - bcc GetTrackLine - inc p_song+1 + lda #$80 + sta trackn_instrx2,x + inx +xtracks01 cpx #TRACKS + bne nn1 + lda p_song + clc +xtracks02 adc #TRACKS + sta p_song + bcc GetTrackLine + inc p_song+1 nn1b - jmp GetTrackLine + jmp GetTrackLine nn2 - beq nn3 + beq nn3 nn2a - lda #0 - beq nn1a2 + lda #0 + beq nn1a2 nn3 - ldy #2 - lda (p_song),y - tax - iny - lda (p_song),y - sta p_song+1 - stx p_song - ldx #0 - beq nn0 + ldy #2 + lda (p_song),y + tax + iny + lda (p_song),y + sta p_song+1 + stx p_song + ldx #0 + beq nn0 GetTrackLine oo0 oo0a - lda v_speed + lda v_speed - sta v_bspeed - ldx #-1 + sta v_bspeed + ldx #-1 oo1 - inx - dec trackn_pause,x - bne oo1x + inx + dec trackn_pause,x + bne oo1x oo1b - lda trackn_db,x - sta ns - lda trackn_hb,x - sta ns+1 + lda trackn_db,x + sta ns + lda trackn_hb,x + sta ns+1 oo1i - ldy trackn_idx,x - inc trackn_idx,x - lda (ns),y - sta reg1 - and #$3f - cmp #61 - beq oo1a - bcs oo2 - sta trackn_note,x - iny - lda (ns),y - lsr @ - and #$3f*2 - sta trackn_instrx2,x + ldy trackn_idx,x + inc trackn_idx,x + lda (ns),y + sta reg1 + and #$3f + cmp #61 + beq oo1a + bcs oo2 + sta trackn_note,x + iny + lda (ns),y + lsr @ + and #$3f*2 + sta trackn_instrx2,x oo1a - lda #1 - sta trackn_pause,x - ldy trackn_idx,x - inc trackn_idx,x - lda (ns),y - lsr @ - ror reg1 - lsr @ - ror reg1 - lda reg1 - and #$f0 - sta trackn_volume,x + lda #1 + sta trackn_pause,x + ldy trackn_idx,x + inc trackn_idx,x + lda (ns),y + lsr @ + ror reg1 + lsr @ + ror reg1 + lda reg1 + and #$f0 + sta trackn_volume,x oo1x -xtracks03sub1 cpx #TRACKS-1 - bne oo1 - lda v_bspeed +xtracks03sub1 cpx #TRACKS-1 + bne oo1 + lda v_bspeed - sta v_speed - sta v_aspeed - jmp InitOfNewSetInstrumentsOnly + sta v_speed + sta v_aspeed + jmp InitOfNewSetInstrumentsOnly oo2 - cmp #63 - beq oo63 - lda reg1 - and #$c0 - beq oo62_b - asl @ - rol @ - rol @ - sta trackn_pause,x - jmp oo1x + cmp #63 + beq oo63 + lda reg1 + and #$c0 + beq oo62_b + asl @ + rol @ + rol @ + sta trackn_pause,x + jmp oo1x oo62_b - iny - lda (ns),y - sta trackn_pause,x - inc trackn_idx,x - jmp oo1x + iny + lda (ns),y + sta trackn_pause,x + inc trackn_idx,x + jmp oo1x oo63 - lda reg1 - bmi oo63_1X - iny - lda (ns),y - sta v_bspeed - inc trackn_idx,x - jmp oo1i + lda reg1 + bmi oo63_1X + iny + lda (ns),y + sta v_bspeed + inc trackn_idx,x + jmp oo1i oo63_1X - cmp #255 - beq oo63_11 - iny - lda (ns),y - sta trackn_idx,x - jmp oo1i + cmp #255 + beq oo63_11 + iny + lda (ns),y + sta trackn_idx,x + jmp oo1i oo63_11 - jmp GetSongLine -p2xrmtp3 jmp rmt_p3 + jmp GetSongLine +p2xrmtp3 jmp rmt_p3 p2x0 dex - bmi p2xrmtp3 + bmi p2xrmtp3 InitOfNewSetInstrumentsOnly p2x1 ldy trackn_instrx2,x - bmi p2x0 - jsr SetUpInstrumentY2 - jmp p2x0 + bmi p2x0 + jsr SetUpInstrumentY2 + jmp p2x0 rmt_sfx - sta trackn_note,x - lda RMTSFXVOLUME ;* sfx note volume*16 - ;* label for sfx note volume parameter overwriting - sta trackn_volume,x + sta trackn_note,x + lda RMTSFXVOLUME ;* sfx note volume*16 + ;* label for sfx note volume parameter overwriting + sta trackn_volume,x SetUpInstrumentY2 - lda (p_instrstable),y - sta trackn_instrdb,x - sta nt - iny - lda (p_instrstable),y - sta trackn_instrhb,x - sta nt+1 - lda #1 - sta trackn_filter,x - tay - lda (nt),y - sta trackn_tablelop,x - iny - lda (nt),y - sta trackn_instrlen,x - iny - lda (nt),y - sta trackn_instrlop,x - iny - lda (nt),y - sta trackn_tabletypespeed,x - sta trackn_tablespeeda,x - iny - lda (nt),y - sta trackn_audctl,x - iny - lda (nt),y - sta trackn_volumeslidedepth,x - ldy #8 - lda (nt),y - sta trackn_effdelay,x - iny - lda (nt),y - tay - lda vibtabbeg,y - sta trackn_effvibratoa,x - ldy #10 - lda (nt),y - sta trackn_effshift,x - lda #128 - sta trackn_volumeslidevalue,x - sta trackn_instrx2,x - asl @ - sta trackn_instrreachend,x - sta trackn_shiftfrq,x - tay - lda (nt),y - sta trackn_tableend,x - adc #0 - sta trackn_instridx,x - lda #INSTRPAR - sta trackn_tablea,x - tay - lda (nt),y - sta trackn_tablenote,x + lda (p_instrstable),y + sta trackn_instrdb,x + sta nt + iny + lda (p_instrstable),y + sta trackn_instrhb,x + sta nt+1 + lda #1 + sta trackn_filter,x + tay + lda (nt),y + sta trackn_tablelop,x + iny + lda (nt),y + sta trackn_instrlen,x + iny + lda (nt),y + sta trackn_instrlop,x + iny + lda (nt),y + sta trackn_tabletypespeed,x + sta trackn_tablespeeda,x + iny + lda (nt),y + sta trackn_audctl,x + iny + lda (nt),y + sta trackn_volumeslidedepth,x + ldy #8 + lda (nt),y + sta trackn_effdelay,x + iny + lda (nt),y + tay + lda vibtabbeg,y + sta trackn_effvibratoa,x + ldy #10 + lda (nt),y + sta trackn_effshift,x + lda #128 + sta trackn_volumeslidevalue,x + sta trackn_instrx2,x + asl @ + sta trackn_instrreachend,x + sta trackn_shiftfrq,x + tay + lda (nt),y + sta trackn_tableend,x + adc #0 + sta trackn_instridx,x + lda #INSTRPAR + sta trackn_tablea,x + tay + lda (nt),y + sta trackn_tablenote,x xata_rtshere - rts + rts rmt_play rmt_p0 - jsr SetPokey + jsr SetPokey rmt_p1 rmt_p2 - dec v_aspeed - bne rmt_p3 - inc v_abeat - lda v_abeat + dec v_aspeed + bne rmt_p3 + inc v_abeat + lda v_abeat - cmp v_maxtracklen + cmp v_maxtracklen - beq p2o3 - jmp GetTrackLine + beq p2o3 + jmp GetTrackLine p2o3 - jmp GetSongLineTrackLineInitOfNewSetInstrumentsOnlyRmtp3 -go_ppnext jmp ppnext + jmp GetSongLineTrackLineInitOfNewSetInstrumentsOnlyRmtp3 +go_ppnext jmp ppnext rmt_p3 - lda #>frqtab - sta nr+1 -xtracks05sub1 ldx #TRACKS-1 + lda #>frqtab + sta nr+1 +xtracks05sub1 ldx #TRACKS-1 pp1 - lda trackn_instrhb,x - beq go_ppnext - sta ns+1 - lda trackn_instrdb,x - sta ns - ldy trackn_instridx,x - lda (ns),y - sta reg1 - iny - lda (ns),y - sta reg2 - iny - lda (ns),y - sta reg3 - iny - tya - cmp trackn_instrlen,x - bcc pp2 - beq pp2 - lda #$80 - sta trackn_instrreachend,x + lda trackn_instrhb,x + beq go_ppnext + sta ns+1 + lda trackn_instrdb,x + sta ns + ldy trackn_instridx,x + lda (ns),y + sta reg1 + iny + lda (ns),y + sta reg2 + iny + lda (ns),y + sta reg3 + iny + tya + cmp trackn_instrlen,x + bcc pp2 + beq pp2 + lda #$80 + sta trackn_instrreachend,x pp1b - lda trackn_instrlop,x -pp2 sta trackn_instridx,x - lda reg1 - and #$0f - ora trackn_volume,x - tay - lda volumetab,y - sta tmp - lda reg2 - and #$0e - tay - lda tabbeganddistor,y - sta nr - lda tmp - ora tabbeganddistor+1,y - sta trackn_audc,x + lda trackn_instrlop,x +pp2 sta trackn_instridx,x + lda reg1 + and #$0f + ora trackn_volume,x + tay + lda volumetab,y + sta tmp + lda reg2 + and #$0e + tay + lda tabbeganddistor,y + sta nr + lda tmp + ora tabbeganddistor+1,y + sta trackn_audc,x InstrumentsEffects - lda trackn_effdelay,x - beq ei2 - cmp #1 - bne ei1 - lda trackn_shiftfrq,x - clc - adc trackn_effshift,x - clc - ldy trackn_effvibratoa,x - adc vib0,y - sta trackn_shiftfrq,x - lda vibtabnext,y - sta trackn_effvibratoa,x - jmp ei2 + lda trackn_effdelay,x + beq ei2 + cmp #1 + bne ei1 + lda trackn_shiftfrq,x + clc + adc trackn_effshift,x + clc + ldy trackn_effvibratoa,x + adc vib0,y + sta trackn_shiftfrq,x + lda vibtabnext,y + sta trackn_effvibratoa,x + jmp ei2 ei1 - dec trackn_effdelay,x + dec trackn_effdelay,x ei2 - ldy trackn_tableend,x - cpy #INSTRPAR+1 - bcc ei3 - lda trackn_tablespeeda,x - bpl ei2f + ldy trackn_tableend,x + cpy #INSTRPAR+1 + bcc ei3 + lda trackn_tablespeeda,x + bpl ei2f ei2c - tya - cmp trackn_tablea,x - bne ei2c2 - lda trackn_tablelop,x - sta trackn_tablea,x - bne ei2a + tya + cmp trackn_tablea,x + bne ei2c2 + lda trackn_tablelop,x + sta trackn_tablea,x + bne ei2a ei2c2 - inc trackn_tablea,x + inc trackn_tablea,x ei2a - lda trackn_instrdb,x - sta nt - lda trackn_instrhb,x - sta nt+1 - ldy trackn_tablea,x - lda (nt),y - sta trackn_tablenote,x - lda trackn_tabletypespeed,x + lda trackn_instrdb,x + sta nt + lda trackn_instrhb,x + sta nt+1 + ldy trackn_tablea,x + lda (nt),y + sta trackn_tablenote,x + lda trackn_tabletypespeed,x ei2f - sec - sbc #1 - sta trackn_tablespeeda,x + sec + sbc #1 + sta trackn_tablespeeda,x ei3 - lda trackn_instrreachend,x - bpl ei4 - lda trackn_volume,x - beq ei4 - tay - lda trackn_volumeslidevalue,x - clc - adc trackn_volumeslidedepth,x - sta trackn_volumeslidevalue,x - bcc ei4 - tya - sbc #16 - sta trackn_volume,x + lda trackn_instrreachend,x + bpl ei4 + lda trackn_volume,x + beq ei4 + tay + lda trackn_volumeslidevalue,x + clc + adc trackn_volumeslidedepth,x + sta trackn_volumeslidevalue,x + bcc ei4 + tya + sbc #16 + sta trackn_volume,x ei4 - lda reg2 - sta trackn_command,x - and #$70 - beq cmd0 + lda reg2 + sta trackn_command,x + and #$70 + beq cmd0 cmd1 - lda reg3 - jmp cmd0c + lda reg3 + jmp cmd0c cmd2 cmd3 cmd4 @@ -548,101 +548,101 @@ cmd5 cmd6 cmd7 cmd0 - lda trackn_note,x - clc - adc reg3 + lda trackn_note,x + clc + adc reg3 cmd0a - clc - adc trackn_tablenote,x - cmp #61 - bcc cmd0a1 - lda #0 - sta trackn_audc,x - lda #63 + clc + adc trackn_tablenote,x + cmp #61 + bcc cmd0a1 + lda #0 + sta trackn_audc,x + lda #63 cmd0a1 - tay - lda (nr),y - clc - adc trackn_shiftfrq,x + tay + lda (nr),y + clc + adc trackn_shiftfrq,x cmd0c - sta trackn_audf,x + sta trackn_audf,x pp9 ppnext - dex - bmi rmt_p4 - jmp pp1 + dex + bmi rmt_p4 + jmp pp1 rmt_p4 - lda trackn_audctl+0 - ora trackn_audctl+1 - ora trackn_audctl+2 - ora trackn_audctl+3 - tax + lda trackn_audctl+0 + ora trackn_audctl+1 + ora trackn_audctl+2 + ora trackn_audctl+3 + tax qq1 - stx v_audctl - lda trackn_command+0 - bpl qq2 - lda trackn_audc+0 - and #$0f - beq qq2 - lda trackn_audf+0 - clc - adc trackn_filter+0 - sta trackn_audf+2 - lda #0 - sta trackn_audc+2 + stx v_audctl + lda trackn_command+0 + bpl qq2 + lda trackn_audc+0 + and #$0f + beq qq2 + lda trackn_audf+0 + clc + adc trackn_filter+0 + sta trackn_audf+2 + lda #0 + sta trackn_audc+2 qq1a - txa - ora #4 - tax + txa + ora #4 + tax qq2 - lda trackn_command+1 - bpl qq3 - lda trackn_audc+1 - and #$0f - beq qq3 - lda trackn_audf+1 - clc - adc trackn_filter+1 - sta trackn_audf+3 - lda #0 - sta trackn_audc+3 + lda trackn_command+1 + bpl qq3 + lda trackn_audc+1 + and #$0f + beq qq3 + lda trackn_audf+1 + clc + adc trackn_filter+1 + sta trackn_audf+3 + lda #0 + sta trackn_audc+3 qq2a - txa - ora #2 - tax + txa + ora #2 + tax qq3 - cpx v_audctl - bne qq5 + cpx v_audctl + bne qq5 qq5 - stx v_audctl + stx v_audctl rmt_p5 -; lda v_ainstrspeed +; lda v_ainstrspeed .IF TARGET = 800 - ldx #$10 ; pseudo stereo - bne SetPokey_OffsetX ; pseudo stereo -.ELSE - rts + ldx #$10 ; pseudo stereo + bne SetPokey_OffsetX ; pseudo stereo +.ELIF TARGET = 5200 + rts .ENDIF SetPokey - ldx #0 ; POKEY registers offset (for stereo) + ldx #0 ; POKEY registers offset (for stereo) SetPokey_OffsetX - lda trackn_audf+0 - sta AUDF1,x - lda trackn_audc+0 - sta AUDC1,x - lda trackn_audf+1 - sta AUDF2,x - lda trackn_audc+1 - sta AUDC2,x - lda trackn_audf+2 - sta AUDF3,x - lda trackn_audc+2 - sta AUDC3,x - lda trackn_audf+3 - sta AUDF4,x - lda trackn_audc+3 - sta AUDC4,x - lda v_audctl - sta AUDCTL,x - rts + lda trackn_audf+0 + sta AUDF1,x + lda trackn_audc+0 + sta AUDC1,x + lda trackn_audf+1 + sta AUDF2,x + lda trackn_audc+1 + sta AUDC2,x + lda trackn_audf+2 + sta AUDF3,x + lda trackn_audc+2 + sta AUDC3,x + lda trackn_audf+3 + sta AUDF4,x + lda trackn_audc+3 + sta AUDC4,x + lda v_audctl + sta AUDCTL,x + rts RMTPLAYEREND diff --git a/artwork/splash_v2/lzss_player.asm b/artwork/splash_v2/lzss_player.asm index 6a0bdfd..f276135 100644 --- a/artwork/splash_v2/lzss_player.asm +++ b/artwork/splash_v2/lzss_player.asm @@ -6,8 +6,8 @@ song_end buffers .ds 256 * 9 - -POKEY2 = POKEY+$10 ; stereo + +POKEY2 = POKEY+$10 ; stereo ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Song Initialization - this runs in the first tick: @@ -15,14 +15,14 @@ POKEY2 = POKEY+$10 ; stereo .proc init_song ; pokeys init - lda #3 ; stereo - sta POKEY+$0f ; stereo - sta POKEY2+$0f ; stereo + lda #3 ; stereo + sta POKEY+$0f ; stereo + sta POKEY2+$0f ; stereo mva #1 bit_data ; Example: here initializes song pointer: - + ;mwa #song_data song_ptr ; Init all channels: @@ -32,8 +32,8 @@ clear ; Read just init value and store into buffer and POKEY jsr get_byte sta POKEY, x - sta POKEY2,x ; stereo - sta stereo_buff,x ; stereo + sta POKEY2,x ; stereo + sta stereo_buff,x ; stereo sty chn_copy, x cbuf sta buffers + 255 @@ -62,12 +62,12 @@ delay ; Play one frame of the song ; .proc play_frame - ldx #8 ; stereo -@ lda stereo_buff,x ; stereo - sta POKEY2,x ; stereo - dex ;stereo - bpl @- ; stereo - + ldx #8 ; stereo +@ lda stereo_buff,x ; stereo + sta POKEY2,x ; stereo + dex ;stereo + bpl @- ; stereo + lda #>buffers sta bptr+1 @@ -110,7 +110,7 @@ do_copy_byte: store: ldy cur_pos sta POKEY,x ; Store to output and buffer - sta stereo_buff,x ; stereo + sta stereo_buff,x ; stereo sta (bptr), y skip_chn: @@ -148,6 +148,5 @@ skip rts .endp -stereo_buff ; stereo - .ds 9 ; stereo - \ No newline at end of file +stereo_buff ; stereo + .ds 9 ; stereo diff --git a/artwork/splash_v2/splash.asm b/artwork/splash_v2/splash.asm index 2a0edba..93accb2 100644 --- a/artwork/splash_v2/splash.asm +++ b/artwork/splash_v2/splash.asm @@ -3,8 +3,8 @@ /* Mode: GED- (bitmap mode) */ /***************************************/ - icl "splash.h" - + icl "splash.h" + ; --- dmsc LZSS player routine on zero page org $80 @@ -17,265 +17,265 @@ chn_bits .ds 1 bit_data .ds 1 ; --- - org $00 + org $00 -fcnt .ds 2 -fadr .ds 2 -fhlp .ds 2 -cloc .ds 1 -regA .ds 1 -regX .ds 1 -regY .ds 1 -byt2 .ds 1 +fcnt .ds 2 +fadr .ds 2 +fhlp .ds 2 +cloc .ds 1 +regA .ds 1 +regX .ds 1 +regY .ds 1 +byt2 .ds 1 -zc .ds ZCOLORS +zc .ds ZCOLORS -* --- BASIC switch OFF - org $2000\ mva #$ff portb\ rts\ ini $2000 +* --- BASIC switch OFF + org $2000\ mva #$ff portb\ rts\ ini $2000 -* --- MAIN PROGRAM - org $2010 - IFT PIC_HEIGHT>=204 -scr ins "output.png.mic", 0, 8160 - :16 .byte 0 - ins "output.png.mic" , +8160 - ELS -scr ins "output.png.mic" - EIF +* --- MAIN PROGRAM + org $2010 + IFT PIC_HEIGHT>=204 +scr ins "output.png.mic", 0, 8160 + :16 .byte 0 + ins "output.png.mic" , +8160 + ELS +scr ins "output.png.mic" + EIF - .ifdef nil_used -nil :8*40 brk - eif + .ifdef nil_used +nil :8*40 brk + eif - .ALIGN $0400 -ant ANTIC_PROGRAM scr,ant + .ALIGN $0400 +ant ANTIC_PROGRAM scr,ant fnt - ift USESPRITES - .ALIGN $0800 - .ds $0300 -pmg SPRITES - eif - + ift USESPRITES + .ALIGN $0800 + .ds $0300 +pmg SPRITES + eif + FontSplash ins '../../artwork/weapons_AW6_mod.fnt' ; 'artwork/weapons.fnt' mother -; dta d" The Mother of All Games " - dta d" Father Unknown of All Games " - icl "lzss_player.asm" ; player (and data) for splash music +; dta d" The Mother of All Games " + dta d" Father Unknown of All Games " + icl "lzss_player.asm" ; player (and data) for splash music main jsr init_song -* --- init PMG +* --- init PMG - ift USESPRITES - mva >pmg pmbase ;missiles and players data address - mva #$03 pmcntl ;enable players and missiles - eif + ift USESPRITES + mva >pmg pmbase ;missiles and players data address + mva #$03 pmcntl ;enable players and missiles + eif - lda:cmp:req $14 ;wait 1 frame + lda:cmp:req $14 ;wait 1 frame - sei ;stop interrups - mva #$00 nmien ;stop all interrupts - mva #$fe portb ;switch off ROM to get 16k more ram + sei ;stop interrups + mva #$00 nmien ;stop all interrupts + mva #$fe portb ;switch off ROM to get 16k more ram - ZPINIT + ZPINIT //////////////////// // RASTER PROGRAM // //////////////////// -; jmp line239 - jmp raster_program_end +; jmp line239 + jmp raster_program_end -LOOP lda vcount ;synchronization for the first screen (picture) line - cmp #$02 - ;sta colpf0 - ;sta colpm0 - ;sta colbak - bne LOOP +LOOP lda vcount ;synchronization for the first screen (picture) line + cmp #$02 + ;sta colpf0 + ;sta colpm0 + ;sta colbak + bne LOOP - mva #%00111110 dmactl ;set new screen width - mva ant dlptr+1 + mva #%00111110 dmactl ;set new screen width + mva ant dlptr+1 icl "output.png.rp.ini" - + ;--- 16 lines down ---- !!! - :16 sta wsync - - ; wait 13 cycles !!! - :4 nop - inc byt2 - + :16 sta wsync + + ; wait 13 cycles !!! + :4 nop + inc byt2 + ;--- wait 18 cycles -; jsr _rts -; inc byt3 +; jsr _rts +; inc byt3 ;--- set global offset (23 cycles) - jsr _rts - cmp byt3\ pha:pla + jsr _rts + cmp byt3\ pha:pla ;--- empty line - jsr wait54cycle - inc byt2 + jsr wait54cycle + inc byt2 icl "output.png.rp" raster_program_end - lda >FontSplash - sta chbase -c0 lda #$00 - sta colbak -c1 lda #$00 - sta colpf0 -c2 lda #$02 - sta colpf1 -c3 lda #$08 - sta colpf2 -c4 lda #$00 - sta colpf3 -s0 lda #$03 - sta sizep0 - sta sizep1 - sta sizep2 - sta sizep3 - mva #$ff sizem - sta grafm - mva #$20 hposm0 - mva #$28 hposm1 - mva #$d0 hposm2 - mva #$d8 hposm3 - mva #$02 pmcntl - lda #$14 - sta gtictl + lda >FontSplash + sta chbase +c0 lda #$00 + sta colbak +c1 lda #$00 + sta colpf0 +c2 lda #$02 + sta colpf1 +c3 lda #$08 + sta colpf2 +c4 lda #$00 + sta colpf3 +s0 lda #$03 + sta sizep0 + sta sizep1 + sta sizep2 + sta sizep3 + mva #$ff sizem + sta grafm + mva #$20 hposm0 + mva #$28 hposm1 + mva #$d0 hposm2 + mva #$d8 hposm3 + mva #$02 pmcntl + lda #$14 + sta gtictl //-------------------- -// EXIT +// EXIT //-------------------- - lda trig0 ; FIRE #0 - beq stop + lda trig0 ; FIRE #0 + beq stop - lda trig1 ; FIRE #1 - beq stop + lda trig1 ; FIRE #1 + beq stop - lda consol ; START - and #1 - beq stop + lda consol ; START + and #1 + beq stop - lda skctl ; ANY KEY - and #$04 - bne skp + lda skctl ; ANY KEY + and #$04 + bne skp -stop mva #$00 pmcntl ;PMG disabled - tax - sta:rne hposp0,x+ +stop mva #$00 pmcntl ;PMG disabled + tax + sta:rne hposp0,x+ - ; silent - lda #0 + ; silent + lda #0 ldx #8 @ sta POKEY,x - sta POKEY2,x ; stereo + sta POKEY2,x ; stereo dex bpl @- - + ;no glitching please (issue #67) lda #0 sta $D400 ;dmactl sta $022F ;dmactls - mva #$ff portb ;ROM switch on - mva #$40 nmien ;only NMI interrupts, DLI disabled - cli ;IRQ enabled + mva #$ff portb ;ROM switch on + mva #$40 nmien ;only NMI interrupts, DLI disabled + cli ;IRQ enabled - rts ;return to ... DOS + rts ;return to ... DOS skp //-------------------- jsr play_frame - jmp LOOP + jmp LOOP ;--- wait54cycle - :2 inc byt2 + :2 inc byt2 wait44cycle - inc byt3 - nop + inc byt3 + nop wait36cycle - inc byt3 - jsr _rts + inc byt3 + jsr _rts wait18cycle - inc byt3 -_rts rts + inc byt3 +_rts rts -byt3 brk +byt3 brk ;--- -.MACRO ANTIC_PROGRAM - dta $70,$70 - :+8 dta $4e,a(:1+$0000+#*40) - :+8 dta $4e,a(:1+$0140+#*40) - :+8 dta $4e,a(:1+$0280+#*40) - :+8 dta $4e,a(:1+$03C0+#*40) - :+8 dta $4e,a(:1+$0500+#*40) - :+8 dta $4e,a(:1+$0640+#*40) - :+8 dta $4e,a(:1+$0780+#*40) - :+8 dta $4e,a(:1+$08C0+#*40) - :+8 dta $4e,a(:1+$0A00+#*40) - :+8 dta $4e,a(:1+$0B40+#*40) - :+8 dta $4e,a(:1+$0C80+#*40) - :+8 dta $4e,a(:1+$0DC0+#*40) - :+8 dta $4e,a(:1+$0F00+#*40) - :+8 dta $4e,a(:1+$1040+#*40) - :+8 dta $4e,a(:1+$1180+#*40) - :+8 dta $4e,a(:1+$12C0+#*40) - :+8 dta $4e,a(:1+$1400+#*40) - :+8 dta $4e,a(:1+$1540+#*40) - :+8 dta $4e,a(:1+$1680+#*40) - :+8 dta $4e,a(:1+$17C0+#*40) - :+8 dta $4e,a(:1+$1900+#*40) - :+8 dta $4e,a(:1+$1A40+#*40) - :+8 dta $4e,a(:1+$1B80+#*40) - :+8 dta $4e,a(:1+$1CC0+#*40) - :+8 dta $4e,a(:1+$1E00+#*40) -; :+4 dta $4e,a(:1+$1F40+#*40) -; :+4 dta $4e,a(:1+$1FF0+#*40) -; :+8 dta $4e,a(:1+$2090+#*40) -; :+8 dta $4e,a(:1+$21D0+#*40) -; :+8 dta $4e,a(:1+$2310+#*40) -; :+8 dta $4e,a(:1+$2450+#*40) - dta $00 - dta $42,a(mother) - dta $41,a(:2) +.MACRO ANTIC_PROGRAM + dta $70,$70 + :+8 dta $4e,a(:1+$0000+#*40) + :+8 dta $4e,a(:1+$0140+#*40) + :+8 dta $4e,a(:1+$0280+#*40) + :+8 dta $4e,a(:1+$03C0+#*40) + :+8 dta $4e,a(:1+$0500+#*40) + :+8 dta $4e,a(:1+$0640+#*40) + :+8 dta $4e,a(:1+$0780+#*40) + :+8 dta $4e,a(:1+$08C0+#*40) + :+8 dta $4e,a(:1+$0A00+#*40) + :+8 dta $4e,a(:1+$0B40+#*40) + :+8 dta $4e,a(:1+$0C80+#*40) + :+8 dta $4e,a(:1+$0DC0+#*40) + :+8 dta $4e,a(:1+$0F00+#*40) + :+8 dta $4e,a(:1+$1040+#*40) + :+8 dta $4e,a(:1+$1180+#*40) + :+8 dta $4e,a(:1+$12C0+#*40) + :+8 dta $4e,a(:1+$1400+#*40) + :+8 dta $4e,a(:1+$1540+#*40) + :+8 dta $4e,a(:1+$1680+#*40) + :+8 dta $4e,a(:1+$17C0+#*40) + :+8 dta $4e,a(:1+$1900+#*40) + :+8 dta $4e,a(:1+$1A40+#*40) + :+8 dta $4e,a(:1+$1B80+#*40) + :+8 dta $4e,a(:1+$1CC0+#*40) + :+8 dta $4e,a(:1+$1E00+#*40) +; :+4 dta $4e,a(:1+$1F40+#*40) +; :+4 dta $4e,a(:1+$1FF0+#*40) +; :+8 dta $4e,a(:1+$2090+#*40) +; :+8 dta $4e,a(:1+$21D0+#*40) +; :+8 dta $4e,a(:1+$2310+#*40) +; :+8 dta $4e,a(:1+$2450+#*40) + dta $00 + dta $42,a(mother) + dta $41,a(:2) .ENDM CL -.MACRO ZPINIT +.MACRO ZPINIT .ENDM -ZCOLORS = 0 +ZCOLORS = 0 ;--- - ini main + ini main ;--- - opt l- + opt l- -.MACRO SPRITES - icl "output.png.pmg" +.MACRO SPRITES + icl "output.png.pmg" .ENDM USESPRITES = 1 diff --git a/artwork/talk.asm b/artwork/talk.asm index 7eb46ab..8ef8985 100644 --- a/artwork/talk.asm +++ b/artwork/talk.asm @@ -77,7 +77,7 @@ L72 dta d"FAREWELL, CRUEL WORLD." L73 dta d"REMEMBER THE ALAMO!" L74 dta d"OH MAN!" L75 dta d"DOOUGH!" -L76 dta d"ANOTHER DAY, ANOTHER BOMB." +L76 dta d"NEW DAY, NEW BOMB." L77 dta d"THIS IS THE END, MY ONLY FRIEND." L78 dta d"VERY FUNNY." L79 dta d"THE FAT LADY SANG." @@ -89,7 +89,7 @@ L84 dta d"POW!" L85 dta d"BIF!" L86 dta d"BAM!" L87 dta d"ZONK!" -L88 dta d"I SHOULD'VE LISTENED TO MY MOTHER..." +L88 dta d"I SHOULD'VE LISTENED TO MY MOTHER." L89 dta d"I WALK THROUGH THE VALLEY OF THE SHADOW..." L90 dta d"WHAT WAS THAT NOISE?" L91 dta d"MAMA SAID THERE'D BE DAYS LIKE THIS." @@ -114,8 +114,8 @@ L109 dta d"I'VE FALLEN AND I CAN'T GET UP!" L110 dta d"911?" L111 dta d"OH NO! HERE I BLOW AGAIN!" L112 dta d"I'LL BE BACK..." -L113 dta d"HEY - I'VE GOT LAWYERS." -L114 dta d"TIME TO CALL 1-900-SUE-TANK." +L113 dta d"I'VE GOT LAWYERS!" +L114 dta d"CALL 1-900-SUE-TANK." L115 dta d"YOU BIG DUMMY!" ;(sanford and son) LEND OffensiveTextTableL diff --git a/constants.asm b/constants.asm index 69fbf21..cf10a5e 100644 --- a/constants.asm +++ b/constants.asm @@ -32,14 +32,18 @@ LevelNameBeginH .by >(NamesOfLevels+64),>(NamesOfLevels+74),>(NamesOfLevels+84) ;-------------- TanksWeaponsTableL - .by TanksWeapon1,>TanksWeapon2,>TanksWeapon3,>TanksWeapon4,>TanksWeapon5,>TanksWeapon6 + .REPT MaxPlayers, #+1 + .by >TanksWeapon:1 + .ENDR ;-------------- XtankOffsetGO_L - .by 6,56,106,156,206,0 + .by 6,56,106,156,206,0 XtankOffsetGO_H - .by 0,0,0,0,0,1 + .by 0,0,0,0,0,1 ;-----4x4 texts----- LineTop dta d"(%%%%%%%%%%%%)" @@ -55,7 +59,12 @@ LineGameOver seppukuText dta d"# SEPPUKU! #" areYouSureText - dta d"# SURE? Y/N #" + .IF TARGET = 800 + dta d"# SURE? Y/N #" + .ELIF TARGET = 5200 + dta d"#END? Y-1/N-0#" + .ENDIF + lineClear dta d" " @@ -64,17 +73,17 @@ TankColoursTable .BYTE $58,$2a,$96,$ca,$7a,$ed TankStatusColoursTable .BYTE $74,$c4,$24,$e4,$54,$94 ; Adam's order ;----------- GradientAddrL - .by dliColorsFore, >dliColorsFore, >dliColorsFore2 -dliColorsFore2 ; colors for NTSC - .by $0a ; one mountains color - .by $7e,$7a,$7c,$6a,$6c,$58,$5a,$48,$4a,$38 - .by $3a,$16,$18,$e6,$e8,$d4,$d6,$b4,$b6,$b6 -dliColorsFore2PAL ; colors for PAL - .by $0a ; one mountains color - .by $7e,$7a,$7c,$6a,$6c,$58,$5a,$48,$4a,$38 - .by $3a,$16,$18,$e6,$e8,$c4,$c6,$a4,$a6,$a6 + .by >dliColorsFore, >dliColorsFore, >dliColorsFore2 +dliColorsFore2 ; colors for NTSC + .by $0a ; one mountains color + .by $7a,$7a,$7a,$6a,$6a,$5a,$5a,$4a,$4a,$3a + .by $3a,$1a,$1a,$ea,$ea,$d8,$d8,$b8,$b8,$b8 +dliColorsFore2PAL ; colors for PAL + .by $0a ; one mountains color + .by $7a,$7a,$7a,$6a,$6a,$5a,$5a,$4a,$4a,$3a + .by $3a,$1a,$1a,$ea,$ea,$c8,$c8,$a8,$a8,$a8 ;----------- pmtableL ; addressess of the P/M memory for 6 tanks @@ -197,12 +206,9 @@ bittable2 ;---------------------------- disktance ;tanks distance .by 0,0 - .by screenwidth/3 - .by screenwidth/4 - .by screenwidth/5 - .by screenwidth/6 - .by screenwidth/7 - ;max number of players=6 +.REPT MaxPlayers-1, #+3 + .by screenwidth/:1 +.ENDR ; this table is for deciding where a tank should slide ; accordingly to what is below the tank @@ -222,113 +228,113 @@ TanksNamesDefault dta d"1st.Tank" dta d"2nd.Tank" dta d"3rd.Tank" - dta d"4th.Tank" - dta d"5th.Tank" - dta d"6th.Tank" +.REPT MaxPlayers-3, #+4 + dta d":1th.Tank" +.ENDR +;------------------------------------------------- +TankShapesTable .BYTE char_tank1 + .BYTE char_tank2 + .BYTE char_tank3 + .BYTE char_tank4 ;------------------------------------------------- -TankShapesTable .BYTE char_tank1___________ - .BYTE char_tank2___________ - .BYTE char_tank3___________ - .BYTE char_tank4___________ -;------------------------------------------------- WeaponPriceH ; weapons prices (tables with prices of weapons) - .by >price_Baby_Missile___ - .by >price_Missile________ - .by >price_Baby_Nuke______ - .by >price_Nuke___________ - .by >price_LeapFrog_______ - .by >price_Funky_Bomb_____ - .by >price_MIRV___________ - .by >price_Death_s_Head___ - .by >price_Napalm_________ - .by >price_Hot_Napalm_____ - .by >price_Tracer_________ - .by >price_Smoke_Tracer___ - .by >price_Baby_Roller____ - .by >price_Roller_________ - .by >price_Heavy_Roller___ - .by >price_Riot_Charge____ - .by >price_Riot_Blast_____ - .by >price_Riot_Bomb______ + .by >price_Baby_Missile + .by >price_Missile + .by >price_Baby_Nuke + .by >price_Nuke + .by >price_LeapFrog + .by >price_Funky_Bomb + .by >price_MIRV + .by >price_Death_s_Head + .by >price_Napalm + .by >price_Hot_Napalm + .by >price_Tracer + .by >price_Smoke_Tracer + .by >price_Baby_Roller + .by >price_Roller + .by >price_Heavy_Roller + .by >price_Riot_Charge + .by >price_Riot_Blast + .by >price_Riot_Bomb .by >price_Heavy_Riot_Bomb - .by >price_Baby_Digger____ - .by >price_Digger_________ - .by >price_Heavy_Digger___ - .by >price_Baby_Sandhog___ - .by >price_Sandhog________ - .by >price_Heavy_Sandhog__ - .by >price_Dirt_Clod______ - .by >price_Dirt_Ball______ - .by >price_Ton_of_Dirt____ - .by >price_Liquid_Dirt____ - .by >price_Dirt_Charge____ - .by >price_Buy_me_________ - .by >price_Laser__________ - .by >price_White_Flag_____ - .by >price_Battery________ - .by >price_Hovercraft_____ - .by >price_Parachute______ + .by >price_Baby_Digger + .by >price_Digger + .by >price_Heavy_Digger + .by >price_Baby_Sandhog + .by >price_Sandhog + .by >price_Heavy_Sandhog + .by >price_Dirt_Clod + .by >price_Dirt_Ball + .by >price_Ton_of_Dirt + .by >price_Liquid_Dirt + .by >price_Dirt_Charge + .by >price_Buy_me + .by >price_Laser + .by >price_White_Flag + .by >price_Battery + .by >price_Hovercraft + .by >price_Parachute .by >price_StrongParachute - .by >price_Mag_Deflector__ - .by >price_Shield_________ - .by >price_Heavy_Shield___ - .by >price_Force_Shield___ - .by >price_Bouncy_Castle__ - .by >price_Long_Barrel____ + .by >price_Mag_Deflector + .by >price_Shield + .by >price_Heavy_Shield + .by >price_Force_Shield + .by >price_Bouncy_Castle + .by >price_Long_Barrel .by >price_Nuclear_Winter_ - .by >price_Lazy_Boy_______ - .by >price_Lazy_Darwin____ - .by >price_Auto_Defense___ - .by >price_Spy_Hard_______ + .by >price_Lazy_Boy + .by >price_Lazy_Darwin + .by >price_Auto_Defense + .by >price_Spy_Hard WeaponPriceL - .by 0 diff --git a/constants_top.asm b/constants_top.asm index 79869b9..9ee1268 100644 --- a/constants_top.asm +++ b/constants_top.asm @@ -7,14 +7,14 @@ TanksPMOrder .BYTE 4,3,1,5,0,2 ; 0-3 = P0-P3 , 4 = M0+M1 , 5 = M2+M3 dliColorsBack :10 .by $02,$00 dliColorsFore - .by $0a ; one mountains color -; .by $0e,$0c,$0c,$0b,$0b,$0a,$0a,$09,$09,$08 ; mountains colors array -; .by $08,$08,$07,$07,$07,$06,$06,$06,$06,$05 - .by $0e,$0c,$0c,$0c,$0c,$0a,$0a,$0a,$0a,$08 ; mountains colors array new - .by $08,$08,$08,$06,$06,$06,$06,$06,$06,$04 + .by $0a ; one mountains color +; .by $0e,$0c,$0c,$0b,$0b,$0a,$0a,$09,$09,$08 ; mountains colors array +; .by $08,$08,$07,$07,$07,$06,$06,$06,$06,$05 + .by $0e,$0c,$0c,$0c,$0c,$0a,$0a,$0a,$0a,$08 ; mountains colors array new + .by $08,$08,$08,$06,$06,$06,$06,$06,$06,$04 CashOptionL ;(one zero less than on the screen) .by 0,<200,<800,<1200,<2000 -CashOptionH +CashOptionH .by 0,>200,>800,>1200,>2000 GravityTable .by 10,20,25,30,40 MaxWindTable .by 5,20,40,70,99 @@ -22,4 +22,4 @@ RoundsTable .by 10,20,30,40,50 AIForceTable .wo 375,470,630,720,820 ; starting shoot forces for different gravity flyDelayTable .by 255,150,75,35,1 seppukuTable .by 255, 45,25,15,9 -.endif +.ENDIF diff --git a/definitions.asm b/definitions.asm index 140f45a..536388b 100644 --- a/definitions.asm +++ b/definitions.asm @@ -4,7 +4,7 @@ screenheight = 200 screenBytes = 40 screenwidth = screenBytes*8 ; Max screenwidth = 512!!! -TankWidth = 8 +TankWidth = 8 ;---------------------------------------------- ; Player/missile memory PMGraph = $1800 ; real PM start = PMGraph + $0300 @@ -19,7 +19,7 @@ PMOffsetX = $2C ; P/M to graphics offset PMOffsetY = $2A ; P/M to graphics offset napalmRadius = 10 StandardBarrel = 6 ; standard tank barrel length -LongBarrel = 20 ; long barrel length +LongBarrel = 20 ; long barrel length TextBackgroundColor = $02 ; REAL constans - use: LDA #TextBackgroundColor TextForegroundColor = $0A @@ -28,123 +28,123 @@ space = 0 ; space in screencodes KeyRepeatSpeed = 10 ; (max 127 !!!) ;character codes for symbols (tank, parachute, etc. ) -char_parachute_______ = $02 -char_flag____________ = $1e -char_flame___________ = $14 -char_clear_flame_____ = $1c -char_digger__________ = $04 -char_sandhog_________ = $0c -char_sandhog_offset = char_sandhog_________ - char_digger__________ -char_tank1___________ = $20 -char_tank2___________ = $24 -char_tank3___________ = $2c -char_tank4___________ = $28 ; robotank shape +char_parachute = $02 +char_flag = $1e +char_flame = $14 +char_clear_flame = $1c +char_digger = $04 +char_sandhog = $0c +char_sandhog_offset = char_sandhog - char_digger +char_tank1 = $20 +char_tank2 = $24 +char_tank3 = $2c +char_tank4 = $28 ; robotank shape ;Weapon prices (*10 on screen) -price_Baby_Missile___ = 0 ;_00 -price_Missile________ = 96 ;_01 -price_Baby_Nuke______ = 111 ;_02 -price_Nuke___________ = 144 ;_03 -price_LeapFrog_______ = 192 ;_04 -price_Funky_Bomb_____ = 293 ;_05 -price_MIRV___________ = 456 ;_06 -price_Death_s_Head___ = 337 ;_07 -price_Napalm_________ = 125 ;_08 -price_Hot_Napalm_____ = 162 ;_09 -price_Tracer_________ = 102 ;_10 -price_Smoke_Tracer___ = 291 ;_11 -price_Baby_Roller____ = 211 ;_12 -price_Roller_________ = 244 ;_13 -price_Heavy_Roller___ = 326 ;_14 -price_Riot_Charge____ = 230 ;_15 -price_Riot_Blast_____ = 241 ;_16 -price_Riot_Bomb______ = 259 ;_17 +price_Baby_Missile = 0 ;_00 +price_Missile = 96 ;_01 +price_Baby_Nuke = 111 ;_02 +price_Nuke = 144 ;_03 +price_LeapFrog = 192 ;_04 +price_Funky_Bomb = 293 ;_05 +price_MIRV = 456 ;_06 +price_Death_s_Head = 337 ;_07 +price_Napalm = 125 ;_08 +price_Hot_Napalm = 162 ;_09 +price_Tracer = 102 ;_10 +price_Smoke_Tracer = 291 ;_11 +price_Baby_Roller = 211 ;_12 +price_Roller = 244 ;_13 +price_Heavy_Roller = 326 ;_14 +price_Riot_Charge = 230 ;_15 +price_Riot_Blast = 241 ;_16 +price_Riot_Bomb = 259 ;_17 price_Heavy_Riot_Bomb = 272 ;_18 -price_Baby_Digger____ = 136 ;_19 -price_Digger_________ = 176 ;_20 -price_Heavy_Digger___ = 207 ;_21 -price_Baby_Sandhog___ = 158 ;_22 -price_Sandhog________ = 191 ;_23 -price_Heavy_Sandhog__ = 223 ;_24 -price_Dirt_Clod______ = 104 ;_25 -price_Dirt_Ball______ = 130 ;_26 -price_Ton_of_Dirt____ = 171 ;_27 -price_Liquid_Dirt____ = 330 ;_28 -price_Dirt_Charge____ = 343 ;_29 -price_Buy_me_________ = 170 ;_30 -price_Laser__________ = 277 ;_31 -price_White_Flag_____ = $0 ;_32 -price_Battery________ = 300 ;_33 -price_Hovercraft_____ = 352 ;_34 -price_Parachute______ = 234 ;_35 -price_StrongParachute = 1000 ;_36 -price_Mag_Deflector__ = 745 ;_37 -price_Shield_________ = 224 ;_38 -price_Heavy_Shield___ = 628 ;_39 -price_Force_Shield___ = 1100 ;_40 -price_Bouncy_Castle__ = 512 ;_41 -price_Long_Barrel____ = 2100 ;_42 +price_Baby_Digger = 136 ;_19 +price_Digger = 176 ;_20 +price_Heavy_Digger = 207 ;_21 +price_Baby_Sandhog = 158 ;_22 +price_Sandhog = 191 ;_23 +price_Heavy_Sandhog = 223 ;_24 +price_Dirt_Clod = 104 ;_25 +price_Dirt_Ball = 130 ;_26 +price_Ton_of_Dirt = 171 ;_27 +price_Liquid_Dirt = 330 ;_28 +price_Dirt_Charge = 343 ;_29 +price_Buy_me = 170 ;_30 +price_Laser = 277 ;_31 +price_White_Flag = $0 ;_32 +price_Battery = 300 ;_33 +price_Hovercraft = 352 ;_34 +price_Parachute = 234 ;_35 +price_StrongParachute = 1000 ;_36 +price_Mag_Deflector = 745 ;_37 +price_Shield = 224 ;_38 +price_Heavy_Shield = 628 ;_39 +price_Force_Shield = 1100 ;_40 +price_Bouncy_Castle = 512 ;_41 +price_Long_Barrel = 2100 ;_42 price_Nuclear_Winter_ = 1000 ;_43 -price_Lazy_Boy_______ = 500 ;_44 -price_Lazy_Darwin____ = 730 ;_45 -price_Auto_Defense___ = 250 ;_46 -price_Spy_Hard_______ = 83 ;_47 +price_Lazy_Boy = 500 ;_44 +price_Lazy_Darwin = 730 ;_45 +price_Auto_Defense = 250 ;_46 +price_Spy_Hard = 83 ;_47 ;Weapon indexes (numbers) -ind_Baby_Missile___ = 0 -first_offensive____ = ind_Baby_Missile___ -ind_Missile________ = 1 -ind_Baby_Nuke______ = 2 -ind_Nuke___________ = 3 -ind_LeapFrog_______ = 4 -ind_Funky_Bomb_____ = 5 -ind_MIRV___________ = 6 -ind_Death_s_Head___ = 7 -ind_Napalm_________ = 8 -ind_Hot_Napalm_____ = 9 -ind_Tracer_________ = 10 -ind_Smoke_Tracer___ = 11 -ind_Baby_Roller____ = 12 -ind_Roller_________ = 13 -ind_Heavy_Roller___ = 14 -ind_Riot_Charge____ = 15 -ind_Riot_Blast_____ = 16 -ind_Riot_Bomb______ = 17 +ind_Baby_Missile = 0 +first_offensive = ind_Baby_Missile +ind_Missile = 1 +ind_Baby_Nuke = 2 +ind_Nuke = 3 +ind_LeapFrog = 4 +ind_Funky_Bomb = 5 +ind_MIRV = 6 +ind_Death_s_Head = 7 +ind_Napalm = 8 +ind_Hot_Napalm = 9 +ind_Tracer = 10 +ind_Smoke_Tracer = 11 +ind_Baby_Roller = 12 +ind_Roller = 13 +ind_Heavy_Roller = 14 +ind_Riot_Charge = 15 +ind_Riot_Blast = 16 +ind_Riot_Bomb = 17 ind_Heavy_Riot_Bomb = 18 -ind_Baby_Digger____ = 19 -ind_Digger_________ = 20 -ind_Heavy_Digger___ = 21 -ind_Baby_Sandhog___ = 22 -ind_Sandhog________ = 23 -ind_Heavy_Sandhog__ = 24 -ind_Dirt_Clod______ = 25 -ind_Dirt_Ball______ = 26 -ind_Ton_of_Dirt____ = 27 -ind_Liquid_Dirt____ = 28 -ind_Dirt_Charge____ = 29 -ind_Buy_me_________ = 30 -ind_Laser__________ = 31 -last_offensive_____ = ind_Laser__________ -ind_White_Flag_____ = 32 -first_defensive____ = ind_White_Flag_____ -ind_Battery________ = 33 -ind_Hovercraft_____ = 34 -ind_Parachute______ = 35 -ind_StrongParachute = 36 -ind_Mag_Deflector__ = 37 -ind_Shield_________ = 38 -ind_Heavy_Shield___ = 39 -ind_Force_Shield___ = 40 -ind_Bouncy_Castle__ = 41 -ind_Long_Barrel____ = 42 +ind_Baby_Digger = 19 +ind_Digger = 20 +ind_Heavy_Digger = 21 +ind_Baby_Sandhog = 22 +ind_Sandhog = 23 +ind_Heavy_Sandhog = 24 +ind_Dirt_Clod = 25 +ind_Dirt_Ball = 26 +ind_Ton_of_Dirt = 27 +ind_Liquid_Dirt = 28 +ind_Dirt_Charge = 29 +ind_Buy_me = 30 +ind_Laser = 31 +last_offensive = ind_Laser +ind_White_Flag = 32 +first_defensive = ind_White_Flag +ind_Battery = 33 +ind_Hovercraft = 34 +ind_Parachute = 35 +ind_StrongParachute = 36 +ind_Mag_Deflector = 37 +ind_Shield = 38 +ind_Heavy_Shield = 39 +ind_Force_Shield = 40 +ind_Bouncy_Castle = 41 +ind_Long_Barrel = 42 ind_Nuclear_Winter_ = 43 -ind_Lazy_Boy_______ = 44 -ind_Lazy_Darwin____ = 45 -ind_Auto_Defense___ = 46 -ind_Spy_Hard_______ = 47 -last_defensive_____ = ind_Spy_Hard_______ -last_real_defensive = ind_Bouncy_Castle__ -number_of_offensives = last_offensive_____ - first_offensive____+1 -number_of_defensives = (last_defensive_____ - first_defensive____+1) +ind_Lazy_Boy = 44 +ind_Lazy_Darwin = 45 +ind_Auto_Defense = 46 +ind_Spy_Hard = 47 +last_defensive = ind_Spy_Hard +last_real_defensive = ind_Bouncy_Castle +number_of_offensives = last_offensive - first_offensive +1 +number_of_defensives = (last_defensive - first_defensive +1) number_of_weapons = number_of_offensives + number_of_defensives ;-------------------------------- ; names of RMT instruments (sfx) @@ -180,9 +180,9 @@ sfx_liquid_dirt = $1b ;2 sfx_battery = $1c ;3 sfx_white_flag = $1d ;4 sfx_long_barrel = $1e -sfx_tank_move = $1f +sfx_tank_move = $1f sfx_auto_defense= $2b -sfx_lazy_boys = $2c +sfx_lazy_boys = $2c ;-------------------------------- ; RMT songs (lines) ;-------------------------------- diff --git a/game.asm b/game.asm new file mode 100644 index 0000000..cb061ee --- /dev/null +++ b/game.asm @@ -0,0 +1,1392 @@ +.IF *>0 ;this is a trick that prevents compiling this file alone + +; All main procedures of the game not dependent on hardware (I hope) :) + +START + jsr MakeDarkScreen + ; Startup sequence + jsr Initialize + + ;jsr GameOverScreen ; only for test !!! + + RMTSong song_main_menu + + jsr Options ;startup screen + jsr SetVariablesFromOptions + jsr MakeDarkScreen + bit escFlag + bmi START + + jsr EnterPlayerNames + jsr MakeDarkScreen + bit escFlag + bmi START + + jsr RandomizeSequence + ; for the round #1 shooting sequence is random + +MainGameLoop + jsr SetWallsType + ; first set default barrel lengths (fix for Long Schlong activation :) ) + ; we must do it before purchase/activate + ; and set Auto Defense to off + jsr SetStandardBarrels + + jsr CallPurchaseForEveryTank + jsr MakeDarkScreen + bit escFlag + bmi START + + jsr GetRandomWind + + jsr RoundInit + + jsr MainRoundLoop + bit escFlag + jvs GoGameOver + bmi START + + jsr CalculateGains + + jsr SortSequence + + mva #0 TankNr ; + sta COLBAKS ; set background color to black + sta JoystickNumber ; set joystick port for player + + ; Hide all (easier than hide last ;) ) tanks + jsr cleartanks ; A=0 + + ; here gains and losses should be displayed (dollars) + ; finally we have changed our minds and money of players + ; is displayed only in weapons shop + + ; Results are number of other deaths + ; before the player dies itself + + RmtSong song_round_over + jsr DisplayResults + + jsr DemoModeOrKey + jsr MakeDarkScreen + + lda GameIsOver + beq NoGameOverYet +GoGameOver + jsr GameOverScreen + jmp START +NoGameOverYet + inc CurrentRoundNr + mva #sfx_silencer sfx_effect + + jmp MainGameLoop + +;-------------------------------------------------- +.proc CalculateGains +;-------------------------------------------------- + ; add gains and substract losses + ; gain is what player gets for lost energy of opponents + ; energy lost by opponents is added during Round and + ; little below in source, multiplied by 2 to get "dollars". + ; By analogy, loss is energy that given player losses during + ; each Round. + ; Important! If player has 10 energy and gets a central hit + ; from nuke that would take 90 energy points, his loss + ; is 90, not 10 + ldx NumberOfPlayers + dex +CalculateGainsLoop + + ; adding the remaining energy of the tank to gain + ; winner gets more ! :) + lda Energy,x + adc gainL,x + sta gainL,x + bcc @+ + inc gainH,x +@ + ; add gain * 2 + asl gainL,x + rol gainH,x + clc + lda moneyL,x + adc gainL,x + sta moneyL,x + lda moneyH,x + adc gainH,x + sta moneyH,x + ; substract lose + ; if lose is greater than money then zero money + lda moneyH,x + cmp loseH,x + bcc zeromoney + bne substractlose + lda moneyL,x + cmp loseL,x + bcc zeromoney +substractlose + sec + lda moneyL,x + sbc loseL,x + sta moneyL,x + lda moneyH,x + sbc loseH,x + sta moneyH,x + jmp skipzeroing +zeromoney + lda #0 + sta moneyL,x + sta moneyH,x +skipzeroing +; and earned money for summary + clc + lda EarnedMoneyL,x + adc gainL,x + sta EarnedMoneyL,x + lda EarnedMoneyH,x + adc gainH,x + sta EarnedMoneyH,x + ; substract lose + ; if lose is greater than money then zero money + lda EarnedMoneyH,x + cmp loseH,x + bcc ezeromoney + bne esubstractlose + lda EarnedMoneyL,x + cmp loseL,x + bcc ezeromoney +esubstractlose + sec + lda EarnedMoneyL,x + sbc loseL,x + sta EarnedMoneyL,x + lda EarnedMoneyH,x + sbc loseH,x + sta EarnedMoneyH,x + jmp eskipzeroing +ezeromoney + lda #0 + sta EarnedMoneyL,x + sta EarnedMoneyH,x +eskipzeroing + + dex + jpl CalculateGainsLoop + rts +.endp +;-------------------------------------------------- +.proc RoundInit +;-------------------------------------------------- +; at the beginning of each Round we set energy +; of all players to 99 +; the maximum shooting energy to 990 (it is 10*energy) +; the default shooting energy to 350 +; the shooting angle is randomized +; of course gains an loses are zeroed + + RmtSong song_ingame + + jsr SetPMWidth ; A=0 + lda #0 + sta AfterBFGflag ; reset BFG flag + sta COLOR2 ; status line "off" + sta COLOR1 + + tax +@ sta singleRoundVars,x + inx + cpx #(singleRoundVarsEnd-singleRoundVars) + bne @- + + ldx #(MaxPlayers-1) +SettingEnergies + lda #$00 + sta gainL,x + sta gainH,x + sta loseL,x + sta loseH,x + lda #99 + sta Energy,x + sta eXistenZ,x + sta LASTeXistenZ,x + ; anything in eXistenZ table means that this tank exist + ; in the given round + lda #<1000 + sta MaxForceTableL,x + lda #>1000 + sta MaxForceTableH,x + lda #<350 + sta ForceTableL,x + lda #>350 + sta ForceTableH,x + + ;lda #(255-45) + ;it does not look good when all tanks have + ;barrels pointing the same direction + ;so it would be nice to have more or less random + ;angles + jsr RandomizeAngle + sta AngleTable,x + + dex + bpl SettingEnergies + +;generating the new landscape + jsr PMoutofScreen ;let P/M disappear + jsr clearscreen ;let the screen be clean + jsr ClearPMmemory + jsr placetanks ;let the tanks be evenly placed + jsr calculatemountains ;let mountains be easy for the eye + ;jsr calculatemountains0 ;only for tests - makes mountains flat and 0 height + + + mwa #StatusBufferROM temp + mwa #StatusBufferCopy temp2 + mwa #StatusBufferCopyEnd+1 modify + jsr CopyFromROM + + jsr SetMainScreen + jsr ColorsOfSprites + + jsr drawmountains ;draw them + jsr drawtanks ;finally draw tanks + + mva #$00 TankSequencePointer + +;---------round screen is ready--------- + mva #TextForegroundColor COLOR1 ; status line "on" + rts +.endp + +;-------------------------------------------------- +.proc MainRoundLoop +; here we must check if by a chance there is only one +; tank with energy greater than 0 left +;-------------------------------------------------- + + ldy #0 ; in Y - number of tanks with energy greater than zero + sty ATRACT ; reset atract mode + ldx NumberOfPlayers + dex +CheckingIfRoundIsFinished + lda eXistenZ,x + beq NoEnergy + iny +NoEnergy + dex + bpl CheckingIfRoundIsFinished + + cpy #2 ; is it less than 2 tanks have energy >0 ? + bcs DoNotFinishTheRound + +;points for the last living tank + ldx NumberOfPlayers + dex +WhichTankWonLoop + lda eXistenZ,x + bne ThisOneWon + dex + bpl WhichTankWonLoop + ;error was here!!! + ; somehow I believed program will be never here + ; but it was a bad assumption + ; god knows when there is such a situation + ; (we've got a SITUATION here, if you know what I mean) + ; there are two tanks left. + ; one of them is killed by the second tank + ; second tank explodes and kills the first one. + ; and code lands here... + ; looks like no one won! + rts + +ThisOneWon + lda CurrentResult + clc + adc ResultsTable,x + sta ResultsTable,x + + rts ; this Round is finished + +DoNotFinishTheRound + ; Seppuku here + lda noDeathCounter + cmp seppukuVal + bcc @+ + + mva #0 noDeathCounter + mva #sfx_seppuku sfx_effect + + jsr DisplaySeppuku + jmp Seppuku + +@ + ; Auto Defense - activates defensives + ldx NumberOfPlayers + dex +CheckNextTankAD + lda Energy,x ; only active players + beq @+ + lda AutoDefenseFlag,x ; with Auto Defence activated + beq @+ + ; run auto defense for tank in X + jsr AutoDefense +@ dex + bpl CheckNextTankAD + jsr DrawTanks ; redraw tanks with new defences +; + ldx TankSequencePointer + lda TankSequence,x + sta TankNr + tax + lda Energy,x ;skip if no energy + jeq NextPlayerShoots + + + + mva #$ff plot4x4color + jsr DisplayTankNameAbove + + mva #1 color ;to display flying point + + ldx tankNr + lda TankStatusColoursTable,x + sta COLOR2 ; set color of status line + jsr PutTankNameOnScreen +; jsr DisplayStatus ; There is no need anymore, it is always after PutTankNameOnScreen + + lda SkillTable,x + beq ManualShooting + +RoboTanks + ; robotanks shoot here + ; TankNr still in X + jsr ArtificialIntelligence + ;pause 30 + ldx TankNr + jsr DisplayStatus ; to make visible AI selected defensive (and offensive :) ) + jsr MoveBarrelToNewPosition + lda kbcode + cmp #@kbcode._esc ; 28 ; ESC + bne @+ + jsr AreYouSure +@ bit escFlag + spl:rts ; keys Esc or O + + + jmp AfterManualShooting + +ManualShooting + lda JoyNumber,x + sta JoystickNumber ; set joystick port for player + jsr WaitForKeyRelease + lda #%00000000 + sta TestFlightFlag ; set "Test Fight" off + jsr BeforeFire + bit escFlag + spl:rts ; keys Esc or O + +AfterManualShooting + mva #$00 plot4x4color + jsr DisplayTankNameAbove + ; defensive weapons without flight handling + ldx TankNr + lda ActiveDefenceWeapon,x + cmp #ind_Hovercraft + beq GoFloat + cmp #ind_White_Flag ; White Flag + beq ShootWhiteFlag + cmp #ind_Nuclear_Winter_ + bne StandardShoot +ShootAtomicWinter + ; --- atomic winter --- + jsr AtomicWinter + jmp NextPlayerShoots ; and we skip shoot +ShootWhiteFlag + ; --- white flag --- + jsr WhiteFlag + jsr TankFlying.SoilDownAfterLanding ; Soildown like after Hovercraf landing :) + jmp NextPlayerShoots ; and we skip shoot +GoFloat + jsr TankFlying + lda #0 + sta ActiveDefenceWeapon,x ; deactivate after use + bit escFlag + bpl ManualShooting ; after floating tank can shoot + rts +StandardShoot + inc noDeathCounter + + jsr DecreaseWeaponBeforeShoot + jsr DisplayStatus + +; ldx TankNr + dec Energy,x ; lower energy to eventually let tanks commit suicide + +ShootNow + jsr Shoot + ;here we clear offensive text (after a shoot) + ldy TankNr + mva #$00 plot4x4color + jsr DisplayOffensiveTextNr + + bit escFlag + spl:rts ; keys Esc or O + + lda HitFlag ;0 if missed + beq missed + + jsr Explosion + +continueMainRoundLoopAfterSeppuku + +AfterExplode + jsr SoilDown2 ; allways +NoFallDown2 + ;here tanks are falling down + mva tankNr tempor2 + ldx NumberOfPlayers + dex +TanksFallDown + stx TankNr + lda eXistenZ,x + beq NoExistNoFall + jsr TankFalls +NoExistNoFall + dex + bpl TanksFallDown + mvx tempor2 TankNr + +missed + ldy WeaponDepleted + bne @+ + ldx TankNr + tya + sta ActiveWeapon,x +@ + + ;here we clear offensive text (after a shoot) + ldy TankNr + mva #$00 plot4x4color + jsr DisplayOffensiveTextNr + +NextPlayerShoots + ;before it shoots, the eXistenZ table must be updated + ;accordingly to actual energy (was forgotten, sorry to ourselves) + + ldx #(MaxPlayers-1) +SeteXistenZ + lda Energy,x + sta eXistenZ,x + + jsr MaxForceCalculate + + dex + bpl SeteXistenZ + + ;was setup of maximum energy for players + + +PlayersAgain + +; In LASTeXistenZ there are values of eXistenZ before shoot +; from the next tank. +; Now it must be checked if by a chance something that had +; LASTeXistenZ>0 is not equal to 0 right now, +; because it means this tank died during this round. +; Most important thing is: +; after each explosion of the tank these operations must be +; performed from the beginning! +; (it is made by another jump into the after explosion routines) +; It is because exploding tank can destroy their neighbours, +; additionally this tank just have had LASTeXistenZ set to 0, +; otherwise it would explode again and again. +; OK, text how to do it is ready, now comes coding . +; Aaaah! - in the main loop we have to set eXistenZ and LASTeXistenZ + + mva #sfx_next_player sfx_effect + + ldx NumberOfPlayers + dex +CheckingPlayersDeath + lda LASTeXistenZ,x + beq NoPlayerNoDeath + lda eXistenZ,x + beq PlayerXdeath +NoPlayerNoDeath + dex + bpl CheckingPlayersDeath + ; if processor is here it means there are no more explosions + + inc:lda TankSequencePointer + cmp NumberOfPlayers + bne NotLastPlayerInRound + mva #0 TankSequencePointer + + lda WindChangeInRound + beq NoWindChangeNow + jsr GetRandomWind ; wind change after each turn (not round only) +NoWindChangeNow +NotLastPlayerInRound + jmp MainRoundLoop +.endp + +;--------------------------------- +.proc PlayerXdeath +; this tank should not explode anymore: +; there is 0 in A, and Tank Number in X, so... +;--------------------------------- + + sta LASTeXistenZ,x + ; save x somewhere + stx TankTempY + + ;clear NoDeathCounter here + sta noDeathCounter + + mva #sfx_death_begin sfx_effect + + ; display defensive text here (well, defensive + ; is not the real meaning, it should be pre-death, + ; but I am too lazy to change names of variables) + + ; in X there is a number of tank that died + + lda #78 ; mumber of defensive text after BFG! ("VERY FUNNY.") + bit AfterBFGflag ; check BFG flag + bmi TextAfterBFG + ; if BFG then no points for dead tanks ... + lda CurrentResult + clc + adc ResultsTable,x + sta ResultsTable,x + ;inc CurrentResult + + ; RandomizeDeffensiveText + randomize talk.NumberOfOffensiveTexts (talk.NumberOfDeffensiveTexts+talk.NumberOfOffensiveTexts-1) +TextAfterBFG + sta TextNumberOff + inc CurrentResult ; ... but increase result of winner (BFG) + ldy TankTempY + mva #$ff plot4x4color + jsr DisplayOffensiveTextNr + ; tank flash + ldy TankTempY + mva TankNr temp2 ; not elegant, and probably unnecessary + sty TankNr + jsr FlashTank ; blinking and pausing (like PAUSE 72 - 18x(2+2) ) + mva temp2 TankNr + + ;Deffensive text cleanup + ;here we clear Deffensive text (after a shoot) + ldy TankTempY + mva #$00 plot4x4color + jsr DisplayOffensiveTextNr + + ; calculate position of the explosion (the post-death one) + ldx TankTempY + clc + lda xtankstableL,x + adc #4 ; more or less in the middle of the tank + sta xdraw + lda xtankstableH,x + adc #0 + sta xdraw+1 + sec + lda ytankstable,x + sbc #4 + sta ydraw + lda #0 + sta ydraw+1 ; there is 0 left in A, so... TODO: bad code above. revisit + + ;cleanup of the soil fall down ranges (left and right) + sta RangeRight + sta RangeRight+1 + mwa #screenwidth RangeLeft + + ; We are randomizing the weapon now. + ; jumping into the middle of the explosion + ; routine +MetodOfDeath + lda random + and #%00011111 ; range 0-31 + cmp #(weaponsOfDeathEnd-weaponsOfDeath) ; we have 20 weapons in table (from 0 to 19) + bcs MetodOfDeath + tay + lda weaponsOfDeath,y + jsr ExplosionDirect + mva #sfx_silencer sfx_effect + + ; Clear current Shooter settings. After that, Shooter will "search" for the target again + ldx NumberOfPlayers + dex +@ lda skillTable,x + cmp #2 ; clear variables only if Shooter + bne NotShooter + lda #0 + sta PreviousAngle,x + sta PreviousEnergyL,x + sta PreviousEnergyH,x +NotShooter + dex + bpl @- + + ; jump to after explosion routines (soil fallout, etc.) + ; After going through these routines we are back + ; to checking if a tank exploded and maybe we have + ; a deadly shot here again. + jmp MainRoundLoop.AfterExplode +.endp + +;-------------------------------------------------- +.proc DecreaseEnergyX +;Decreases energy of player nr X by the value Y +;increases his financial loss +;increases gain of tank TankNr +;-------------------------------------------------- + sty EnergyDecrease + ; Lose increase + lda loseL,x + clc + adc EnergyDecrease + sta loseL,x + lda loseH,x + adc #$00 + sta loseH,x + ; Energy now, not less than 0 + lda Energy,x + cmp EnergyDecrease + bcc ldahashzero + ;sec + sbc EnergyDecrease + bpl NotNegativeEnergy +ldahashzero + lda #0 +NotNegativeEnergy + sta Energy,x + ;now increase the gain of the shooting tank + ldy TankNr + clc + lda gainL,y + adc EnergyDecrease + sta gainL,y + lda gainH,y + adc #$00 + sta gainH,y + rts +.endp + +;-------------------------------------------------- +.proc DecreaseShieldEnergyX +; Decreases energy of shield player nr X by the value Y +; if shield energy is 0 after decrease then in Y we have +; rest of the energy - to decrease tank energy +;-------------------------------------------------- + sty EnergyDecrease + ldy #0 ; if Shield survive then no decrease tank anergy + ; Energy cannot be less than 0 + lda ShieldEnergy,x + cmp EnergyDecrease + bcc UseAllShieldEnergy + ;sec + sbc EnergyDecrease + bpl NotNegativeShieldEnergy ; jump allways +UseAllShieldEnergy + ; now calculate rest of energy for future tank energy decrease + sec + lda EnergyDecrease + sbc ShieldEnergy,x + tay + lda #0 +NotNegativeShieldEnergy + sta ShieldEnergy,x + rts +.endp + +;--------------------------------- +.proc Seppuku +;--------------------------------- + lda #0 + sta ydraw+1 + ; get position of the tank + ldx TankNr +; lda #0 ; turn off defense weapons when hara-kiring + sta ActiveDefenceWeapon,x + sta ShieldEnergy,x + jsr SetupXYdraw + lda #1 ; Missile + jsr ExplosionDirect + jmp MainRoundLoop.continueMainRoundLoopAfterSeppuku +.endp + +;-------------------------------------------------- +.proc GetRandomWind +;in: MaxWind (byte) +;out: Wind (word) +;uses: _ +;-------------------------------------------------- + lda random + cmp MaxWind + bcs GetRandomWind ; if more than MaxWind then randomize again + sta Wind + mva #$00 Wind+1 + sta Wind+2 + sta Wind+3 + ; multiply Wind by 16 + ; two bytes of Wind are treated as a decimal part of vx variable + :4 aslw Wind + ; decide the direction + lda random + and #$01 + beq @+ + sec ; Wind = -Wind + .rept 4 + lda #$00 + sbc Wind+# + sta Wind+# + .endr +@ rts +.endp +;-------------------------------------------------- +.proc MaxForceCalculate +; calculates max force for tank (tanknr in X) +; Energy of tank X in A +;-------------------------------------------------- + sta L1 + + ;DATA L1,L2 + ;Multiplication 8bit*8bit, + ;result 16bit + ;this algiorithm is a little longer than one in Ruszczyc 6502 book + ;but it is faster + + ldy #8 + lda #0 + clc +LP0 ror + ror L1 + bcc B0 + clc + adc #10 ; (L2) multiplication by 10 +B0 dey + bne LP0 + ror + ror L1 + sta MaxForceTableH,x + lda L1 + sta MaxForceTableL,x + rts +.endp + +;-------------------------------------------------- +.proc WeaponCleanup +; cleaning of the weapon possesion tables +; 99 of Baby Missles and White Flags, all other weapons=0) +;-------------------------------------------------- + ldx #(number_of_weapons - 1) +@ lda #$0 + cpx #ind_White_Flag ; White Flag + bne no99 +set99 lda #99 +no99 + .REPT MaxPlayers, #+1 + sta TanksWeapon:1,x + .ENDR + dex + beq set99 ; Baby Missile (index=0) + bpl @- + rts +.endp + +;-------------------------------------------------- +.proc Initialize +;Initialization sequence +;uses: temp, ... +;-------------------------------------------------- +deletePtr = temp + + ; clean variables + lda #0 + sta escFlag + sta JoystickNumber + tay + mwa #variablesStart deletePtr +@ tya + sta (deletePtr),y + inw deletePtr + cpw deletePtr #variablesEnd + bne @- + + ; ser initial shapes for each tank (tanks 0-5 has shape 0 now) + ldy #1 + sty TankShape+1 + sty TankShape+4 + iny + sty TankShape+2 + sty TankShape+5 + + + mwa #1024 RandBoundaryHigh + mva #$ff LastWeapon + sta HowMuchToFall + mva #1 color + + jsr SetStandardBarrels + jsr WeaponCleanup + + mva #>WeaponFont chbas + + ;parameter for old plot (unPlot) max 5 points + ldx #4 +SetunPlots + lda #display + sta oldplotH,x + lda #0 + sta oldply,x + lda #$ff + sta oldora,x + dex + bpl SetunPlots + + ;setting up P/M graphics + lda #>pmgraph + sta pmbase + lda #$03 ; P/M on + sta GRACTL + jsr SetPMWidth + lda #%00100001 ; P/M priorities (multicolor players on) - prior=1 + sta GPRIOR + jsr PMoutofScreen + + ;let the tanks be visible! + ldx #(maxPlayers-1) + lda #99 ; tank is visible +MakeTanksVisible + sta eXistenZ,x + dex + bpl MakeTanksVisible + + mva #1 CurrentRoundNr ;we start from round 1 + mva #6 NTSCcounter + + rts +.endp +;-------------------------------------------------- +.proc SetStandardBarrels +; set standart barrel length and deactivate Auto Defense +; for all tanks +;-------------------------------------------------- + ldx #maxPlayers-1 +@ lda #StandardBarrel ; standard barrel length + sta BarrelLength,x + lda #$00 ; deactivate Auto Defense + sta AutoDefenseFlag,x + dex + bpl @- + rts +.endp +;---------------------------------------------- +/* .proc RandomizeSequence0 + ldx #0 +@ txa + sta TankSequence,x + inx + cpx #MaxPlayers + bne @- + rts +.endp */ +;-------------------------------------------------- +.proc RandomizeSequence +; in: NumberOfPlayers +; out: TankSequence +; how: get random number lower than NumberOfPlayers +; put it in the first slot. +; get another random number lower than NumberOfPlayers +; check if was previously saved in first slot +; if not then save it in second slot +; repeat untill NumberOfPlayers + + ldx #0 +GetRandomAgain0 + lda RANDOM + and #$07 ;NumberOfPlayers < 7 + cmp NumberOfPlayers + bcs GetRandomAgain0 + sta TankSequence,x + ;now first slot is ready, nexts slots are handled + ;in a more complicated way + +GetRandomAgainX + lda RANDOM + and #$07 ;NumberOfPlayers < 7 + cmp NumberOfPlayers + bcs GetRandomAgainX + + ;now we have to check if the value was not used + ;in previous slots + + stx temp + ldy temp +UsageLoop + cmp TankSequence,y + beq GetRandomAgainX ;apparently we have already used this value + dey + bpl UsageLoop + + ;well, looks like this value is new! + inx + sta TankSequence,x + + stx temp + inc:lda temp ;x+1 + + cmp NumberOfPlayers + bne GetRandomAgainX + rts +.endp +;---------------------------------------------- +.proc RandomizeAngle +; routine returns in A +; a valid angle for the tank's barrel. +; X is not changed +;---------------------------------------------- + + ; lets randomize someting between 0 and 180 + lda RANDOM + cmp #180 + bcs RandomizeAngle + rts +.endp +;---------------------------------------------- +.proc RandomizeForce +; routine returns in ForceTable/L/H +; valid force of shooting for TankNr +; in X must be TankNr +; low and high randomize boundary passed as word value +; RandBoundaryLow +; RandBoundaryHigh +;---------------------------------------------- + + lda RANDOM + sta temp2 + lda RANDOM + and #%00000011 ;(0..1023) + sta temp2+1 + + cpw RandBoundaryLow temp2 + seq:bcs RandomizeForce + + cpw RandBoundaryHigh temp2 + bcc RandomizeForce + + lda temp2 + sta ForceTableL,x + lda temp2+1 + sta ForceTableH,x + +;--------- +LimitForce +; in X must be TankNr +; cuts force to MaxForceTable + lda MaxForceTableH,x + cmp ForceTableH,x + bne @+ + lda MaxForceTableL,x + cmp ForceTableL,x +@ bcs @+ + + lda MaxForceTableL,x + sta ForceTableL,x + lda MaxForceTableH,x + sta ForceTableH,x +@ + rts + +.endp +;---------------------------------------------- +.proc Table2Force +;---------------------------------------------- + lda ForceTableL,x + sta Force + lda ForceTableH,x + sta Force+1 + rts +.endp +;---------------------------------------------- +.proc MoveBarrelToNewPosition +;---------------------------------------------- + mva #1 Erase + jsr DrawTankNr.BarrelChange + mva #0 Erase +MoveBarrel + mva #sfx_set_power_2 sfx_effect + jsr DrawTankNr + jsr DisplayStatus.displayAngle + ; + jsr CheckExitKeys + spl:rts ;---Exit key pressed-quit game--- + ldx TankNr + ; + mva #1 Erase + jsr WaitOneFrame + jsr DrawTankNr.BarrelChange + mva #0 Erase + lda NewAngle + cmp AngleTable,x + beq BarrelPositionIsFine + bcc rotateLeft +rotateRight ; older is lower + inc angleTable,x + jmp MoveBarrel +rotateLeft ; older is bigger + dec angleTable,x + jmp MoveBarrel +BarrelPositionIsFine + jmp DrawTankNr + ; rts + +.endp + +;---------------------------------------------- +.proc SortSequence ; +;---------------------------------------------- +; here we try to get a sequence of tanks for two +; purposes: +; 1. to make up shooting sequence for the next round (from down to top) +; 2. to display game results more nicely (from top to down) +; +; I think I will go for a stupid bubble sort... +; it is easy to test :) +; +; Results are in ResultsTable, in TankSequence (Sorted Table) we want to +; have numbers of tanks from the worst to the best. +; in other words, if ResultsTable=(5,4,65,23,3,6) +; the TankSequence=(4,1,0,5,3,2) +; let's assume initially the TankSequence=(0,1,2,3,4,5) + + ldx #0 +SequenceStart + txa + sta TankSequence,x + inx + cpx #MaxPlayers + bne SequenceStart + +; i=0:sortflag=0 +;loop: +; if TR(i) < TX(i+1) then i=i+1: here quit if i=numberofplayers +; or goto loop: +; else +; temp=TR(i): tempo=TankSequence(i) +; TR(i)=TR(i+1): TankSequence(i)=TankSequence(i+1) +; TR(i+1)=temp: TankSequence(i+1)=tempo +; i=i+1 +; sortflag=sortflag+1 +; go loop: +; if sortflag=0 then finished, else repeat... +; +; or something like this :) + +Bubble + ldx #0 ;i=x + stx temp2 ; sortflag=temp2 + inx ; because NumberOfPlayers start from 1 (not 0) + +BubbleBobble + ldy TankSequence-1,x ; x count from 1 to NumberOfPlayers (we need cout from 0 to NumberOfPlayers-1) + lda ResultsTable,y + ldy TankSequence,x + cmp ResultsTable,y + bcc nextishigher + bne swapvalues +nextisequal + ; if results are equal, check Direct Hits + ldy TankSequence-1,x + lda DirectHits,y + ldy TankSequence,x + cmp DirectHits,y + bcc nextishigher + bne swapvalues +nextisequal2 + ; if results are equal, check money (H) + ldy TankSequence-1,x + lda EarnedMoneyH,y + ldy TankSequence,x + cmp EarnedMoneyH,y + bcc nextishigher + bne swapvalues +nextisequal2b + ; if results are equal, check money (L) + ldy TankSequence-1,x + lda EarnedMoneyL,y + ldy TankSequence,x + cmp EarnedMoneyL,y + ; + beq nextishigher ; this is to block hangs when 2 equal values meet + bcc nextishigher + ;here we must swap values + ;because next is smaller than previous +swapvalues + lda TankSequence-1,x + sta temp + lda TankSequence,x + sta TankSequence-1,x + lda temp + sta TankSequence,x + inc temp2 +nextishigher + inx + cpx NumberOfPlayers + bne BubbleBobble + + lda temp2 + + bne Bubble + + rts +.endp +;-------------------------------------------------- +.proc SetWallsType +;-------------------------------------------------- + mva #0 WallsType + lda OptionsTable+8 + cmp #4 + beq SetRandomWalls + lsr + ror WallsType + lsr + ror WallsType + rts +SetRandomWalls + lda random + and #%11000000 + sta WallsType + rts +.endp +; -------------------------------------- +; Sets the appropriate variables based on the options table +; +.proc SetVariablesFromOptions + ;first option + ldy OptionsTable + iny + iny + sty NumberOfPlayers ;1=1 player (but minimum is 2) + + ;second option (cash) + + ldy OptionsTable+1 + ldx #0 +@ + lda CashOptionL,y + sta moneyL,x + lda CashOptionH,y + sta moneyH,x + inx + cpx NumberOfPlayers + bne @- + + ;third option (gravity) + ldy OptionsTable+2 + lda GravityTable,y + sta gravity + + ;fourth option (wind) + ldy OptionsTable+3 + lda MaxWindTable,y + sta MaxWind + + ;fifth option (no of rounds) + ldy OptionsTable+4 + lda RoundsTable,y + sta RoundsInTheGame + + ;6th option (shell speed) + ldy OptionsTable+5 + lda flyDelayTable,y + sta flyDelay + + ;7th option (Airstrike after how many missess) + ldy OptionsTable+6 + lda seppukuTable,y + sta seppukuVal + + ;8th option (how aggressive are mountains) + ldy OptionsTable+7 + lda mountainsDeltaTableH,y + sta mountainDeltaH + lda mountainsDeltaTableL,y + sta mountainDeltaL + + rts +.endp + +;-------------------------------- +.proc DisplayResults ; +;displays results of the round +;using 4x4 font + jsr RoundOverSprites + + + mva #$ff plot4x4color + + ;centering the result screen + mva #((ScreenHeight/2)-(8*4)) ResultY + + + ;upper frame + mva ResultY LineYdraw + jsr TL4x4_top + + adb ResultY #4 ;next line + + ;Header1 + ;Displays round number + lda CurrentRoundNr + cmp RoundsInTheGame + beq GameOver4x4 + + sta decimal + mwa #RoundNrDisplay displayposition + jsr displaybyte ;decimal (byte), displayposition (word) + + mwa #LineHeader1 LineAddress4x4 + mwa #((ScreenWidth/2)-(8*4)) LineXdraw + mva ResultY LineYdraw + jsr TypeLine4x4 + beq @+ ;unconditional jump, because TypeLine4x4 ends with beq + +GameOver4x4 + RmtSong song_round_over + mwa #LineGameOver LineAddress4x4 + mwa #((ScreenWidth/2)-(8*4)) LineXdraw + mva ResultY LineYdraw + jsr TypeLine4x4 + mva #1 GameIsOver + +@ + adb ResultY #4 ;next line + + ;Empty line + mva ResultY LineYdraw + jsr TL4x4_empty + + adb ResultY #2 ;next line + + + ;Header2 + mwa #LineHeader2 LineAddress4x4 + mwa #((ScreenWidth/2)-(8*4)) LineXdraw + mva ResultY LineYdraw + jsr TypeLine4x4 + + adb ResultY #4 ;next line + + ;Empty line + mva ResultY LineYdraw + jsr TL4x4_empty + + sbb ResultY #2 ;next line (was empty) + + ldx NumberOfPlayers ;we start from the highest (best) tank + dex ;and it is the last one + stx ResultOfTankNr ;in TankSequence table + + mwa #TanksNames tempXROLLER + +ResultOfTheNextPlayer + ldx ResultOfTankNr ;we are after a round, so we can use TankNr + lda TankSequence,x ;and we keep here real number if the tank + sta TankNr ;for which we are displaying results + + + + + adb ResultY #4 ;next line + + ;there are at least 2 players, so we can safely + ;start displaying the result + + lda #3 ;it means | + sta ResultLineBuffer + + ldy TankNr + lda ResultsTable,y + sta decimal + mva #0 decimal+1 + mwa #(ResultLineBuffer+8) displayposition + jsr displaydec5 ;decimal (byte), displayposition (word) + + ; overwrite the second digit of the points (max 255) + ;it means ":" + mva #26 ResultLineBuffer+9 + + ldx #0 + lda TankNr + asl + asl ; times 8, because it is lengtgh + asl ; of the names of the tanks + tay + +TankNameCopyLoop + lda (tempXROLLER),y ;XROLLER is not working now + and #$3f ;always CAPITAL letters + inx + sta ResultLineBuffer,x + iny + cpx #8 ; end of name + bne TankNameCopyLoop + ; last letter of tank name overwrites first digit of the points (max 255) + + + ;just after the digits + ;it means | + mva #$3 ResultLineBuffer+13 + + ;result line display + mwa #ResultLineBuffer LineAddress4x4 + mwa #((ScreenWidth/2)-(8*4)) LineXdraw + mva ResultY LineYdraw + jsr TypeLine4x4 + + adb ResultY #4 ;next line + + ;Empty line + mva ResultY LineYdraw + jsr TL4x4_empty + + dec ResultOfTankNr + bmi FinishResultDisplay + + sbb ResultY #2 ;distance between lines is smaller + + jmp ResultOfTheNextPlayer + +FinishResultDisplay + mva ResultY LineYdraw + ;jmp TL4x4_bottom ; just go +.endp + +.proc TL4x4_bottom + ;bottom of the frame + mwa #LineBottom LineAddress4x4 + mwa #((ScreenWidth/2)-(8*4)) LineXdraw + jmp TypeLine4x4 ; jsr:rts +.endp + +.proc TL4x4_top + ;bottom of the frame + mwa #LineTop LineAddress4x4 + mwa #((ScreenWidth/2)-(8*4)) LineXdraw + jmp TypeLine4x4 ; jsr:rts +.endp + +.proc TL4x4_empty + ;empty frame + mwa #LineEmpty LineAddress4x4 + mwa #((ScreenWidth/2)-(8*4)) LineXdraw + jmp TypeLine4x4 ; jsr:rts +.endp + +.ENDIF \ No newline at end of file diff --git a/grafproc.asm b/grafproc.asm index a3fe794..ae1b631 100644 --- a/grafproc.asm +++ b/grafproc.asm @@ -1,10 +1,10 @@ -; @com.wudsn.ide.asm.mainsourcefile=scorch.asm +; @com.wudsn.ide.asm.mainsourcefile=scorch.asm .IF *>0 ;this is a trick that prevents compiling this file alone ;-------------------------------------------------- -.proc draw ;;fuxxing good draw :) +.proc draw ;;fuxxing good draw :) ; xdraw,ydraw (word) - coordinates of first point ; xbyte,ybyte (word) - coordinates of last point ;-------------------------------------------------- @@ -142,10 +142,10 @@ LineParametersReady ora DX+1 ora DY ora DY+1 - bne NotOnePoint - ; length=0 - sta LineLength - sta LineLength+1 + bne NotOnePoint + ; length=0 + sta LineLength + sta LineLength+1 jmp EndOfDraw NotOnePoint @@ -221,13 +221,13 @@ LineGoesLeft ; line goes left - we are reversing X sbw xtempDRAW temp xdraw ; XI PutPixelinDraw - + ; 0 - plot, %10000000 - LineLength (N), %01000000 - DrawCheck (V) bit drawFunction bpl @+ inw LineLength - bit Vdebug - bmi MeasureVisualisation + bit Vdebug + bmi MeasureVisualisation jmp ContinueDraw ; was `bne` - not good, because LineLength starts from $ffff @ bvc @+ @@ -239,7 +239,7 @@ yestrace jsr plot notrace ;aftertrace - ;key + ;key lda HitFlag bne StopHitChecking @@ -252,13 +252,13 @@ CheckCollisionDraw lda HitFlag bne StopHitChecking - clc - lda xdraw - adc #mountaintable - sta temp+1 + clc + lda xdraw + adc #mountaintable + sta temp+1 ldy #0 lda ydraw @@ -266,17 +266,17 @@ CheckCollisionDraw bcc StopHitChecking mwa xdraw XHit - lda (temp),y - sec - sbc #1 - sta YHit - sty YHit+1 + lda (temp),y + sec + sbc #1 + sta YHit + sty YHit+1 mva #$ff HitFlag StopHitChecking jmp ContinueDraw @ MeasureVisualisation - jsr plot + jsr plot ContinueDraw ; XI=XI+1 @@ -292,9 +292,9 @@ EndOfDraw .endp ;-------------------------------------------------- -.proc circle ;fxxxing good circle drawing :) +.proc circle ;fxxxing good circle drawing :) ; xdraw,ydraw (word) - coordinates of circle center -; radius (byte) - radius of circle +; radius (byte) - radius of circle ;-------------------------------------------------- ;Turbo Basic source ; R=30 @@ -398,19 +398,19 @@ endcircleloop adc YC sta ydraw sta tempcir - lda ycircle+1 - adc #$00 - sta ydraw+1 - sta tempcir+1 + lda ycircle+1 + adc #$00 + sta ydraw+1 + sta tempcir+1 jsr plot sec lda ycircle sbc YC sta ydraw - lda ycircle+1 - sbc #$00 - sta ydraw+1 + lda ycircle+1 + sbc #$00 + sta ydraw+1 jsr plot sec @@ -424,8 +424,8 @@ endcircleloop lda tempcir sta ydraw - lda tempcir+1 - sta ydraw+1 + lda tempcir+1 + sta ydraw+1 jsr plot ;--- clc @@ -440,19 +440,19 @@ endcircleloop adc xC sta ydraw sta tempcir - lda ycircle+1 - adc #$00 - sta ydraw+1 - sta tempcir+1 + lda ycircle+1 + adc #$00 + sta ydraw+1 + sta tempcir+1 jsr plot sec lda ycircle sbc xC sta ydraw - lda ycircle+1 - sbc #$00 - sta ydraw+1 + lda ycircle+1 + sbc #$00 + sta ydraw+1 jsr plot sec @@ -466,26 +466,13 @@ endcircleloop lda tempcir sta ydraw - lda tempcir+1 - sta ydraw+1 + lda tempcir+1 + sta ydraw+1 jsr plot RTS .endp -;-------------------------------------------------- -.proc ClearScreen -;-------------------------------------------------- - mwa #display temp - ldy #0 -@ lda #$ff - sta (temp),y - inw temp - cpw temp #display+screenheight*screenBytes+1 - bne @- - rts -.endp - ;-------------------------------*------------------ .proc placetanks ;-------------------------------------------------- @@ -496,10 +483,10 @@ endcircleloop ; it is necessary, because randomizing checks ; if the given tank is already placed ; after check if its position is not (0,0) - + ; I will be honest with you - I have no idea ; what the above comment was intending to mean :) - + sta XtankstableL,x sta XtankstableH,x sta Ytankstable,x @@ -508,7 +495,7 @@ endcircleloop mwa #0 temptankX - mva #0 temptankNr ;player number + sta temptankNr ;player number StillRandomize ldx NumberOfPlayers lda random @@ -555,15 +542,15 @@ NotHigherByte02 sec lda xtankstableL,x sbc #$0f - ; and clear lowest bit to be sure that the X coordinate is even - ; (this is to have P/M background look nice) - ; "AND" does not change "Carry" bit. - ; x correction for P/M - ; -- - .IF XCORRECTION_FOR_PM = 1 - and #$fe - .ENDIF - ; -- + ; and clear lowest bit to be sure that the X coordinate is even + ; (this is to have P/M background look nice) + ; "AND" does not change "Carry" bit. + ; x correction for P/M + ; -- + .IF XCORRECTION_FOR_PM = 1 + and #$fe + .ENDIF + ; -- sta xtankstableL,x bcs NotHigherByte01 dec xtankstableH,x @@ -601,8 +588,8 @@ UnequalTanks ;------------------------------------------------- .proc ClearTanks - jsr PMoutofScreen - mva #1 Erase ; erase tanks flag + jsr PMoutofScreen + mva #1 Erase ; erase tanks flag .endp ;-- .proc drawtanks @@ -622,10 +609,15 @@ DrawNextTank pla sta TankNr - mva #0 Erase ; no erase tanks flag + mva #0 Erase ; no erase tanks flag rts .endp ;--------- +ClearTankNr + mva #1 Erase + bne DrawTankNr +PutTankNr + mva #0 Erase .proc DrawTankNr ldx tankNr ; let's check the energy @@ -633,35 +625,35 @@ DrawNextTank bne SkipHidingPM ; if energy=0 then no tank ; hide P/M - lda TanksPMOrder,x - tax + lda TanksPMOrder,x + tax lda #0 cpx #$4 ; 5th tank is defferent bne No5thTankHide - sta hposp0+4 - sta hposp0+5 - beq @+ + sta hposp0+4 + sta hposp0+5 + beq @+ No5thTankHide - cpx #$5 ; 6th tank is defferent - bne No6thTankHide - sta hposp0+6 - sta hposp0+7 - beq @+ + cpx #$5 ; 6th tank is defferent + bne No6thTankHide + sta hposp0+6 + sta hposp0+7 + beq @+ No6thTankHide sta hposp0,x @ - ldx TankNr + ldx TankNr jmp DoNotDrawTankNr SkipHidingPM - lda TankShape,x - tax - ldy TankShapesTable,x - ldx TankNr + lda TankShape,x + tax + ldy TankShapesTable,x + ldx TankNr lda AngleTable,x - cmp #91 ; left or right tank shape - bcs LeftTank - :2 iny ; right tank + cmp #91 ; left or right tank shape + bcs LeftTank + :2 iny ; right tank LeftTank sty CharCode DrawTankNrX @@ -669,13 +661,13 @@ DrawTankNrX jsr SetupXYdraw jsr TypeChar - lda Erase - jne noTankNoPM + lda Erase + jne noTankNoPM ; now P/M graphics on the screen (only for 5 tanks) ; horizontal position ldx TankNr - lda TanksPMOrder,x - tax + lda TanksPMOrder,x + tax mwa xdraw xbyte rorw xbyte ; divide by 2 (carry does not matter) lda xbyte @@ -685,17 +677,17 @@ DrawTankNrX bne No5thTank clc adc #$04 ; missile offset offset - sta hposp0+4 - sta hposp0+5 - bne NoMissile + sta hposp0+4 + sta hposp0+5 + bne NoMissile No5thTank - cpx #$5 ; 6th tank are joined missiles and offset is defferent - bne Tanks1to4 + cpx #$5 ; 6th tank are joined missiles and offset is defferent + bne Tanks1to4 clc adc #$04 ; missile offset offset - sta hposp0+6 - sta hposp0+7 - bne NoMissile + sta hposp0+6 + sta hposp0+7 + bne NoMissile Tanks1to4 sta hposp0,x @@ -715,81 +707,81 @@ NoMissile cpx #$5 bcs PMForTank6 ; clear sprite and put 3 lines on the tank at the same time - ldx #3 ; three lines of PM -ClearPM + ldx #3 ; three lines of PM +ClearPM cpy temp bne ZeroesToGo -@ lda (xbyte),y - and #%11110000 +@ lda (xbyte),y + and #%11110000 ora #%00001111 ; (2 bits set) we set on two pixels in three lines sta (xbyte),y dey - dex - bne @- + dex + bne @- ZeroesToGo lda (xbyte),y - and #%11110000 + and #%11110000 sta (xbyte),y dey bne ClearPM - beq NoPlayerMissile + beq NoPlayerMissile PMForTank6 ; clear sprite and put 3 lines on the tank at the same time - ldx #3 ; three lines of PM -ClearPM6 + ldx #3 ; three lines of PM +ClearPM6 cpy temp bne ZeroesToGo6 -@ lda (xbyte),y - and #%00001111 +@ lda (xbyte),y + and #%00001111 ora #%11110000 ; (2 bits set) we set on two pixels in three lines sta (xbyte),y dey - dex - bne @- + dex + bne @- ZeroesToGo6 lda (xbyte),y - and #%00001111 + and #%00001111 sta (xbyte),y dey bne ClearPM6 NoPlayerMissile noTankNoPM - ldy #$01 - lda Erase - beq @+ - dey -@ sty color - ; draw defensive weapons like shield ( tank number in X ) - ; in xdraw, ydraw we have coordinates left LOWER corner of Tank char + ldy #$01 + lda Erase + beq @+ + dey +@ sty color + ; draw defensive weapons like shield ( tank number in X ) + ; in xdraw, ydraw we have coordinates left LOWER corner of Tank char ldx TankNr - lda ActiveDefenceWeapon,x - cmp #ind_Shield_________ ; one shot shield - beq DrawTankSh - cmp #ind_Force_Shield___ ; shield with energy and parachute - beq DrawTankShieldBold - cmp #ind_Heavy_Shield___ ; shield with energy - beq DrawTankShieldBold - cmp #ind_Bouncy_Castle__ ; Auto Defence - beq DrawTankShieldWihHorns - cmp #ind_Mag_Deflector__ ; Mag Deflector - beq DrawTankShieldWihHorns - cmp #ind_White_Flag_____ ; White Flag - beq DrawTankFlag - bne NoShieldDraw + lda ActiveDefenceWeapon,x + cmp #ind_Shield ; one shot shield + beq DrawTankSh + cmp #ind_Force_Shield ; shield with energy and parachute + beq DrawTankShieldBold + cmp #ind_Heavy_Shield ; shield with energy + beq DrawTankShieldBold + cmp #ind_Bouncy_Castle ; Auto Defence + beq DrawTankShieldWihHorns + cmp #ind_Mag_Deflector ; Mag Deflector + beq DrawTankShieldWihHorns + cmp #ind_White_Flag ; White Flag + beq DrawTankFlag + bne NoShieldDraw DrawTankSh - jsr DrawTankShield - jmp NoShieldDraw + jsr DrawTankShield + jmp NoShieldDraw DrawTankShieldWihHorns - jsr DrawTankShield - jsr DrawTankShieldHorns - jmp NoShieldDraw + jsr DrawTankShield + jsr DrawTankShieldHorns + jmp NoShieldDraw DrawTankShieldBold - jsr DrawTankShield - jsr DrawTankShieldBoldLine - jmp NoShieldDraw + jsr DrawTankShield + jsr DrawTankShieldBoldLine + jmp NoShieldDraw DrawTankFlag - lda #char_flag____________ ; flag symbol + lda #char_flag ; flag symbol sta CharCode lda Ytankstable,x sec @@ -798,41 +790,41 @@ DrawTankFlag jsr TypeChar NoShieldDraw BarrelChange - ldy #$01 - lda Erase - beq @+ - dey -@ sty color - jsr DrawBarrel - ldx TankNr + ldy #$01 + lda Erase + beq @+ + dey +@ sty color + jsr DrawBarrel + ldx TankNr DoNotDrawTankNr - rts + rts .endp ; ------------------------------------- .proc FlashTank ; ------------------------------------- ; number of blinking tank in TankNr - mva #18 fs ; temp, how many times flash the tank + mva #18 fs ; temp, how many times flash the tank tankflash_loop lda CONSOL ; turbo mode - and #%00000001 ; START KEY - sne:mva #1 fs ; finish it + and #%00000001 ; START KEY + sne:mva #1 fs ; finish it mva #1 Erase - ldx TankNr - jsr DrawTankNr.SkipHidingPM ; it's necessary becouse DrawTankNr skips tanks with no energy ! - ;PAUSE 2 + ldx TankNr + jsr DrawTankNr.SkipHidingPM ; it's necessary becouse DrawTankNr skips tanks with no energy ! + ;PAUSE 2 ldy #1 jsr PauseYFrames mva #0 Erase - ldx TankNr + ldx TankNr jsr DrawTankNr.SkipHidingPM ;PAUSE 2 ldy #1 jsr PauseYFrames dec fs jne tankflash_loop - rts + rts .endp ;-------------------------------------------------- @@ -841,48 +833,48 @@ tankflash_loop ; if use DrawInPosition entry point then: ; xdraw, ydraw - coordinates left LOWER corner of Tank char ; values remain there after a DrawTankNr proc. -; +; ; this proc change xdraw, ydraw and temp! ;-------------------------------------------------- - sbw xdraw #$03 ; 3 pixels to left - ; draw left vertical line of shield ( | ) - mva #7 temp ; strange !!! + sbw xdraw #$03 ; 3 pixels to left + ; draw left vertical line of shield ( | ) + mva #7 temp ; strange !!! @ - jsr plot -.nowarn dew ydraw - dec temp - bne @- - ; draw left oblique line of shield ( / ) - mva #3 temp + jsr plot +.nowarn dew ydraw + dec temp + bne @- + ; draw left oblique line of shield ( / ) + mva #3 temp @ - jsr plot -.nowarn dew ydraw - inw xdraw - dec temp - bne @- - ; draw top horizontal line of shield ( _ ) - mva #7 temp + jsr plot +.nowarn dew ydraw + inw xdraw + dec temp + bne @- + ; draw top horizontal line of shield ( _ ) + mva #7 temp @ - jsr plot - inw xdraw - dec temp - bne @- - ; draw right oblique line of shield ( \ ) - mva #3 temp + jsr plot + inw xdraw + dec temp + bne @- + ; draw right oblique line of shield ( \ ) + mva #3 temp @ - jsr plot - inw ydraw - inw xdraw - dec temp - bne @- - ; draw right vertical line of shield ( | ) - mva #7 temp + jsr plot + inw ydraw + inw xdraw + dec temp + bne @- + ; draw right vertical line of shield ( | ) + mva #7 temp @ - jsr plot - inw ydraw - dec temp - bne @- - rts + jsr plot + inw ydraw + dec temp + bne @- + rts .endp ;-------------------------------------------------- .proc DrawTankShieldHorns @@ -890,18 +882,18 @@ tankflash_loop ; this proc draws a little "horns" on shield. ; Symbol of defensive but aggressive :) weapon ;-------------------------------------------------- -.nowarn dew xdraw ; 1 pixel left - sbw ydraw #$0a ; 10 pixels up - jsr plot -.nowarn dew ydraw - inw xdraw - jsr plot - sbw xdraw #$0d ; 13 pixels left - jsr plot - inw xdraw - inw ydraw - jsr plot - rts +.nowarn dew xdraw ; 1 pixel left + sbw ydraw #$0a ; 10 pixels up + jsr plot +.nowarn dew ydraw + inw xdraw + jsr plot + sbw xdraw #$0d ; 13 pixels left + jsr plot + inw xdraw + inw ydraw + jsr plot + rts .endp ;-------------------------------------------------- .proc DrawTankShieldBoldLine @@ -909,152 +901,152 @@ tankflash_loop ; this proc draws bold top on shield. ; Symbol of ablative shield ? :) ;-------------------------------------------------- - sbw xdraw #$04 ; 5 pixels left - sbw ydraw #$0b ; 11 pixels up - ; draw additional top horizontal line of shield ( _ ) - mva #6 temp + sbw xdraw #$04 ; 5 pixels left + sbw ydraw #$0b ; 11 pixels up + ; draw additional top horizontal line of shield ( _ ) + mva #6 temp @ - jsr plot -.nowarn dew xdraw - dec temp - bne @- - rts + jsr plot +.nowarn dew xdraw + dec temp + bne @- + rts .endp ;-------------------------------------------------- .proc DrawTankParachute ;Tank number in X ;-------------------------------------------------- - lda #char_parachute_______ ; parachute symbol + lda #char_parachute ; parachute symbol sta CharCode lda Ytankstable,x - cmp #16 - bcc ToHighToParachute + cmp #16 + bcc ToHighToParachute ;sec sbc #8 sta ydraw jsr SetupXYdraw.X jsr TypeChar ToHighToParachute - ldx TankNr - rts + ldx TankNr + rts .endp ;-------------------------------------------------- .proc DrawTankRocketEngine ; X - tank number -; +; ; this proc change xdraw, ydraw and temp! ;-------------------------------------------------- - clc - lda Ytankstable,x - adc #2 ; 1 pixel down - sta ydraw - mva #0 ydraw+1 - - clc - lda XtanksTableL,x - adc #2 ; 2 pixels to right - sta xdraw - lda XtanksTableH,x - adc #0 - sta xdraw+1 + clc + lda Ytankstable,x + adc #2 ; 1 pixel down + sta ydraw + mva #0 ydraw+1 - ; draw first horizontal line - mva #5 temp + clc + lda XtanksTableL,x + adc #2 ; 2 pixels to right + sta xdraw + lda XtanksTableH,x + adc #0 + sta xdraw+1 + + ; draw first horizontal line + mva #5 temp @ - jsr plot - inw xdraw - dec temp - bne @- - - sbw xdraw #2 ; 2 pixels left - inw ydraw ; 1 pixel down - - ; draw second horizontal line - mva #3 temp + jsr plot + inw xdraw + dec temp + bne @- + + sbw xdraw #2 ; 2 pixels left + inw ydraw ; 1 pixel down + + ; draw second horizontal line + mva #3 temp @ - jsr plot -.nowarn dew xdraw - dec temp - bne @- + jsr plot +.nowarn dew xdraw + dec temp + bne @- - adw xdraw #2 ; 2 pixels right - inw ydraw ; 1 pixel down + adw xdraw #2 ; 2 pixels right + inw ydraw ; 1 pixel down - ; and last pixel - jsr plot + ; and last pixel + jsr plot - ldx TankNr - rts + ldx TankNr + rts .endp ;-------------------------------------------------- .proc DrawTankEngine ; X - tank number -; +; ; this proc change xdraw, ydraw and temp! ;-------------------------------------------------- - ; one pixel under tank - clc - lda Ytankstable,x - adc #1 - sta ydraw - mva #0 ydraw+1 - lda XtankstableL,x - sta xdraw - lda XtankstableH,x - sta xdraw+1 - ; clear first pixel under tank - mva #0 color - jsr plot - inw xdraw - ; plot 6 random color pixels - mva #6 temp -@ lda Erase - eor #%00000001 - and random - and #%00000001 - sta color - jsr plot - inw xdraw - dec temp - bne @- - ; clear last pixel under tank - mva #0 color - jsr plot - ldx TankNr - rts + ; one pixel under tank + clc + lda Ytankstable,x + adc #1 + sta ydraw + mva #0 ydraw+1 + lda XtankstableL,x + sta xdraw + lda XtankstableH,x + sta xdraw+1 + ; clear first pixel under tank + mva #0 color + jsr plot + inw xdraw + ; plot 6 random color pixels + mva #6 temp +@ lda Erase + eor #%00000001 + and random + and #%00000001 + sta color + jsr plot + inw xdraw + dec temp + bne @- + ; clear last pixel under tank + mva #0 color + jsr plot + ldx TankNr + rts .endp ;-------------------------------------------------- .proc TankFalls; ;-------------------------------------------------- lda #0 - sta PreviousFall ; bit 7 - left, bit 6 - right + sta PreviousFall ; bit 7 - left, bit 6 - right sta EndOfTheFallFlag sta Parachute - mva #2 FallingSoundBit ; another trick for only one sfx initialization in loop + mva #2 FallingSoundBit ; another trick for only one sfx initialization in loop ; let's check if the given tank has got the parachute - ldx TankNr - lda ActiveDefenceWeapon,x - cmp #ind_Parachute______ ; parachute - beq ParachuteActive - cmp #ind_StrongParachute ; strong parachute - beq ParachuteActive - cmp #ind_Force_Shield___ ; shield witch energy and parachute + ldx TankNr + lda ActiveDefenceWeapon,x + cmp #ind_Parachute ; parachute + beq ParachuteActive + cmp #ind_StrongParachute ; strong parachute + beq ParachuteActive + cmp #ind_Force_Shield ; shield witch energy and parachute bne TankFallsX ParachuteActive inc Parachute TankFallsX - ; sound only if really falls - lda Parachute - and FallingSoundBit ; bit 1 - beq NoFallingSound - mva #0 FallingSoundBit + ; sound only if really falls + lda Parachute + and FallingSoundBit ; bit 1 + beq NoFallingSound + mva #0 FallingSoundBit mva #sfx_shield_off sfx_effect NoFallingSound ; clear previous position mva #1 Erase - jsr DrawTankNr + jsr ClearTankNr ; and the parachute (if present) lda Parachute and #01 @@ -1065,8 +1057,8 @@ NoFallingSound DoNotClearParachute mva #0 Erase ; ldx TankNr - lda EndOfTheFallFlag ; We only get byte below the tank if still falling - bne NoGroundCheck + lda EndOfTheFallFlag ; We only get byte below the tank if still falling + bne NoGroundCheck ; coordinates of the first pixel under the tank ldx TankNr jsr SetupXYdraw.X @@ -1076,58 +1068,58 @@ DoNotClearParachute ; time in our lives! Tada! It opens a new chapter!!! sta ydraw ; -; UnderTank1 ; byte under tank -; UnderTank2 ; byte under tank reversed (for simple check right direction) +; UnderTank1 ; byte under tank +; UnderTank2 ; byte under tank reversed (for simple check right direction) lda #08 sta temp ; Loop Counter ByteBelowTank jsr point_plot beq EmptyPoint2 sec - ror UnderTank2 - sec + ror UnderTank2 + sec bcs ROLPoint2 EmptyPoint2 clc - ror UnderTank2 - clc + ror UnderTank2 + clc ROLPoint2 rol UnderTank1 inw xdraw dec temp - bne ByteBelowTank + bne ByteBelowTank NoGroundCheck ldx TankNr - lda Ytankstable,x - cmp #screenheight-1 ; tank on lowest position (no falling down) - jcs EndOfFall - lda UnderTank1 - bne NoFallingDown - ; Tank falling down ---- - lda Parachute + lda Ytankstable,x + cmp #screenheight-1 ; tank on lowest position (no falling down) + jcs EndOfFall + lda UnderTank1 + bne NoFallingDown + ; Tank falling down ---- + lda Parachute and #1 bne ParachutePresent - ; decreasing energy + ; decreasing energy ldy #2 ; how much energy to substract if no parachute jsr DecreaseEnergyX ParachutePresent - ; check parachute type - lda ActiveDefenceWeapon,x + ; check parachute type + lda ActiveDefenceWeapon,x cmp #ind_StrongParachute ; strong parachute - bne OneTimeParachute + bne OneTimeParachute ; decreasing energy of parachute ldy #1 ; how much parachute energy to substract - jsr DecreaseShieldEnergyX - cpy #0 ; is necessary to reduce tenk energy ? - beq @+ + jsr DecreaseShieldEnergyX + cpy #0 ; is necessary to reduce tenk energy ? + beq @+ jsr DecreaseEnergyX @ - ; check energy of parachute - lda ShieldEnergy,x - bne OneTimeParachute - lda #$00 - sta Parachute - sta ActiveDefenceWeapon,x ; deactivate defence + ; check energy of parachute + lda ShieldEnergy,x + bne OneTimeParachute + lda #$00 + sta Parachute + sta ActiveDefenceWeapon,x ; deactivate defence OneTimeParachute lda Parachute ora #2 ; we set bit nr 1 (nr 0 means that parachute is present) @@ -1137,28 +1129,28 @@ OneTimeParachute clc adc #1 sta Ytankstable,x - jmp EndOfFCycle + jmp EndOfFCycle NoFallingDown - ; check direction (left or right) - ldy #SlideLeftTableLen-1 ; SlideLeftTable length -1 (from 0 to 7) -@ lda SlideLeftTable,y - cmp UnderTank1 - beq FallingLeft - cmp UnderTank2 - beq FallingRight - dey - bpl @- - bmi NoLeftOrRight + ; check direction (left or right) + ldy #SlideLeftTableLen-1 ; SlideLeftTable length -1 (from 0 to 7) +@ lda SlideLeftTable,y + cmp UnderTank1 + beq FallingLeft + cmp UnderTank2 + beq FallingRight + dey + bpl @- + bmi NoLeftOrRight FallingRight - ; tank is falling right - bit PreviousFall ; bit 6 - left - bvs EndRightFall + ; tank is falling right + bit PreviousFall ; bit 6 - left + bvs EndRightFall ; we finish falling right if the tank reached the edge of the screen lda XtanksTableH,x - cmp #>(screenwidth-TankWidth-2) ; 2 pixels correction due to a barrel wider than tank - bne @+ + cmp #>(screenwidth-TankWidth-2) ; 2 pixels correction due to a barrel wider than tank + bne @+ lda XtanksTableL,x - cmp #<(screenwidth-TankWidth-2) ; 2 pixels correction due to a barrel wider than tank + cmp #<(screenwidth-TankWidth-2) ; 2 pixels correction due to a barrel wider than tank @ bcs EndRightFall NotRightEdge ; tank is falling right - modify coorinates @@ -1169,17 +1161,17 @@ NotRightEdge lda XtankstableH,x adc #0 sta XtankstableH,x - mva #%10000000 PreviousFall ; set bit 7 - right - bne EndOfFCycle + mva #%10000000 PreviousFall ; set bit 7 - right + bne EndOfFCycle FallingLeft - ; tank is falling left - bit PreviousFall ; bit 7 - right - bmi EndLeftFall + ; tank is falling left + bit PreviousFall ; bit 7 - right + bmi EndLeftFall ; we finish falling left if the tank reached the edge of the screen lda XtanksTableH,x bne NotLeftEdge lda XtanksTableL,x - cmp #3 ; 2 pixels correction due to a barrel wider than tank + cmp #3 ; 2 pixels correction due to a barrel wider than tank bcc EndLeftFall NotLeftEdge ; tank is falling left - modify coorinates @@ -1190,51 +1182,51 @@ NotLeftEdge lda XtankstableH,x sbc #0 sta XtankstableH,x - mva #%01000000 PreviousFall ; set bit 6 - left - bne EndOfFCycle + mva #%01000000 PreviousFall ; set bit 6 - left + bne EndOfFCycle EndLeftFall EndRightFall NoLeftOrRight - inc EndOfTheFallFlag ; after this is shouldn't fall + inc EndOfTheFallFlag ; after this is shouldn't fall EndOfFCycle - ; draw tank on new position - jsr DrawTankNr ; ew have TankNr in X (I hope :) ) + ; draw tank on new position + jsr DrawTankNr ; ew have TankNr in X (I hope :) ) ; checking is parachute present and if so, draw it lda Parachute - cmp #3 ; parachute and falling - bne DoNotDrawParachute + cmp #3 ; parachute and falling + bne DoNotDrawParachute ; here we draw parachute ; ldx TankNr jsr DrawTankParachute - jsr WaitOneFrame ; only if tank with parachute + jsr WaitOneFrame ; only if tank with parachute RapidFalling DoNotDrawParachute - lda EndOfTheFallFlag - jeq TankFallsX + lda EndOfTheFallFlag + jeq TankFallsX ; Tank falling down already finished, but it is not sure that ; the horizontal coordinate is even. ; If it is odd then it must be corrected because otherwise ; P/M graphics background would not look OK ; ldx TankNr - ; x correction for P/M - ; -- - .IF XCORRECTION_FOR_PM = 1 + ; x correction for P/M + ; -- + .IF XCORRECTION_FOR_PM = 1 lda XtanksTableL,x and #$01 beq EndOfFall ; if it is even then it is the end ; and if not, we push it one pixel the way it was falling before - lda #%10000000 ; set "virtual ground" for right falling - ldy #%00000001 - bit PreviousFall - bmi ForceFallLeft - tay ; tricky - replaces ldy #%10000000 - lda #%00000001 ; set "virtual ground" for left falling + lda #%10000000 ; set "virtual ground" for right falling + ldy #%00000001 + bit PreviousFall + bmi ForceFallLeft + tay ; tricky - replaces ldy #%10000000 + lda #%00000001 ; set "virtual ground" for left falling ForceFallLeft - sta UnderTank1 - sty UnderTank2 - jmp TankFallsX - .ENDIF - ; -- + sta UnderTank1 + sty UnderTank2 + jmp TankFallsX + .ENDIF + ; -- EndOfFall mva #1 Erase ; ldx TankNr @@ -1243,11 +1235,11 @@ EndOfFall lda Parachute cmp #$03 ; was falling down and the parachute bne NoParachuteWeapon - ; first we check type of parachute - lda ActiveDefenceWeapon,x - cmp #ind_Parachute______ ; deactivate weapon only if parachute (54) - bne NoParachuteWeapon - mva #0 ActiveDefenceWeapon,x ; deactivate defence weapon (parachute) + ; first we check type of parachute + lda ActiveDefenceWeapon,x + cmp #ind_Parachute ; deactivate weapon only if parachute (54) + bne NoParachuteWeapon + mva #0 ActiveDefenceWeapon,x ; deactivate defence weapon (parachute) NoParachuteWeapon ; now we clear parachute on the screen if present lda Parachute @@ -1255,9 +1247,8 @@ NoParachuteWeapon beq ThereWasNoParachute jsr DrawTankParachute ThereWasNoParachute - mva #0 Erase -; ldx TankNr - jsr DrawTankNr ; redraw tank after erase parachute (exactly for redraw leaky schield :) ) +; ldx TankNr + jsr PutTankNr ; redraw tank after erase parachute (exactly for redraw leaky schield :) ) mva #sfx_silencer sfx_effect rts @@ -1267,70 +1258,21 @@ ThereWasNoParachute .proc ClearPMmemory ;-------------------------------------------------- - lda #$00 - tay -@ sta pmgraph+$300,y - sta pmgraph+$400,y - sta pmgraph+$500,y - sta pmgraph+$600,y - sta pmgraph+$700,y - iny - bne @- - rts + lda #$00 + tay +@ sta pmgraph+$300,y + sta pmgraph+$400,y + sta pmgraph+$500,y + sta pmgraph+$600,y + sta pmgraph+$700,y + iny + bne @- + rts .endp -;-------------------------------------------------- -.proc drawmountains -;-------------------------------------------------- - mwa #0 xdraw - mwa #mountaintable modify - mva #1 color - -drawmountainsloop - ldy #0 - lda (modify),y - cmp #screenheight - beq NoMountain - sta ydraw - sty ydraw+1 -.IF FASTER_GRAF_PROCS = 1 -; there was Drawline proc - lda #screenheight - sec - sbc ydraw - sta tempbyte01 - jsr plot.MakePlot - ; after plot we have: (xbyte),y - addres of screen byte; X - index in bittable (number of bit) -; jmp IntoDraw ; jumps inside Draw routine - ; because one pixel is already plotted (and who cares? :) ) -@ - lda (xbyte),y - and bittable2,x - sta (xbyte),y -;IntoDraw - adw xbyte #screenBytes - dec tempbyte01 - bne @- -; end of Drawline proc -.ELSE -; there was Drawline proc -drawline - jsr plot.MakePlot - inc ydraw - lda ydraw - cmp #screenheight - bne drawline -; end of Drawline proc -.ENDIF -NoMountain - inw modify - inw xdraw - cpw xdraw #screenwidth - bne drawmountainsloop - rts /* ;-------------------------------------------------- -drawmountainspixel ; never used ? +drawmountainspixel ; never used ? ;-------------------------------------------------- mwa #0 xdraw mwa #mountaintable modify @@ -1338,7 +1280,7 @@ drawmountainspixelloop ldy #0 lda (modify),y sta ydraw - sty ydraw+1 + sty ydraw+1 jsr plot inw modify inw xdraw @@ -1346,7 +1288,6 @@ drawmountainspixelloop bne drawmountainspixelloop rts */ -.endp ;-------------------------------------------------- .proc SoilDown2 ;-------------------------------------------------- @@ -1374,17 +1315,17 @@ drawmountainspixelloop ; how it works. I have just translated Polish comment ; but I do not understand a word of it :) ; If you know how it works, please write here :)))) - jsr ClearTanks + jsr ClearTanks NoClearTanks ; Fix for lonely pixel after nuclear winter :) #103 - lda #0 - sta xdraw - sta xdraw+1 - sta ydraw - sta ydraw+1 - sta color - jsr plot + lda #0 + sta xdraw + sta xdraw+1 + sta ydraw + sta ydraw+1 + sta color + jsr plot ; First we look for highest pixels and fill with their coordinates ; both tables @@ -1394,7 +1335,7 @@ NoClearTanks adw RangeLeft #mountaintable2 tempor2 cpw xdraw RangeRight - jcs NothingToFall + jcs NothingToFall NextColumn1 mwa #0 ydraw @@ -1410,9 +1351,9 @@ StillNothing inc ydraw lda ydraw cmp #screenheight - bne NextPoint1 - ; no pixels on whole column !!! - ldy #0 + bne NextPoint1 + ; no pixels on whole column !!! + ldy #0 lda ydraw sta (tempor2),y sta (temp),y @@ -1478,16 +1419,19 @@ ColumnIsReady bcc FalloutOfLine beq FalloutOfLine + jsr CheckExitKeys ; Check for O, Esc or Start+Option keys + spl:rts ; exit if pressed 'Exit keys' + lda IsEndOfTheFallFlag ; we repeat untill at some point first table reaches ; level of the mountains jeq MainFallout2 ; now correct heights are in the mountaintable - sta color ; Pozor! :) we know - now A=1 + sta color ; Pozor! :) we know - now A=1 NothingToFall mva #sfx_silencer sfx_effect - jsr DrawTanks - rts + jmp DrawTanks + ; rts .endp ;-------------------------------------------------- @@ -1595,7 +1539,7 @@ EndDrawing rts .endp -/* +/* ;-------------------------------------------------- .proc calculatemountains0 ; Only for testing - makes ground flat (0 pixels) @@ -1604,14 +1548,14 @@ EndDrawing ;-------------------------------------------------- mwa #0 xdraw nextPointDrawing - adw xdraw #mountaintable modify + adw xdraw #mountaintable modify lda #screenheight ldy #0 sta (modify),y inw xdraw cpw xdraw #screenwidth bne nextPointDrawing - ldx NumberOfPlayers + ldx NumberOfPlayers dex SetYofNextTank lda #screenheight-1 @@ -1630,511 +1574,16 @@ SetYofNextTank ldy #0 ldx #screenheight-1 nextPointChecking - txa + txa cmp (modify),y - bcc NotHigher + bcc NotHigher lda (modify),y - tax + tax NotHigher inw modify cpw modify #(mountaintable+screenwidth) bne nextPointChecking - txa - rts -.endp - -; ----------------------------------------- -.proc unPlot -; plots a point and saves the plotted byte, reverts the previous plot. -; ----------------------------------------- - ldx #0 ; only one pixel -unPlotAfterX - stx WhichUnPlot - - ; first remake the oldie - lda oldplotL,x - sta oldplot - lda oldplotH,x - sta oldplot+1 - - lda oldply,x - tay - lda oldora,x - sta (oldplot),y - - - ; is it not out of the screen ???? - cpw ydraw #screenheight - jcc CheckX - mwa #0 ydraw -CheckX - cpw xdraw #screenwidth - jcs EndOfUnPlot -MakeUnPlot - ; let's count coordinates taken from xdraw and ydraw - mwa xdraw xbyte - - lda xbyte - and #$7 - sta ybit - - lsrw xbyte - rorw xbyte - rorw xbyte -;--- - ldy xbyte - - ldx WhichUnPlot - tya - sta oldply,x - - - ldx ydraw - lda linetableL,x - sta xbyte - sta oldplot - lda linetableH,x - sta xbyte+1 - sta oldplot+1 - ldx ybit - - - lda color - bne ClearUnPlot - - ;plotting here - lda (xbyte),y - sta OldOraTemp - ora bittable,x - sta (xbyte),y - jmp ContinueUnPlot -ClearUnPlot - lda (xbyte),y - sta OldOraTemp - and bittable2,x - sta (xbyte),y -ContinueUnPlot - ldx WhichUnPlot - lda OldOraTemp - sta oldora,x - lda oldplot - sta oldplotL,x - lda oldplot+1 - sta oldplotH,x - ; and now we must solve the problem of several plots - ; in one byte - ldx #4 - ldy WhichUnPlot -LetsCheckOverlapping - cpx WhichUnPlot - beq SkipThisPlot - lda oldplotL,x - cmp oldplotL,y - bne NotTheSamePlot - lda oldplotH,x - cmp oldplotH,y - bne NotTheSamePlot - lda oldply,x - cmp oldply,y - bne NotTheSamePlot - ; the pixel is in the same byte so let's take correct contents - lda oldora,x - sta oldora,y -NotTheSamePlot -SkipThisPlot - dex - bpl LetsCheckOverlapping -EndOfUnPlot - rts -.endp - -; ----------------------------------------- -.proc plot ;plot (xdraw, ydraw, color) -; color == 1 --> put pixel -; color == 0 --> erase pixel -; this is one of the most important routines in the whole -; game. If you are going to speed up the game, start with -; plot - it is used by every single effect starting from explosions -; through line drawing and small text output!!! -; -; Optimized by 0xF (Fox) THXXXX!!! - -; ----------------------------------------- - ; is it not over the screen ??? - cpw ydraw #(screenheight+1); changed for one additional line. cpw ydraw #(screenheight-1) - bcs unPlot.EndOfUnPlot ;nearest RTS -CheckX02 - cpw xdraw #screenwidth - bcs EndOfPlot -MakePlot - ; let's calculate coordinates from xdraw and ydraw - - ;xbyte = xbyte/8 - lda xdraw+1 - lsr - lda xdraw - ror ;just one bit over 256. Max screenwidth = 512!!! - lsr - lsr - sta xbyte - ;--- - ldx ydraw - ldy linetableL,x - lda linetableH,x - sta xbyte+1 - - lda xdraw - and #$7 - tax - lda color - bne ClearPlot - - lda (xbyte),y - ora bittable,x - sta (xbyte),y -EndOfPlot - rts -ClearPlot - lda (xbyte),y - and bittable2,x - sta (xbyte),y - rts -.endp - -; ----------------------------------------- -.proc point_plot -; ----------------------------------------- - ; checks state of the pixel (coordinates in xdraw and ydraw) - ; result is in A (zero or appropriate bit is set) - - ; let's calculate coordinates from xdraw and ydraw - - ;xbyte = xbyte/8 - lda xdraw+1 - lsr - lda xdraw - ror ;just one bit over 256. Max screenwidht = 512!!! - lsr - lsr - sta xbyte - ;--- - ldx ydraw - ldy linetableL,x - lda linetableH,x - sta xbyte+1 - - lda xdraw - and #$7 - tax - - lda (xbyte),y - eor #$ff - and bittable,x - rts -.endp -;-------------------------------------------------- -.proc TypeChar -; puts char on the graphics screen -; in: CharCode -; in: left LOWER corner of the char coordinates (xdraw, ydraw) -;-------------------------------------------------- - ; char to the table - lda CharCode - sta fontind - lda #$00 - sta fontind+1 - ; char intex times 8 - aslw fontind - rolw fontind - rolw fontind - - adw fontind #TankFont - - ; and 8 bytes to the table - ldy #7 -CopyChar - lda (fontind),y - eor #$ff - sta char1,y - lda #$ff - sta char2,y - dey - bpl CopyChar - ; and 8 subsequent bytes as a mask - adw fontind #8 - ldy #7 -CopyMask - lda (fontind),y - eor #$ff - sta mask1,y - lda #$00 - sta mask2,y - dey - bpl CopyMask - -.IF FASTER_GRAF_PROCS = 1 - ; calculating coordinates from xdraw and ydraw - mwa xdraw xbyte - - lda xbyte - and #$7 - sta ybit - - lsrw xbyte ; div 8 - rorw xbyte - rorw xbyte -;--- - ldy xbyte - - lda ydraw ; y = y - 7 because left lower. shouldn't it be 8? - sec - sbc #7 - tax - - lda linetableL,x - sta xbyte - lda linetableH,x - sta xbyte+1 - ; mask preparation and character shifting - ldx ybit - beq MaskOK00 -MakeMask00 - .rept 8 - lsr mask1+# - ror mask2+# - .endr - sec - .rept 8 - ror char1+# ; in second (and next) lines we have C=1 - one SEC enough - ror char2+# - .endr - dex - bne MakeMask00 -MaskOK00 - ; here x=0 - lda Erase - beq CharLoopi ; it works, because x=0 - lda #$ff - ldx #7 -EmptyChar - sta char1,x - sta char2,x - dex - bpl EmptyChar - ldx #0 -CharLoopi - lda (xbyte),y - ora mask1,x - and char1,x - sta (xbyte),y - iny - lda (xbyte),y - ora mask2,x - and char2,x - sta (xbyte),y - dey - adw xbyte #screenBytes - inx - cpx #8 - bne CharLoopi -.ELSE - mvx #7 temp ; line counter (Y) -CharLoop1 - mva #7 temp+1 ; pixel counter (X) -CharLoop2 - mva #0 color - rol mask1,x - bcc NoMaskNoPlot - rol char1,x - bcs NoPlot -MakeCharPlot - lda Erase - bne ErasingChar - inc color -ErasingChar -NoPlot - jsr plot.MakePlot -AfterCharPlot - inw xdraw - ldx temp - dec temp+1 - bpl CharLoop2 - sec - sbw xdraw #8 - dec ydraw - ldx temp - dex - stx temp - bpl CharLoop1 - clc - lda ydraw - adc #8 - sta ydraw - bne EndPutChar -NoMaskNoPlot - rol char1,x - jmp AfterCharPlot -.ENDIF -EndPutChar - rts -.endp - -;-------------------------------------------------- -.proc PutChar4x4 -; puts 4x4 pixels char on the graphics screen -; in: dx, dy (LOWER left corner of the char) -; in: CharCode4x4 (.sbyte) -; in: plot4x4color (0/255) -; all pixels are being drawn -; (empty and not empty) -;-------------------------------------------------- - cpw dy #(screenheight-1) - jcs TypeChar.EndPutChar ;nearest RTS - cpw dy #(4) - jcc TypeChar.EndPutChar ;nearest RTS - cpw dx #(screenwidth-4) - jcs TypeChar.EndPutChar ;nearest RTS - ; checks ommited. - ; char to the table - lda CharCode4x4 - and #%00000001 - beq Upper4bits - lda #$ff ; better option to check (nibbler4x4 = $00 or $ff) -Upper4bits - sta nibbler4x4 - lda CharCode4x4 - lsr - sta fontind - lda #$00 - sta fontind+1 - - adw fontind #font4x4 - - ; and 4 bytes to the table - ldy #0 - ldx #3 -CopyChar - lda (fontind),y ; Y must be 0 !!!! - bit nibbler4x4 - bpl GetUpper4bits - :4 rol -GetUpper4bits - ora #$0f - sta char1,x - lda #$ff - sta char2,x - ; and 4 bytes as a mask - lda #$f0 - sta mask1,x - lda #$00 - sta mask2,x - adw fontind #32 ; next byte of 4x4 font - dex - bpl CopyChar - -.IF FASTER_GRAF_PROCS = 1 - ; calculating coordinates from xdraw and ydraw - mwa dx xbyte - - lda xbyte - and #$7 - sta ybit - - :3 lsrw xbyte ; div 8 -; rorw xbyte -; rorw xbyte -;--- - ldy xbyte ; horizontal byte offet stored in Y - lda dy ; y = y - 3 because left lower. - sec - sbc #3 - tax - - lda linetableL,x - sta xbyte - lda linetableH,x - sta xbyte+1 - ; mask preparation and character shifting - ldx ybit - beq MaskOK01 -MakeMask01 - .rept 4 - lsr mask1+# - ror mask2+# - .endr - sec - .rept 4 - ror char1+# ; in second (and next) lines we have C=1 - one SEC enough - ror char2+# - .endr - dex - bne MakeMask01 -MaskOK01 - ldx #0 -CharLoopi4x4 - lda (xbyte),y - ora mask1,x - bit plot4x4color - bpl PutInColor0_1 ; only mask - no char - and char1,x -PutInColor0_1 - sta (xbyte),y - iny - lda (xbyte),y - ora mask2,x - bit plot4x4color - bpl PutInColor0_2 ; only mask - no char - and char2,x -PutInColor0_2 - sta (xbyte),y - dey - adw xbyte #screenBytes - inx - cpx #4 - bne CharLoopi4x4 -.ELSE - mwa xdraw char2 - mwa ydraw mask2 - mva color mask2+2 - mwa dx xdraw - mwa dy ydraw - mvx #3 temp ; line counter (Y) -CharLoop1 - mva #3 temp+1 ; pixel counter (X) -CharLoop2 - mva #0 color - rol mask1,x - bcc NoMaskNoPlot - rol char1,x - bcs NoPlot -MakeCharPlot - lda plot4x4color - beq ErasingChar - inc color -ErasingChar -NoPlot - jsr plot.MakePlot -AfterCharPlot - inw xdraw - ldx temp - dec temp+1 - bpl CharLoop2 - sec - sbw xdraw #4 - dec ydraw - ldx temp - dex - stx temp - bpl CharLoop1 - mwa char2 xdraw - mwa mask2 ydraw - mva mask2+2 color - bpl EndPut4x4 -NoMaskNoPlot - rol char1,x - jmp AfterCharPlot -.ENDIF -EndPut4x4 + txa rts .endp @@ -2152,11 +1601,11 @@ EndPut4x4 sta temp ; opty possible ; substract address of the next text from previous to get text length sbw temp LineAddress4x4 temp2 - mva temp2 fx + mva temp2 fx ;jsr Display4x4AboveTank ;rts - ; POZOR !!! + ; POZOR !!! .endp ;-------------------------------------------------------- @@ -2296,13 +1745,13 @@ DOTOldLowestValue bne end_found dey bne @- - + end_found iny sty fx ldy tankNr - jsr Display4x4AboveTank - rts + jmp Display4x4AboveTank + ; rts .endp ;------------------------------- @@ -2333,7 +1782,7 @@ TypeLine4x4Loop sta CharCode4x4 mwa LineXdraw dx mva LineYdraw dy - mva #0 dy+1 ; dy is 2 bytes value + mva #0 dy+1 ; dy is 2 bytes value jsr PutChar4x4 ;type empty pixels as well! adw LineXdraw #4 inc:lda LineCharNr @@ -2348,21 +1797,21 @@ EndOfTypeLine4x4 ;-------------------------------- .proc AreYouSure ;using 4x4 font - + mva #4 ResultY ; where seppuku text starts Y-wise on the screen - + ;top frame mva ResultY LineYdraw jsr TL4x4_top adb ResultY #4 ;next line - + ;sure? mwa #areYouSureText LineAddress4x4 - jsr _sep_opty + jsr _sep_opty ;bottom frame mva ResultY LineYdraw jsr TL4x4_bottom - + jsr GetKey cmp #@kbcode._Y ; $2b ; "Y" @@ -2372,14 +1821,14 @@ EndOfTypeLine4x4 @ mva #0 escFlag skip01 jsr WaitForKeyRelease - + ;clean mva #3 di mva #4 ResultY @ mva #$ff plot4x4color mwa #lineClear LineAddress4x4 - jsr _sep_opty + jsr _sep_opty dec di bne @- @@ -2398,31 +1847,31 @@ quit_areyousure ;-------------------------------- .proc DisplaySeppuku ;using 4x4 font - + mva #20 fs ; temp, how many times blink the billboard seppuku_loop lda CONSOL ; turbo mode - and #%00000001 ; START KEY - sne:mva #1 fs ; finish it + and #%00000001 ; START KEY + sne:mva #1 fs ; finish it mva #4 ResultY ; where seppuku text starts Y-wise on the screen - + ;top frame mva ResultY LineYdraw jsr TL4x4_top adb ResultY #4 ;next line - + ;seppuku mwa #seppukuText LineAddress4x4 jsr _sep_opty - + ;bottom frame mva ResultY LineYdraw jsr TL4x4_bottom ; just go ;clean seppuku - + mva #3 di ;mva #4 ResultY lda #4 @@ -2430,7 +1879,7 @@ seppuku_loop loplop ;@ mwa #lineClear LineAddress4x4 jsr _sep_opty - + dec di bne loplop ;@- @@ -2439,22 +1888,9 @@ loplop ;@ quit_seppuku rts - + .endp -;-------------------------------------------------- -.proc SetMainScreen -; mva #0 dmactls - SetDLI DLIinterruptGraph ; jsr SetDLI for graphics (game) screen - mwa #dl dlptrs ; issue #72 (glitches when switches) - lda #%00111110 -; and #$fc -; ora #$02 ; 2=normal, 3 = wide screen width - sta dmactls - mva WallsType COLBAKS ; set color of background - jsr WaitOneFrame - rts -.endp ; ------------------------------------- .proc SetupXYdraw lda ytankstable,x @@ -2473,7 +1909,7 @@ X lda XtanksTableL,x ;-------------------------------------------------- ;vx calculation ;vx = sin(90-Angle) for Angle <=90 - ;vx = -sin(Angle-90) for 90 < Angle <= 180 + ;vx = -sin(Angle-90) for 90 < Angle <= 180 ; erase previous barrel @@ -2482,25 +1918,25 @@ X lda XtanksTableL,x ; lda previousBarrelAngle,x ; sta Angle ; jsr DrawBarrelTech - ; + ; ; mva #1 color ldx TankNr jsr SetupXYdraw - lda BarrelLength,x - sta yc ; current tank barrel length + lda BarrelLength,x + sta yc ; current tank barrel length lda angleTable,x sta Angle - jsr DrawBarrelTech - rts + jmp DrawBarrelTech + ; rts .endp .proc DrawBarrelTech ; angle in Angle and A - + mvx #0 goleft cmp #91 bcc angleUnder90 - + ;over 90 sec sbc #90 @@ -2517,8 +1953,8 @@ angleUnder90 tax ; barrel start offset under 90deg adw xdraw #3 xdraw - -@ + +@ sbw ydraw #3 ydraw lda sintable,x ; cos(X) sta vx @@ -2531,7 +1967,7 @@ angleUnder90 lda Angle cmp #91 bcc YangleUnder90 - + lda #180 sec sbc Angle @@ -2543,19 +1979,19 @@ YangleUnder90 lda #0 ; all arithmetic to zero sta vx+1 sta vy+1 - lda #128 ; ; add 0.5 to fx and fy (not vx and vx) for better rounding - it's my opinion (Pecus) + lda #128 ; ; add 0.5 to fx and fy (not vx and vx) for better rounding - it's my opinion (Pecus) sta fx sta fy ; draw by vx vy - ; in each step + ; in each step ; 1. plot(xdraw, ydraw) ; 2. add vx and vy to 3 byte variables xdraw.fx, ydraw.fy ; 3 check length, if shorter, go to 1. - + ; mva #6 yc ; barrel length barrelLoop - + lda goleft bne goright clc @@ -2593,35 +2029,35 @@ ybarrel sta ydraw bcs @+ dec ydraw+1 -@ +@ jsr plot ;.MakePlot dec yc bne barrelLoop - + mwa xdraw EndOfTheBarrelX mva ydraw EndOfTheBarrelY - + rts .endp ;-------------------------------------------------- .proc PMoutofScreen ;-------------------------------------------------- lda #$00 ; let all P/M disappear - ldy #7 -@ sta hposp0,y - dey - bpl @- - ;:8 sta hposp0+# ; optimized... but Y! + ldy #7 +@ sta hposp0,y + dey + bpl @- + ;:8 sta hposp0+# ; optimized... but Y! rts .endp ;-------------------------------------------------- .proc ColorsOfSprites - ldy #3 -@ lda TankColoursTable,y ; colours of sprites under tanks - sta PCOLR0,y - dey - bpl @- + ldy #3 +@ lda TankColoursTable,y ; colours of sprites under tanks + sta PCOLR0,y + dey + bpl @- LDA TankColoursTable+4 STA COLOR3 ; joined missiles (5th tank) rts diff --git a/scorch.asm b/scorch.asm index 5c4a6bf..2be1c60 100644 --- a/scorch.asm +++ b/scorch.asm @@ -1,4 +1,4 @@ -; @com.wudsn.ide.asm.mainsourcefile=scorch.asm +; @com.wudsn.ide.asm.mainsourcefile=scorch.asm ;Atari 8-bit Scorched Earth source code ;--------------------------------------------------- ;by Tomasz 'pecus' Pecko and Pawel 'pirx' Kalinowski @@ -6,7 +6,9 @@ ;Miami & Warsaw 2022, 2023 ;--------------------------------------------------- -.def TARGET = 800 ; 5200 ; or 800 +.IFNDEF TARGET + .def TARGET = 800 ; 5200 +.ENDIF ;atari800 -5200 -cart ${outputFilePath} -cart-type 4 ;atari800 -run ${outputFilePath} ;--------------------------------------------------- @@ -17,11 +19,11 @@ ; (direct writes to screen memory - atari only :) ) ;--------------------------------------------------- - ;OPT r+ ; saves 12 bytes :O + ; OPT r+ ; saves 12 bytes :O ;--------------------------------------------------- .macro build - dta d"1.28" ; number of this build (4 bytes) + dta d"1.30" ; number of this build (4 bytes) .endm .macro RMTSong @@ -34,14 +36,14 @@ ;--------------------------------------------------- FirstZpageVariable = $57 - .zpvar DliColorBack .byte = FirstZpageVariable - .zpvar GradientNr .byte - .zpvar GradientColors .word - .zpvar WindChangeInRound .byte ; wind change after each turn (not round only) flag - (0 - round only, >0 - each turn) - .zpvar JoystickNumber .byte - .zpvar LazyFlag .byte ; 7 bit - run Lazy Darwin, 6 bit - run Lazy Boy or Darwin (!) after inventory, 0 - nothing - .zpvar SpyHardFlag .byte ; >$7f - run SpyHard after inventory - .zpvar Vdebug .byte ; "visual debug" flag ($00 - off, $ff - on) + .zpvar DliColorBack .byte = FirstZpageVariable + .zpvar GradientNr .byte + .zpvar GradientColors .word + .zpvar WindChangeInRound .byte ; wind change after each turn (not round only) flag - (0 - round only, >0 - each turn) + .zpvar JoystickNumber .byte + .zpvar LazyFlag .byte ; 7 bit - run Lazy Darwin, 6 bit - run Lazy Boy or Darwin (!) after inventory, 0 - nothing + .zpvar SpyHardFlag .byte ; >$7f - run SpyHard after inventory + .zpvar Vdebug .byte ; "visual debug" flag ($00 - off, $ff - on) .zpvar xdraw .word ;= $64 ;variable X for plot .zpvar ydraw .word ;variable Y for plot (like in Atari Basic - Y=0 in upper right corner of the screen) .zpvar xbyte .word @@ -59,10 +61,10 @@ FirstZpageVariable = $57 .zpvar xtempDRAW .word ;same as above for XDRAW routine .zpvar ytempDRAW .word ;same as above for XDRAW routine .zpvar tempor2 .word - .zpvar CreditsVScrol .byte + .zpvar CreditsVScrol .byte ;--------------temps used in circle routine .zpvar xi .word ;X (word) in draw routine - .zpvar fx .byte + .zpvar fx .byte .zpvar yi .word ;Y (word) in draw routine .zpvar fy .byte .zpvar xk .word @@ -74,21 +76,21 @@ FirstZpageVariable = $57 .zpvar di .word .zpvar dp .word ;---------------------------- - .zpvar UnderTank1 .byte - .zpvar UnderTank2 .byte + .zpvar UnderTank1 .byte + .zpvar UnderTank2 .byte ;---------------------------- - .zpvar TestFlightFlag .byte ; For AI test flights ($ff - test, $00 - standard shoot flight) + .zpvar TestFlightFlag .byte ; For AI test flights ($ff - test, $00 - standard shoot flight) .zpvar weaponPointer .word - .zpvar dliCounter .byte - .zpvar pressTimer .byte - .zpvar NTSCcounter .byte - .zpvar IsEndOfTheFallFlag .byte ; for small speedup ground falling - .zpvar sfx_effect .byte - .zpvar RMT_blocked .byte - .zpvar ScrollFlag .byte - .zpvar SkStatSimulator .byte - .zpvar FloatingAlt .byte ; floating tank altitude - .zpvar OverTankDir .byte ; (0 go right, $ff go left) direction of bypassing tanks on screen + .zpvar dliCounter .byte + .zpvar pressTimer .byte + .zpvar NTSCcounter .byte + .zpvar IsEndOfTheFallFlag .byte ; for small speedup ground falling + .zpvar sfx_effect .byte + .zpvar RMT_blocked .byte + .zpvar ScrollFlag .byte + .zpvar SkStatSimulator .byte + .zpvar FloatingAlt .byte ; floating tank altitude + .zpvar OverTankDir .byte ; (0 go right, $ff go left) direction of bypassing tanks on screen ; --------------OPTIMIZATION VARIABLES-------------- .zpvar Force .word @@ -103,7 +105,7 @@ FirstZpageVariable = $57 .zpvar NumberOfPlayers .byte ;current number of players (counted from 1) .zpvar Counter .byte ;temporary Counter for outside loops .zpvar ExplosionRadius .byte - .zpvar FunkyBombCounter .byte + .zpvar FunkyBombCounter .byte .zpvar ResultY .byte .zpvar xcircle .word .zpvar ycircle .word @@ -126,10 +128,10 @@ FirstZpageVariable = $57 .zpvar RangeLeft .word .zpvar RangeRight .word .zpvar NewAngle .byte - .zpvar escFlag .byte + .zpvar escFlag .byte ; 7 bit - Exit game, 6 bit - Exit to GameOver (cleared - exit to Menu), 0 - nothing .zpvar LineYdraw .byte .zpvar LineXdraw .word - .zpvar plot4x4color .byte ; $00 / $ff + .zpvar plot4x4color .byte ; $00 / $ff .zpvar Multiplier .word .zpvar Multiplier_ .byte ; 3 bytes .zpvar HowToDraw .byte @@ -141,7 +143,7 @@ FirstZpageVariable = $57 .zpvar goleft .byte .zpvar OffsetDL1 .byte .zpvar L1 .byte - HotNapalmFlag = FunkyBombCounter ; reuse variable! + HotNapalmFlag = FunkyBombCounter ; reuse variable! ;* RMT ZeroPage addresses in artwork/sfx/rmtplayr.a65 displayposition = modify @@ -150,11 +152,15 @@ FirstZpageVariable = $57 ;----------------------------------------------- ; libraries ;----------------------------------------------- - .IF TARGET = 5200 + .IF TARGET = 800 + icl 'Atari/lib/ATARISYS.ASM' + icl 'Atari/lib/MACRO.ASM' + icl 'artwork/splash_v2/splash.asm' ; splash screen and musix + .ELIF TARGET = 5200 OPT h-f+ ; no headers, single block --> cart bin file - icl 'lib/5200SYS.ASM' - icl 'lib/5200MACRO.ASM' - .enum @kbcode + icl 'Atari/lib/5200SYS.ASM' + icl 'Atari/lib/5200MACRO.ASM' + .enum @kbcode /* _0 _1 @@ -187,25 +193,21 @@ FirstZpageVariable = $57 _del = $fc ;$0c ;not used in 5200 _M = $0d _S = $0e - _atari = $fd ; not used in 5200 + _atari = $fd ; not used in 5200 _none = $0f .ende - .ELSE - icl 'lib/ATARISYS.ASM' - icl 'lib/MACRO.ASM' - icl 'artwork/splash_v2/splash.asm' ; splash screen and musix .ENDIF - + ;----------------------------------------------- ; variable declarations in RAM (no code) ;----------------------------------------------- ORG PMGraph + $0300 - (variablesEnd - OneTimeZeroVariables + 1) icl 'variables.asm' - + ; Game loading address ORG $4000 - + WeaponFont ins 'artwork/weapons_AW6_mod.fnt' ; 'artwork/weapons.fnt' @@ -215,28 +217,28 @@ WeaponFont DisplayCopyRom = * org display, DisplayCopyRom DisplayCopyStart - icl 'display_main_menu.asm' + icl 'Atari/display_main_menu.asm' DisplayCopyEnd org DisplayCopyRom + (DisplayCopyEnd - DisplayCopyStart) - + DisplayCopyPurchaseDlROM = * org DisplayCopyPurchase, DisplayCopyPurchaseDlROM DisplayCopyPurchaseStart - icl 'display_purchasedl.asm' + icl 'Atari/display_purchasedl.asm' DisplayCopyPurchaseEnd org DisplayCopyPurchaseDlROM + (DisplayCopyPurchaseEnd - DisplayCopyPurchaseStart) - + StatusBufferROM = * org StatusBufferCopy, StatusBufferROM StatusBufferCopyStart - icl 'display_status.asm' + icl 'Atari/display_status.asm' StatusBufferCopyEnd org StatusBufferROM + (StatusBufferCopyEnd - StatusBufferCopyStart) - - icl 'display_static.asm' + + icl 'Atari/display_static.asm' ;---------------------------------------------- - + ;-------------------------------------------------- ; Game Code ;-------------------------------------------------- @@ -244,16 +246,11 @@ FirstSTART .IF TARGET = 5200 ; start in 5200 diagnostic mode ; move original startup procedure to RAM + Modified5200Splash = $2100 ; apparently there is some free space here - ; 6502 initialization - ; SEI - ; CLD - ; LDX #$FF - ; TXS - ; check kernel version Atari5200KernelByte = $fff8 - ; $32 - 4 joy + ; $32 - 4 joy ; $00 - 2 joy ; $ff - Altirra kernel @@ -274,103 +271,83 @@ rom2joy @ mwa $fffc temp ; startup proc address mwa #Modified5200Splash temp2 - jsr CopyFromROM + jsr CopyFromROM ; modify the end of the splash procedure lda #$60 ; rts sta (temp2),y - + jsr Modified5200Splash+$0f ; after the diag cart detection ; modify the text splash_text = $3c80 ; '.scorch.supersystem.copyright.19xx.atari' splash_year = splash_text + $1e - splash_copyright = splash_text + $14 - ldy #19 ; 20 characters -@ lda NewSplashText,y - sta splash_copyright,y - dey - bpl @- - + splash_copyright = splash_text + $14 + ldy #19 ; 20 characters +@ lda NewSplashText,y + sta splash_copyright,y + dey + bpl @- + ; splash screen delay. maybe add fire to speed up? @ cpx RTCLOK+1 bne @- -no5200splash +no5200splash .ENDIF - jsr MakeDarkScreen + jsr MakeDarkScreen - ; one time zero variables in RAM (non zero page) - lda #0 - ldy #OneTimeZeroVariablesCount-1 -@ sta OneTimeZeroVariables,y - dey - bpl @- - - ; one time zero variables in RAM (zero page) - ldy #FirstZpageVariable -@ sta $0000,y - iny - bne @- - - ; initialize variables in RAM (non zero page) - ldy #initialvaluesCount-1 -@ lda initialvaluesStart,y - sta variablesToInitialize,y - dey - bpl @- + ; one time zero variables in RAM (non zero page) + lda #0 + ldy #OneTimeZeroVariablesCount-1 +@ sta OneTimeZeroVariables,y + dey + bpl @- - ; set gradient to the full LGBTIQQAAPP+ flag on start - mva #0 GradientNr ; #1 to set gradient number 2 :) (next one) - jsr SelectNextGradient.NotWind - - ; generate linetables - mwa #display temp - mwa #linetableL temp2 - mwa #linetableH modify - ldy #0 -@ lda temp - sta (temp2),y - lda temp+1 - sta (modify),y - adw temp #40 - iny - cpy #screenheight+1 + ; one time zero variables in RAM (zero page) + ldy #FirstZpageVariable +@ sta $0000,y + iny bne @- + ; initialize variables in RAM (non zero page) + ldy #initialvaluesCount-1 +@ lda initialvaluesStart,y + sta variablesToInitialize,y + dey + bpl @- + + ; set gradient to the full LGBTIQQAAPP+ flag on start + mva #0 GradientNr ; #1 to set gradient number 2 :) (next one) + jsr SelectNextGradient.NotWind + + ; generate linetables + jsr GenerateLineTable + .IF TARGET = 800 - -; pokeys init - lda #3 ; stereo - sta POKEY+$0f ; stereo - sta POKEY+$1f ; stereo - - lda PAL - and #%00001110 - bne NoRMT_PALchange - ;it is PAL here - ; Change RMT to PAL version - ; 5 values in RMT file - ; not elegant :( - mva #$06 MODUL-6+$967 ; $07 > $06 - ;mva #$06 MODUL-6+$bc3 ; $07 > $06 - ;mva #$06 MODUL-6+$e69 ; $08 > $06 - ;mva #$06 MODUL-6+$ebc ; $08 > $06 - sta MODUL-6+$bc3 ; $07 > $06 - sta MODUL-6+$e69 ; $08 > $06 - sta MODUL-6+$ebc ; $08 > $06 - mva #$10 MODUL-6+$a69 ; $12 > $10 - mva #$04 MODUL-6+$bf8 ; $05 > $04 - mva #$08 MODUL-6+$e3d ; $0a > $08 - - ; and mountains colors table address - mva #dliColorsFore2PAL GradientAddrH+2 -; mva #$c4 dliColorsFore2+16 -; mva #$c6 dliColorsFore2+17 -; mva #$a4 dliColorsFore2+18 -; mva #$a6 dliColorsFore2+19 -; sta dliColorsFore2+20 + ; pokeys init + lda #3 ; stereo + sta POKEY+$0f ; stereo + sta POKEY+$1f ; stereo + + lda PAL + and #%00001110 + bne NoRMT_PALchange + ;it is PAL here + ; Change RMT to PAL version + ; 5 values in RMT file + ; not elegant :( + mva #$06 MODUL-6+$967 ; $07 > $06 + sta MODUL-6+$bc3 ; $07 > $06 + sta MODUL-6+$e69 ; $08 > $06 + sta MODUL-6+$ebc ; $08 > $06 + mva #$10 MODUL-6+$a69 ; $12 > $10 + mva #$04 MODUL-6+$bf8 ; $05 > $04 + mva #$08 MODUL-6+$e3d ; $0a > $08 + + ; and mountains colors table address + mva #dliColorsFore2PAL GradientAddrH+2 NoRMT_PALchange - .ELSE - mva #$7f SkStatSimulator + .ELIF TARGET = 5200 + mva #$7f SkStatSimulator .ENDIF @@ -388,1160 +365,16 @@ NoRMT_PALchange mva #$04 CONSOL5200 ;Speaker off, Pots enabled, port #1 selected mwa #kb_continue VKEYCNT ;Keyboard handler .ENDIF - VMAIN VBLinterrupt,7 ;jsr SetVBL - - mva #2 chactl ; necessary for 5200 - -START - jsr MakeDarkScreen - ; Startup sequence - jsr Initialize + VMAIN VBLinterrupt,7 ;jsr SetVBL - ;jsr GameOverScreen ; only for test !!! - - RMTSong song_main_menu - - jsr Options ;startup screen - jsr SetVariablesFromOptions - jsr MakeDarkScreen - bit escFlag - bmi START - - jsr EnterPlayerNames - jsr MakeDarkScreen - bit escFlag - bmi START - - jsr RandomizeSequence - ; for the round #1 shooting sequence is random - -MainGameLoop - jsr SetWallsType - ; first set default barrel lengths (fix for Long Schlong activation :) ) - ; we must do it before purchase/activate - ; and set Auto Defense to off - jsr SetStandardBarrels - - jsr CallPurchaseForEveryTank - jsr MakeDarkScreen - bit escFlag - bmi START - - jsr GetRandomWind - - jsr RoundInit - - jsr MainRoundLoop - bit escFlag - bmi START - jvs GoGameOver - - jsr SortSequence - - mva #0 TankNr ; - sta COLBAKS ; set background color to black - sta JoystickNumber ; set joystick port for player - - ; Hide all (easier than hide last ;) ) tanks - jsr cleartanks ; A=0 - - ; here gains and losses should be displayed (dollars) - ; finally we have changed our minds and money of players - ; is displayed only in weapons shop - - ; Results are number of other deaths - ; before the player dies itself - - RmtSong song_round_over - jsr DisplayResults - - jsr DemoModeOrKey - jsr MakeDarkScreen - - ldx NumberOfPlayers - dex -CalculateGains - ; add gains and substract losses - ; gain is what player gets for lost energy of opponents - ; energy lost by opponents is added during Round and - ; little below in source, multiplied by 2 to get "dollars". - ; By analogy, loss is energy that given player losses during - ; each Round. - ; Important! If player has 10 energy and gets a central hit - ; from nuke that would take 90 energy points, his loss - ; is 90, not 10 - - ; adding the remaining energy of the tank to gain - ; winner gets more ! :) - lda Energy,x - adc gainL,x - sta gainL,x - bcc @+ - inc gainH,x -@ - ; add gain * 2 - asl gainL,x - rol gainH,x - clc - lda moneyL,x - adc gainL,x - sta moneyL,x - lda moneyH,x - adc gainH,x - sta moneyH,x - ; substract lose - ; if lose is greater than money then zero money - lda moneyH,x - cmp loseH,x - bcc zeromoney - bne substractlose - lda moneyL,x - cmp loseL,x - bcc zeromoney -substractlose - sec - lda moneyL,x - sbc loseL,x - sta moneyL,x - lda moneyH,x - sbc loseH,x - sta moneyH,x - jmp skipzeroing -zeromoney - lda #0 - sta moneyL,x - sta moneyH,x -skipzeroing -; and earned money for summary - clc - lda EarnedMoneyL,x - adc gainL,x - sta EarnedMoneyL,x - lda EarnedMoneyH,x - adc gainH,x - sta EarnedMoneyH,x - ; substract lose - ; if lose is greater than money then zero money - lda EarnedMoneyH,x - cmp loseH,x - bcc ezeromoney - bne esubstractlose - lda EarnedMoneyL,x - cmp loseL,x - bcc ezeromoney -esubstractlose - sec - lda EarnedMoneyL,x - sbc loseL,x - sta EarnedMoneyL,x - lda EarnedMoneyH,x - sbc loseH,x - sta EarnedMoneyH,x - jmp eskipzeroing -ezeromoney - lda #0 - sta EarnedMoneyL,x - sta EarnedMoneyH,x -eskipzeroing - - dex - jpl CalculateGains - - lda GameIsOver - beq NoGameOverYet -GoGameOver - jsr GameOverScreen - jmp START -NoGameOverYet - inc CurrentRoundNr - mva #sfx_silencer sfx_effect - - jmp MainGameLoop - + mva #2 chactl ; necessary for 5200 ;-------------------------------------------------- -.proc RoundInit -;-------------------------------------------------- -; at the beginning of each Round we set energy -; of all players to 99 -; the maximum shooting energy to 990 (it is 10*energy) -; the default shooting energy to 350 -; the shooting angle is randomized -; of course gains an loses are zeroed - - RmtSong song_ingame - - jsr SetPMWidth ; A=0 - lda #0 - sta AfterBFGflag ; reset BFG flag - sta COLOR2 ; status line "off" - sta COLOR1 - - tax -@ sta singleRoundVars,x - inx - cpx #(singleRoundVarsEnd-singleRoundVars) - bne @- - - ldx #(MaxPlayers-1) -SettingEnergies - lda #$00 - sta gainL,x - sta gainH,x - sta loseL,x - sta loseH,x - lda #99 - sta Energy,x - sta eXistenZ,x - sta LASTeXistenZ,x - ; anything in eXistenZ table means that this tank exist - ; in the given round - lda #<1000 - sta MaxForceTableL,x - lda #>1000 - sta MaxForceTableH,x - lda #<350 - sta ForceTableL,x - lda #>350 - sta ForceTableH,x - - ;lda #(255-45) - ;it does not look good when all tanks have - ;barrels pointing the same direction - ;so it would be nice to have more or less random - ;angles - jsr RandomizeAngle - sta AngleTable,x - - dex - bpl SettingEnergies - -;generating the new landscape - jsr PMoutofScreen ;let P/M disappear - jsr clearscreen ;let the screen be clean - jsr ClearPMmemory - jsr placetanks ;let the tanks be evenly placed - jsr calculatemountains ;let mountains be easy for the eye - ;jsr calculatemountains0 ;only for tests - makes mountains flat and 0 height - - - mwa #StatusBufferROM temp - mwa #StatusBufferCopy temp2 - mwa #StatusBufferCopyEnd+1 modify - jsr CopyFromROM - - jsr SetMainScreen - jsr ColorsOfSprites - - jsr drawmountains ;draw them - jsr drawtanks ;finally draw tanks - - mva #$00 TankSequencePointer - -;---------round screen is ready--------- - mva #TextForegroundColor COLOR1 ; status line "on" - rts -.endp - -;-------------------------------------------------- -.proc MainRoundLoop -; here we must check if by a chance there is only one -; tank with energy greater than 0 left +; Main program of the game + icl 'game.asm' ;-------------------------------------------------- - ldy #0 ; in Y - number of tanks with energy greater than zero - sty ATRACT ; reset atract mode - ldx NumberOfPlayers - dex -CheckingIfRoundIsFinished - lda eXistenZ,x - beq NoEnergy - iny -NoEnergy - dex - bpl CheckingIfRoundIsFinished - cpy #2 ; is it less than 2 tanks have energy >0 ? - bcs DoNotFinishTheRound - -;points for the last living tank - ldx NumberOfPlayers - dex -WhichTankWonLoop - lda eXistenZ,x - bne ThisOneWon - dex - bpl WhichTankWonLoop - ;error was here!!! - ; somehow I believed program will be never here - ; but it was a bad assumption - ; god knows when there is such a situation - ; (we've got a SITUATION here, if you know what I mean) - ; there are two tanks left. - ; one of them is killed by the second tank - ; second tank explodes and kills the first one. - ; and code lands here... - ; looks like no one won! - rts - -ThisOneWon - lda CurrentResult - clc - adc ResultsTable,x - sta ResultsTable,x - - rts ; this Round is finished - -DoNotFinishTheRound - ; Seppuku here - lda noDeathCounter - cmp seppukuVal - bcc @+ - - mva #0 noDeathCounter - mva #sfx_seppuku sfx_effect - - jsr DisplaySeppuku - jmp Seppuku - -@ - ; Auto Defense - activates defensives - ldx NumberOfPlayers - dex -CheckNextTankAD - lda Energy,x ; only active players - beq @+ - lda AutoDefenseFlag,x ; with Auto Defence activated - beq @+ - ; run auto defense for tank in X - jsr AutoDefense -@ dex - bpl CheckNextTankAD - jsr DrawTanks ; redraw tanks with new defences -; - ldx TankSequencePointer - lda TankSequence,x - sta TankNr - tax - lda Energy,x ;skip if no energy - jeq NextPlayerShoots - - - - mva #$ff plot4x4color - jsr DisplayTankNameAbove - - mva #1 color ;to display flying point - - ldx tankNr - lda TankStatusColoursTable,x - sta COLOR2 ; set color of status line - jsr PutTankNameOnScreen - jsr DisplayStatus - - lda SkillTable,x - beq ManualShooting - -RoboTanks - ; robotanks shoot here - ; TankNr still in X - jsr ArtificialIntelligence - ;pause 30 - ldx TankNr - jsr DisplayStatus ; to make visible AI selected defensive (and offensive :) ) - jsr MoveBarrelToNewPosition - lda kbcode - cmp #@kbcode._esc ; 28 ; ESC - bne @+ - jsr AreYouSure -@ lda escFlag - seq:rts ; keys Esc or O - - - jmp AfterManualShooting - -ManualShooting - lda JoyNumber,x - sta JoystickNumber ; set joystick port for player - jsr WaitForKeyRelease - lda #%00000000 - sta TestFlightFlag ; set "Test Fight" off - jsr BeforeFire - lda escFlag - seq:rts ; keys Esc or O - -AfterManualShooting - mva #$00 plot4x4color - jsr DisplayTankNameAbove - ; defensive weapons without flight handling - ldx TankNr - lda ActiveDefenceWeapon,x - cmp #ind_Hovercraft_____ - beq GoFloat - cmp #ind_White_Flag_____ ; White Flag - beq ShootWhiteFlag - cmp #ind_Nuclear_Winter_ - bne StandardShoot -ShootAtomicWinter - ; --- atomic winter --- - jsr AtomicWinter - jmp NextPlayerShoots ; and we skip shoot -ShootWhiteFlag - ; --- white flag --- - jsr WhiteFlag - jmp NextPlayerShoots ; and we skip shoot -GoFloat - jsr TankFlying - lda #0 - sta ActiveDefenceWeapon,x ; deactivate after use - bit escFlag - bpl ManualShooting ; after floating tank can shoot - rts -StandardShoot - inc noDeathCounter - - jsr DecreaseWeaponBeforeShoot - jsr DisplayStatus - -; ldx TankNr - dec Energy,x ; lower energy to eventually let tanks commit suicide - -ShootNow - jsr Shoot - ;here we clear offensive text (after a shoot) - ldy TankNr - mva #$00 plot4x4color - jsr DisplayOffensiveTextNr - - lda HitFlag ;0 if missed - beq missed - - jsr Explosion - -continueMainRoundLoopAfterSeppuku - -AfterExplode - jsr SoilDown2 ; allways -NoFallDown2 - ;here tanks are falling down - mva tankNr tempor2 - ldx NumberOfPlayers - dex -TanksFallDown - stx TankNr - lda eXistenZ,x - beq NoExistNoFall - jsr TankFalls -NoExistNoFall - dex - bpl TanksFallDown - mvx tempor2 TankNr - -missed - ldy WeaponDepleted - bne @+ - ldx TankNr - tya - sta ActiveWeapon,x -@ - - ;here we clear offensive text (after a shoot) - ldy TankNr - mva #$00 plot4x4color - jsr DisplayOffensiveTextNr - -NextPlayerShoots - ;before it shoots, the eXistenZ table must be updated - ;accordingly to actual energy (was forgotten, sorry to ourselves) - - ldx #(MaxPlayers-1) -SeteXistenZ - lda Energy,x - sta eXistenZ,x - - jsr MaxForceCalculate - - dex - bpl SeteXistenZ - - ;was setup of maximum energy for players - - -PlayersAgain - -; In LASTeXistenZ there are values of eXistenZ before shoot -; from the next tank. -; Now it must be checked if by a chance something that had -; LASTeXistenZ>0 is not equal to 0 right now, -; because it means this tank died during this round. -; Most important thing is: -; after each explosion of the tank these operations must be -; performed from the beginning! -; (it is made by another jump into the after explosion routines) -; It is because exploding tank can destroy their neighbours, -; additionally this tank just have had LASTeXistenZ set to 0, -; otherwise it would explode again and again. -; OK, text how to do it is ready, now comes coding . -; Aaaah! - in the main loop we have to set eXistenZ and LASTeXistenZ - - mva #sfx_next_player sfx_effect - - ldx NumberOfPlayers - dex -CheckingPlayersDeath - lda LASTeXistenZ,x - beq NoPlayerNoDeath - lda eXistenZ,x - beq PlayerXdeath -NoPlayerNoDeath - dex - bpl CheckingPlayersDeath - ; if processor is here it means there are no more explosions - - inc:lda TankSequencePointer - cmp NumberOfPlayers - bne NotLastPlayerInRound - mva #0 TankSequencePointer - - lda WindChangeInRound - beq NoWindChangeNow - jsr GetRandomWind ; wind change after each turn (not round only) -NoWindChangeNow -NotLastPlayerInRound - jmp MainRoundLoop -.endp - -;--------------------------------- -.proc PlayerXdeath -; this tank should not explode anymore: -; there is 0 in A, and Tank Number in X, so... -;--------------------------------- - - sta LASTeXistenZ,x - ; save x somewhere - stx TankTempY - - ;clear NoDeathCounter here - sta noDeathCounter - - mva #sfx_death_begin sfx_effect - - ; display defensive text here (well, defensive - ; is not the real meaning, it should be pre-death, - ; but I am too lazy to change names of variables) - - ; in X there is a number of tank that died - - lda #78 ; mumber of defensive text after BFG! ("VERY FUNNY.") - bit AfterBFGflag ; check BFG flag - bmi TextAfterBFG - ; if BFG then no points for dead tanks ... - lda CurrentResult - clc - adc ResultsTable,x - sta ResultsTable,x - ;inc CurrentResult - - ; RandomizeDeffensiveText - randomize talk.NumberOfOffensiveTexts (talk.NumberOfDeffensiveTexts+talk.NumberOfOffensiveTexts-1) -TextAfterBFG - sta TextNumberOff - inc CurrentResult ; ... but increase result of winner (BFG) - ldy TankTempY - mva #$ff plot4x4color - jsr DisplayOffensiveTextNr - ; tank flash - ldy TankTempY - mva TankNr temp2 ; not elegant, and probably unnecessary - sty TankNr - jsr FlashTank ; blinking and pausing (like PAUSE 72 - 18x(2+2) ) - mva temp2 TankNr - - ;Deffensive text cleanup - ;here we clear Deffensive text (after a shoot) - ldy TankTempY - mva #$00 plot4x4color - jsr DisplayOffensiveTextNr - - ; calculate position of the explosion (the post-death one) - ldx TankTempY - clc - lda xtankstableL,x - adc #4 ; more or less in the middle of the tank - sta xdraw - lda xtankstableH,x - adc #0 - sta xdraw+1 - sec - lda ytankstable,x - sbc #4 - sta ydraw - lda #0 - sta ydraw+1 ; there is 0 left in A, so... TODO: bad code above. revisit - - ;cleanup of the soil fall down ranges (left and right) - sta RangeRight - sta RangeRight+1 - mwa #screenwidth RangeLeft - - ; We are randomizing the weapon now. - ; jumping into the middle of the explosion - ; routine -MetodOfDeath - lda random - and #%00011111 ; range 0-31 - cmp #(weaponsOfDeathEnd-weaponsOfDeath) ; we have 20 weapons in table (from 0 to 19) - bcs MetodOfDeath - tay - lda weaponsOfDeath,y - jsr ExplosionDirect - mva #sfx_silencer sfx_effect - - ; Clear current Shooter settings. After that, Shooter will "search" for the target again - ldx NumberOfPlayers - dex -@ lda skillTable,x - cmp #2 ; clear variables only if Shooter - bne NotShooter - lda #0 - sta PreviousAngle,x - sta PreviousEnergyL,x - sta PreviousEnergyH,x -NotShooter - dex - bpl @- - - ; jump to after explosion routines (soil fallout, etc.) - ; After going through these routines we are back - ; to checking if a tank exploded and maybe we have - ; a deadly shot here again. - jmp MainRoundLoop.AfterExplode -.endp - -;-------------------------------------------------- -.proc DecreaseEnergyX -;Decreases energy of player nr X by the value Y -;increases his financial loss -;increases gain of tank TankNr -;-------------------------------------------------- - sty EnergyDecrease - ; Lose increase - lda loseL,x - clc - adc EnergyDecrease - sta loseL,x - lda loseH,x - adc #$00 - sta loseH,x - ; Energy now, not less than 0 - lda Energy,x - cmp EnergyDecrease - bcc ldahashzero - ;sec - sbc EnergyDecrease - bpl NotNegativeEnergy -ldahashzero - lda #0 -NotNegativeEnergy - sta Energy,x - ;now increase the gain of the shooting tank - ldy TankNr - clc - lda gainL,y - adc EnergyDecrease - sta gainL,y - lda gainH,y - adc #$00 - sta gainH,y - rts -.endp - -;-------------------------------------------------- -.proc DecreaseShieldEnergyX -; Decreases energy of shield player nr X by the value Y -; if shield energy is 0 after decrease then in Y we have -; rest of the energy - to decrease tank energy -;-------------------------------------------------- - sty EnergyDecrease - ldy #0 ; if Shield survive then no decrease tank anergy - ; Energy cannot be less than 0 - lda ShieldEnergy,x - cmp EnergyDecrease - bcc UseAllShieldEnergy - ;sec - sbc EnergyDecrease - bpl NotNegativeShieldEnergy ; jump allways -UseAllShieldEnergy - ; now calculate rest of energy for future tank energy decrease - sec - lda EnergyDecrease - sbc ShieldEnergy,x - tay - lda #0 -NotNegativeShieldEnergy - sta ShieldEnergy,x - rts -.endp - -;--------------------------------- -.proc Seppuku -;--------------------------------- - lda #0 - sta ydraw+1 - ; get position of the tank - ldx TankNr -; lda #0 ; turn off defense weapons when hara-kiring - sta ActiveDefenceWeapon,x - sta ShieldEnergy,x - jsr SetupXYdraw - lda #1 ; Missile - jsr ExplosionDirect - jmp MainRoundLoop.continueMainRoundLoopAfterSeppuku -.endp - -;-------------------------------------------------- -.proc GetRandomWind -;in: MaxWind (byte) -;out: Wind (word) -;uses: _ -;-------------------------------------------------- - lda random - cmp MaxWind - bcs GetRandomWind ; if more than MaxWind then randomize again - sta Wind - mva #$00 Wind+1 - sta Wind+2 - sta Wind+3 - ; multiply Wind by 16 - ; two bytes of Wind are treated as a decimal part of vx variable - :4 aslw Wind - ; decide the direction - lda random - and #$01 - beq @+ - sec ; Wind = -Wind - .rept 4 - lda #$00 - sbc Wind+# - sta Wind+# - .endr -@ rts -.endp -;-------------------------------------------------- -.proc MaxForceCalculate -; calculates max force for tank (tanknr in X) -; Energy of tank X in A -;-------------------------------------------------- - sta L1 - - ;DATA L1,L2 - ;Multiplication 8bit*8bit, - ;result 16bit - ;this algiorithm is a little longer than one in Ruszczyc 6502 book - ;but it is faster - - ldy #8 - lda #0 - clc -LP0 ror - ror L1 - bcc B0 - clc - adc #10 ; (L2) multiplication by 10 -B0 dey - bne LP0 - ror - ror L1 - sta MaxForceTableH,x - lda L1 - sta MaxForceTableL,x - rts -.endp - -;-------------------------------------------------- -.proc WeaponCleanup -; cleaning of the weapon possesion tables -; 99 of Baby Missles and White Flags, all other weapons=0) -;-------------------------------------------------- - ldx #(number_of_weapons - 1) -@ lda #$0 - cpx #ind_White_Flag_____ ; White Flag - bne no99 -set99 lda #99 -no99 sta TanksWeapon1,x - sta TanksWeapon2,x - sta TanksWeapon3,x - sta TanksWeapon4,x - sta TanksWeapon5,x - sta TanksWeapon6,x - dex - beq set99 ; Baby Missile (index=0) - bpl @- - rts -.endp - -;-------------------------------------------------- -.proc Initialize -;Initialization sequence -;uses: temp, ... -;-------------------------------------------------- -deletePtr = temp - - ; clean variables - lda #0 - sta escFlag - sta JoystickNumber - tay - mwa #variablesStart deletePtr -@ tya - sta (deletePtr),y - inw deletePtr - cpw deletePtr #variablesEnd - bne @- - - ; ser initial shapes for each tank (tanks 0-5 has shape 0 now) - ldy #1 - sty TankShape+1 - sty TankShape+4 - iny - sty TankShape+2 - sty TankShape+5 - - - mwa #1024 RandBoundaryHigh - mva #$ff LastWeapon - sta HowMuchToFall - mva #1 color - - jsr SetStandardBarrels - jsr WeaponCleanup - - mva #>WeaponFont chbas - - ;parameter for old plot (unPlot) max 5 points - ldx #4 -SetunPlots - lda #display - sta oldplotH,x - lda #0 - sta oldply,x - lda #$ff - sta oldora,x - dex - bpl SetunPlots - - ;setting up P/M graphics - lda #>pmgraph - sta pmbase - lda #$03 ; P/M on - sta GRACTL - jsr SetPMWidth - lda #%00100001 ; P/M priorities (multicolor players on) - prior=1 - sta GPRIOR - jsr PMoutofScreen - - ;let the tanks be visible! - ldx #(maxPlayers-1) - lda #99 ; tank is visible -MakeTanksVisible - sta eXistenZ,x - dex - bpl MakeTanksVisible - - mva #1 CurrentRoundNr ;we start from round 1 - mva #6 NTSCcounter - - rts -.endp -;-------------------------------------------------- -.proc SetStandardBarrels -; set standart barrel length and deactivate Auto Defense -; for all tanks -;-------------------------------------------------- - ldx #maxPlayers-1 -@ lda #StandardBarrel ; standard barrel length - sta BarrelLength,x - lda #$00 ; deactivate Auto Defense - sta AutoDefenseFlag,x - dex - bpl @- - rts -.endp -;---------------------------------------------- -/* .proc RandomizeSequence0 - ldx #0 -@ txa - sta TankSequence,x - inx - cpx #MaxPlayers - bne @- - rts -.endp */ -;-------------------------------------------------- -.proc RandomizeSequence -; in: NumberOfPlayers -; out: TankSequence -; how: get random number lower than NumberOfPlayers -; put it in the first slot. -; get another random number lower than NumberOfPlayers -; check if was previously saved in first slot -; if not then save it in second slot -; repeat untill NumberOfPlayers - - ldx #0 -GetRandomAgain0 - lda RANDOM - and #$07 ;NumberOfPlayers < 7 - cmp NumberOfPlayers - bcs GetRandomAgain0 - sta TankSequence,x - ;now first slot is ready, nexts slots are handled - ;in a more complicated way - -GetRandomAgainX - lda RANDOM - and #$07 ;NumberOfPlayers < 7 - cmp NumberOfPlayers - bcs GetRandomAgainX - - ;now we have to check if the value was not used - ;in previous slots - - stx temp - ldy temp -UsageLoop - cmp TankSequence,y - beq GetRandomAgainX ;apparently we have already used this value - dey - bpl UsageLoop - - ;well, looks like this value is new! - inx - sta TankSequence,x - - stx temp - inc:lda temp ;x+1 - - cmp NumberOfPlayers - bne GetRandomAgainX - rts -.endp -;---------------------------------------------- -.proc RandomizeAngle -; routine returns in A -; a valid angle for the tank's barrel. -; X is not changed -;---------------------------------------------- - - ; lets randomize someting between 0 and 180 - lda RANDOM - cmp #180 - bcs RandomizeAngle - rts -.endp -;---------------------------------------------- -.proc RandomizeForce -; routine returns in ForceTable/L/H -; valid force of shooting for TankNr -; in X must be TankNr -; low and high randomize boundary passed as word value -; RandBoundaryLow -; RandBoundaryHigh -;---------------------------------------------- - - lda RANDOM - sta temp2 - lda RANDOM - and #%00000011 ;(0..1023) - sta temp2+1 - - cpw RandBoundaryLow temp2 - seq:bcs RandomizeForce - - cpw RandBoundaryHigh temp2 - bcc RandomizeForce - - lda temp2 - sta ForceTableL,x - lda temp2+1 - sta ForceTableH,x - -;--------- -LimitForce -; in X must be TankNr -; cuts force to MaxForceTable - lda MaxForceTableH,x - cmp ForceTableH,x - bne @+ - lda MaxForceTableL,x - cmp ForceTableL,x -@ bcs @+ - - lda MaxForceTableL,x - sta ForceTableL,x - lda MaxForceTableH,x - sta ForceTableH,x -@ - rts - -.endp -;---------------------------------------------- -.proc Table2Force -;---------------------------------------------- - lda ForceTableL,x - sta Force - lda ForceTableH,x - sta Force+1 - rts -.endp -;---------------------------------------------- -.proc MoveBarrelToNewPosition -;---------------------------------------------- - mva #1 Erase - jsr DrawTankNr.BarrelChange - mva #0 Erase -MoveBarrel - mva #sfx_set_power_2 sfx_effect - jsr DrawTankNr - jsr DisplayStatus.displayAngle -; ldx TankNr - mva #1 Erase - jsr WaitOneFrame - jsr DrawTankNr.BarrelChange - mva #0 Erase - lda NewAngle - cmp AngleTable,x - beq BarrelPositionIsFine - bcc rotateLeft -rotateRight ; older is lower - inc angleTable,x - jmp MoveBarrel -rotateLeft ; older is bigger - dec angleTable,x - jmp MoveBarrel -BarrelPositionIsFine - jsr DrawTankNr - rts - -.endp - -;---------------------------------------------- -.proc SortSequence ; -;---------------------------------------------- -; here we try to get a sequence of tanks for two -; purposes: -; 1. to make up shooting sequence for the next round (from down to top) -; 2. to display game results more nicely (from top to down) -; -; I think I will go for a stupid bubble sort... -; it is easy to test :) -; -; Results are in ResultsTable, in TankSequence (Sorted Table) we want to -; have numbers of tanks from the worst to the best. -; in other words, if ResultsTable=(5,4,65,23,3,6) -; the TankSequence=(4,1,0,5,3,2) -; let's assume initially the TankSequence=(0,1,2,3,4,5) - - ldx #0 -SequenceStart - txa - sta TankSequence,x - inx - cpx #MaxPlayers - bne SequenceStart - -; we will need a TempResults (TR) table to fiddle with - ldx #0 -movetotemp - lda ResultsTable,x - sta TempResults,x - inx - cpx NumberOfPlayers - bne movetotemp - -; i=0:sortflag=0 -;loop: -; if TR(i) < TX(i+1) then i=i+1: here quit if i=numberofplayers -; or goto loop: -; else -; temp=TR(i): tempo=TankSequence(i) -; TR(i)=TR(i+1): TankSequence(i)=TankSequence(i+1) -; TR(i+1)=temp: TankSequence(i+1)=tempo -; i=i+1 -; sortflag=sortflag+1 -; go loop: -; if sortflag=0 then finished, else repeat... -; -; or something like this :) - ldx NumberOfPlayers - dex - stx temp+1 ; for checking end of the loop only - -Bubble - ldx #0 ;i=x - stx temp2 ; sortflag=temp2 - -BubbleBobble - lda TempResults,x - cmp TempResults+1,x - bcc nextishigher - bne swapvalues -nextisequal - ; if results are equal, check Direct Hits - ldy TankSequence,x - lda DirectHits,y - ldy TankSequence+1,x - cmp DirectHits,y - ; - beq nextishigher ; this is to block hangs when 2 equal values meet - bcc nextishigher - ;here we must swap values - ;because next is smaller than previous -swapvalues - sta temp - lda TempResults+1,x - sta TempResults,x - lda temp - sta TempResults+1,x - ; - lda TankSequence,x - sta temp - lda TankSequence+1,x - sta TankSequence,x - lda temp - sta TankSequence+1,x - inc temp2 -nextishigher - inx - cpx temp+1 ;cpx ^NumberOfPlayers-1 - bne BubbleBobble - - lda temp2 - - bne Bubble - - rts -.endp -;-------------------------------------------------- -.proc SetWallsType -;-------------------------------------------------- - mva #0 WallsType - lda OptionsTable+8 - cmp #4 - beq SetRandomWalls - lsr - ror WallsType - lsr - ror WallsType - rts -SetRandomWalls - lda random - and #%11000000 - sta WallsType - rts -.endp ;-------------------------------------------------- .proc GetKey ; waits for pressing a key and returns pressed value in A @@ -1549,26 +382,26 @@ SetRandomWalls ; result: A=keycode ;-------------------------------------------------- jsr WaitForKeyRelease -@ - .IF TARGET = 800 - lda SKSTAT - cmp #$ff - beq checkJoyGetKey ; key not pressed, check Joy - cmp #$f7 ; SHIFT - beq checkJoyGetKey - .ELSE - lda SkStatSimulator - and #%11111110 - bne checkJoyGetKey ; key not pressed, check Joy - .ENDIF - lda kbcode - cmp #@kbcode._none - beq checkJoyGetKey - and #$3f ;CTRL and SHIFT ellimination - cmp #@kbcode._esc ; 28 ; ESC - bne getkeyend - mvy #$80 escFlag - bne getkeyend +getKeyAfterWait + .IF TARGET = 800 + lda SKSTAT + cmp #$ff + beq checkJoyGetKey ; key not pressed, check Joy + cmp #$f7 ; SHIFT + beq checkJoyGetKey + .ELIF TARGET = 5200 + lda SkStatSimulator + and #%11111110 + bne checkJoyGetKey ; key not pressed, check Joy + .ENDIF + lda kbcode + cmp #@kbcode._none + beq checkJoyGetKey + and #$3f ;CTRL and SHIFT ellimination + cmp #@kbcode._esc ; 28 ; ESC + bne getkeyend + mvy #$80 escFlag + bne getkeyend checkJoyGetKey ;------------JOY------------- @@ -1578,35 +411,35 @@ checkJoyGetKey and #$0f cmp #$0f beq notpressedJoyGetKey - tay + tay lda joyToKeyTable,y bne getkeyend notpressedJoyGetKey - ;fire - lda STRIG0 - beq JoyButton - .IF TARGET = 800 ; Select and Option key only on A800 - bne checkSelectKey + ;fire + lda STRIG0 + beq JoyButton + .IF TARGET = 800 ; Select and Option key only on A800 + bne checkSelectKey checkSelectKey - lda CONSOL - and #%00000010 ; Select - beq SelectPressed - lda CONSOL - and #%00000100 ; Option - .ENDIF - bne @- + lda CONSOL + and #%00000010 ; Select + beq SelectPressed + lda CONSOL + and #%00000100 ; Option + .ENDIF + bne getKeyAfterWait OptionPressed - lda #@kbcode._atari ; Option key - bne getkeyend + lda #@kbcode._atari ; Option key + bne getkeyend SelectPressed - lda #@kbcode._tab ; Select key - bne getkeyend + lda #@kbcode._tab ; Select key + bne getkeyend JoyButton - lda #@kbcode._ret ;Return key + lda #@kbcode._ret ;Return key getkeyend - ldy #0 - sty ATRACT ; reset atract mode + ldy #0 + sty ATRACT ; reset atract mode mvy #sfx_keyclick sfx_effect rts .endp @@ -1614,7 +447,7 @@ getkeyend ;-------------------------------------------------- .proc getkeynowait ;-------------------------------------------------- - jsr WaitForKeyRelease + jsr WaitForKeyRelease lda kbcode and #$3f ;CTRL and SHIFT ellimination rts @@ -1623,10 +456,10 @@ getkeyend ;-------------------------------------------------- .proc WaitForKeyRelease ;-------------------------------------------------- - mva #128-KeyRepeatSpeed pressTimer ; tricky -StillWait - bit pressTimer - bmi KeyReleased + mva #128-KeyRepeatSpeed pressTimer ; tricky +StillWait + bit pressTimer + bmi KeyReleased lda STICK0 and #$0f cmp #$0f @@ -1638,13 +471,13 @@ StillWait cmp #$ff bne StillWait lda CONSOL - and #%00000110 ; Select and Option only + and #%00000110 ; Select and Option only cmp #%00000110 bne StillWait - .ELSE - lda SkStatSimulator - and #%11111110 - beq StillWait + .ELIF TARGET = 5200 + lda SkStatSimulator + and #%11111110 + beq StillWait .ENDIF KeyReleased rts @@ -1653,12 +486,12 @@ KeyReleased .proc IsKeyPressed ; result: A=0 - yes , A>0 - no ;-------------------------------------------------- - lda SKSTAT - and #%00000100 - beq @+ - lda #1 -@ and STRIG0 - rts + lda SKSTAT + and #%00000100 + beq @+ + lda #1 +@ and STRIG0 + rts .endp ;-------------------------------------------------- .proc DemoModeOrKey @@ -1676,8 +509,8 @@ checkForHuman ; if all in skillTable other than 0 then switch to DEMO MODE ; no people, just wait a bit ;pause 150 ldy #75 - jsr PauseYFrames - rts + jmp PauseYFrames + ; rts peopleAreHere jmp getkey ; jsr:rts .endp @@ -1685,17 +518,15 @@ peopleAreHere ;-------------------------------------------------- MakeDarkScreen ;-------------------------------------------------- - jsr PMoutofScreen ; hide P/M - mva #0 dmactls ; dark screen - ; and wait one frame :) + jsr PMoutofScreen ; hide P/M + mva #0 dmactls ; dark screen + ; and wait one frame :) ;-------------------------------------------------- .proc WaitOneFrame ;-------------------------------------------------- - lda CONSOL - and #%00000101 ; Start + Option - sne:mva #$40 escFlag - and #%00000001 ; START KEY - seq:wait ; or waitRTC ? + lda CONSOL + and #%00000001 ; START KEY + seq:wait ; or waitRTC ? rts .endp @@ -1711,21 +542,80 @@ MakeDarkScreen rts .endp +;-------------------------------------------------- +.proc CheckExitKeys +;-------------------------------------------------- +; Checks keyboard and sets appropriate flags for exit procedures +; If START+OPTION is pressed - exit to GameOver screen +; If 'O' key is pressed - displays "Are you sure?" and - exit to GameOver screen +; If 'Esc' key is pressed - displays "Are you sure?" and - exit to Menu screen +; Just setting the right flags!!! + + ; Select and Option + lda CONSOL + and #%00000101 ; Start + Option + beq QuitToGameover + lda SKSTAT + cmp #$ff + jeq nokeys + cmp #$f7 ; SHIFT + jeq nokeys + + lda kbcode + and #%10111111 ; SHIFT elimination + + cmp #@kbcode._O ; $08 ; O + bne CheckEsc + jsr AreYouSure + bit escFlag + bpl nokeys + ;---O pressed-quit game to game over screen--- +QuitToGameover + mva #$C0 escFlag ; bits 7 and 6 set + rts +CheckEsc + cmp #@kbcode._esc ; 28 ; ESC + bne nokeys +DisplayAreYouSure + jsr AreYouSure + ;---esc pressed-quit game--- +nokeys + bit escFlag + rts +; +.endp +;-------------------------------------------------- +.proc ShellDelay +;-------------------------------------------------- + lda CONSOL + and #%00000001 ; START KEY + beq noShellDelay + ldx flyDelay +DelayLoop + lda VCOUNT +@ cmp VCOUNT + beq @- + dex + bne DelayLoop +noShellDelay + rts +.endp + ;-------------------------------------------------- .proc RmtSongSelect ; starting song line 0-255 to A reg ;-------------------------------------------------- - cmp #song_ingame - bne noingame ; noMusic blocks only ingame song + cmp #song_ingame + bne noingame ; noMusic blocks only ingame song bit noMusic spl:lda #song_silencio noingame - mvx #$ff RMT_blocked + mvx #$ff RMT_blocked ldx #MODUL ;hi byte of RMT module to Y reg jsr RASTERMUSICTRACKER ;Init - mva #0 RMT_blocked - rts + mva #0 RMT_blocked + rts .endp ;------------------------------------------------- .proc CopyFromROM @@ -1751,13 +641,14 @@ noingame rts .endp ;-------------------------------------------------- - icl 'interrupts.asm' + icl 'Atari/interrupts.asm' ;---------------------------------------------- icl 'constants.asm' ;---------------------------------------------- - icl 'textproc.asm' + icl 'Atari/textproc.asm' ;---------------------------------------------- icl 'grafproc.asm' + icl 'Atari/gr_basics.asm' ;---------------------------------------------- icl 'weapons.asm' ;---------------------------------------------- @@ -1766,7 +657,7 @@ noingame icl 'artwork/talk.asm' ;---------------------------------------------- TankFont - ins 'artwork/tanksv4.fnt',+0,384 ; 48 characters only + ins 'artwork/tanksv4.fnt',+0,384 ; 48 characters only ;---------------------------------------------- font4x4 ins 'artwork/font4x4s.bmp',+62 @@ -1783,76 +674,78 @@ font4x4 tax @ lda CheatName,y - sec + sec sbc tanksnames,x - cmp #$27 - bne NoCheat + cmp #$27 + bne NoCheat inx dey bpl @- YesCheat - ldx TankNr - lda TanksWeaponsTableL,x - sta temp - lda TanksWeaponsTableH,x - sta temp+1 - lda #99 -@ iny - sta (temp),y - cpy #(number_of_weapons - 1) - bne @- + ldx TankNr + lda TanksWeaponsTableL,x + sta temp + lda TanksWeaponsTableH,x + sta temp+1 + lda #99 +@ iny + sta (temp),y + cpy #(number_of_weapons - 1) + bne @- NoCheat rts .endp CheatName - dta d" 008.T"+$27 + dta d" 008.T"+$27 ;---------------------------------------------- .proc DLIinterruptBFG - pha - lda dliCounter - bne EndofBFGDLI - lda dliColorsFore - bit random - bmi @+ - lda DliColorBack -@ sta COLPF2 - lda dliColorsFore - bit random - bmi @+ - lda DliColorBack -@ sta COLPF1 + pha + lda dliCounter + bne EndofBFGDLI + lda dliColorsFore + bit random + bmi @+ + lda DliColorBack +@ sta COLPF2 + lda dliColorsFore + bit random + bmi @+ + lda DliColorBack +@ sta COLPF1 EndofBFGDLI - inc dliCounter + inc dliCounter pla rti .endp ; ------------------------ .proc BFGblink - SetDLI DLIinterruptBFG ; blinking on - ldy #50 - jsr PauseYFrames - SetDLI DLIinterruptGraph ; blinking off - rts + SetDLI DLIinterruptBFG ; blinking on + ldy #50 + jsr PauseYFrames + SetDLI DLIinterruptGraph ; blinking off + rts .endp ;-------------------------------------------------- .IF * > MODUL-1 - .ECHO * + .ECHO * .ERROR 'Code and data too long' .ENDIF .ECHO "Bytes left: ",$b000-* - - + + org $b000 ;address of RMT module -MODUL +MODUL ;RMT module is standard Atari binary file already ins "artwork/sfx/scorch_str9-NTSC.rmt",+6 ;include music RMT module MODULEND ;---------------------------------------------- icl 'constants_top.asm' ;---------------------------------------------- - + .ECHO "Bytes on top left: ",$bfe8-* ;ROM_SETTINGS-* - .IF target = 5200 + .IF TARGET = 800 + run FirstSTART + .ELIF TARGET = 5200 .IF * > ROM_SETTINGS-1 .ERROR 'Code and RMT song too long to fit in 5200' .ENDIF @@ -1861,6 +754,4 @@ MODULEND .byte " scorch supersystem " ;20 characters title .byte " ", $ff ;$BFFD == $ff means diagnostic cart, no splash screen .word FirstSTART - .ELSE - run FirstSTART .ENDIF diff --git a/scorch.bin b/scorch.bin index 1801e81..a4a315e 100644 Binary files a/scorch.bin and b/scorch.bin differ diff --git a/scorch.xex b/scorch.xex index dd03251..32d514e 100644 Binary files a/scorch.xex and b/scorch.xex differ diff --git a/scorchC64.asm b/scorchC64.asm new file mode 100644 index 0000000..dff3a9e --- /dev/null +++ b/scorchC64.asm @@ -0,0 +1,444 @@ +; @com.wudsn.ide.asm.mainsourcefile=scorch.asm +;C64 8-bit Scorched Earth source code +;--------------------------------------------------- +;by Tomasz 'pecus' Pecko and Pawel 'pirx' Kalinowski +;Warsaw 2000, 2001, 2002, 2003, 2009, 2012, 2013 +;Miami & Warsaw 2022, 2023 + +;--------------------------------------------------- +.def TARGET = 64 ; :) +;--------------------------------------------------- +.def XCORRECTION_FOR_PM = 0 +; if 1 - active x position of tanks correction fo PMG +.def FASTER_GRAF_PROCS = 1 +; if 1 - activates faster graphics routines +; (direct writes to screen memory - C64 only :) ) +;--------------------------------------------------- + + + opt h-f+ + org $801 + org [a($801)],$801 + basic_start(FirstSTART) + + +;--------------------------------------------------- +.macro build + dta d"1.28" ; number of this build (4 bytes) +.endm + +.macro RMTSong + lda #:1 ; do nothing in C64 +.endm + +;--------------------------------------------------- + icl 'definitions.asm' +;--------------------------------------------------- + +FirstZpageVariable = $58 ; $57 + .zpvar DliColorBack .byte = FirstZpageVariable + .zpvar GradientNr .byte + .zpvar GradientColors .word + .zpvar WindChangeInRound .byte ; wind change after each turn (not round only) flag - (0 - round only, >0 - each turn) + .zpvar JoystickNumber .byte + .zpvar LazyFlag .byte ; 7 bit - run Lazy Darwin, 6 bit - run Lazy Boy or Darwin (!) after inventory, 0 - nothing + .zpvar SpyHardFlag .byte ; >$7f - run SpyHard after inventory + .zpvar Vdebug .byte ; "visual debug" flag ($00 - off, $ff - on) + .zpvar xdraw .word ;= $64 ;variable X for plot + .zpvar ydraw .word ;variable Y for plot (like in Atari Basic - Y=0 in upper right corner of the screen) + .zpvar xbyte .word + .zpvar ybyte .word + .zpvar CharCode .byte + .zpvar fontind .word + .zpvar tanknr .byte + .zpvar TankSequencePointer .byte + .zpvar oldplot .word + .zpvar xc .word + .zpvar temp .word ;temporary word for the most embeded loops only + .zpvar temp2 .word ;same as above + .zpvar modify .word ;origially used to replace self-modyfying code + .zpvar tempXROLLER .word ;same as above for XROLLER routine (used also in result display routine) + .zpvar xtempDRAW .word ;same as above for XDRAW routine + .zpvar ytempDRAW .word ;same as above for XDRAW routine + .zpvar tempor2 .word + .zpvar CreditsVScrol .byte + ;--------------temps used in circle routine + .zpvar xi .word ;X (word) in draw routine + .zpvar fx .byte + .zpvar yi .word ;Y (word) in draw routine + .zpvar fy .byte + .zpvar xk .word + .zpvar fs .byte + .zpvar yc .byte ;ycircle - temporary for circle + .zpvar dx .word + .zpvar dy .word + .zpvar dd .word + .zpvar di .word + .zpvar dp .word + ;---------------------------- + .zpvar UnderTank1 .byte + .zpvar UnderTank2 .byte + ;---------------------------- + .zpvar TestFlightFlag .byte ; For AI test flights ($ff - test, $00 - standard shoot flight) + .zpvar weaponPointer .word + .zpvar dliCounter .byte + .zpvar pressTimer .byte + .zpvar NTSCcounter .byte + .zpvar IsEndOfTheFallFlag .byte ; for small speedup ground falling + .zpvar sfx_effect .byte + .zpvar RMT_blocked .byte + .zpvar ScrollFlag .byte + .zpvar SkStatSimulator .byte + .zpvar FloatingAlt .byte ; floating tank altitude + .zpvar OverTankDir .byte ; (0 go right, $ff go left) direction of bypassing tanks on screen + + ; --------------OPTIMIZATION VARIABLES-------------- + .zpvar Force .word + .zpvar Force_ .byte ; Force is 3 bytes long + .zpvar Angle .byte + .zpvar Parachute .byte ; are you insured with parachute? + .zpvar color .byte + .zpvar Erase .byte ; if 1 only mask of the character is printed + ; on the graphics screen. if 0 character is printed normally + .zpvar radius .byte + .zpvar decimal .word + .zpvar NumberOfPlayers .byte ;current number of players (counted from 1) + .zpvar Counter .byte ;temporary Counter for outside loops + .zpvar ExplosionRadius .byte + .zpvar FunkyBombCounter .byte + .zpvar ResultY .byte + .zpvar xcircle .word + .zpvar ycircle .word + .zpvar vy .word + .zpvar vy_ .word ; 4 bytes + .zpvar vx .word + .zpvar vx_ .word ; 4 bytes + .zpvar HitFlag .byte ;$ff when missile hit ground, $00 when no hit, $01-$06 tank index+1 when hit tank + .zpvar PositionOnTheList .byte ; pointer position on the list being displayed + .zpvar XHit .word + .zpvar delta .word + .zpvar HowMuchToFall .byte + .zpvar magic .word + .zpvar xtraj .word + .zpvar xtraj_ .byte ; 3 bytes + .zpvar ytraj .word + .zpvar ytraj_ .byte ; 3 bytes + .zpvar Wind .word + .zpvar Wind_ .word ; 4 bytes + .zpvar RangeLeft .word + .zpvar RangeRight .word + .zpvar NewAngle .byte + .zpvar escFlag .byte ; 7 bit - Exit game, 6 bit - Exit to GameOver (cleared - exit to Menu), 0 - nothing + .zpvar LineYdraw .byte + .zpvar LineXdraw .word + .zpvar plot4x4color .byte ; $00 / $ff + .zpvar Multiplier .word + .zpvar Multiplier_ .byte ; 3 bytes + .zpvar HowToDraw .byte + .zpvar gravity .byte + .zpvar LineLength .word + .zpvar tracerflag .byte + .zpvar isInventory .byte + .zpvar DifficultyLevel .byte + .zpvar goleft .byte + .zpvar OffsetDL1 .byte + .zpvar L1 .byte + HotNapalmFlag = FunkyBombCounter ; reuse variable! + ;* RMT ZeroPage addresses in artwork/sfx/rmtplayr.a65 + + displayposition = modify + LineAddress4x4 = xcircle + +;----------------------------------------------- +; libraries +;----------------------------------------------- + icl 'C64/lib/C64_ATARISYS.ASM' + icl 'C64/lib/C64SYS.ASM' + icl 'C64/lib/MACRO.ASM' + +;----------------------------------------------- +; variable declarations in RAM (no code) +;----------------------------------------------- + + ; Game loading address + ORG $4100 + icl 'variables.asm' + +WeaponFont + ins 'artwork/weapons_AW6_mod.fnt' ; 'artwork/weapons.fnt' + + +;-------------------------------------------------- +; Game Code +;-------------------------------------------------- +FirstSTART + DL = 0 + StatusBufferROM = 0 + ;StatusBufferCopy = 0 + StatusBufferCopyEnd = 0 + TRACKS = 4 + DisplayCopyPurchaseEnd = 0 + DisplayCopyPurchaseStart = 0 + displayC64 = $2000 ; graphics screen memory start + + SEI ; disable IRQ + LDA #$36 + STA $0001 ; Turn Off BASIC ROM + LDA #NMI ; to our routine + STA $0319 ; + LDA #$00 ; stop Timer A + STA $DD0E ; + STA $DD04 ; set Timer A to 0, after starting + STA $DD05 ; NMI will occur immediately + LDA #$81 ; + STA $DD0D ; set Timer A as source for NMI + LDA #$01 ; + STA $DD0E ; start Timer A -> NMI + + ; from here on NMI is disabled + + + jsr MakeDarkScreen + + ; one time zero variables in RAM (non zero page) + lda #0 + ldy #OneTimeZeroVariablesCount-1 +@ sta OneTimeZeroVariables,y + dey + bpl @- + + ; one time zero variables in RAM (zero page) + ldy #FirstZpageVariable +@ sta $0000,y + iny + bne @- + + ; initialize variables in RAM (non zero page) + ldy #initialvaluesCount-1 +@ lda initialvaluesStart,y + sta variablesToInitialize,y + dey + bpl @- + + + ; generate linetables + jsr GenerateLineTable + + + ; Random INIT + InitializeSIDrnd + +;-------------------------------------------------- +; Main program of the game + icl 'game.asm' +;-------------------------------------------------- + + +;-------------------------------------------------- +.proc GetKey +; waits for pressing a key and returns pressed value in A +; when [ESC] is pressed, escFlag is set +; result: A=keycode +;-------------------------------------------------- + jsr WaitForKeyRelease + lda #0 + sta escFlag + lda #$ff + rts +.endp + +;-------------------------------------------------- +.proc getkeynowait +;-------------------------------------------------- + jsr WaitForKeyRelease + lda kbcode + and #$3f ;CTRL and SHIFT ellimination + rts +.endp + +;-------------------------------------------------- +.proc WaitForKeyRelease +;-------------------------------------------------- +StillWait + rts +.endp +;-------------------------------------------------- +.proc IsKeyPressed +; result: A=0 - yes , A>0 - no +;-------------------------------------------------- + lda #1 + rts +.endp +;-------------------------------------------------- +.proc DemoModeOrKey +; Waits for the key pressed if at least one human is playing. +; Otherwise, waits 3 seconds (demo mode). +;-------------------------------------------------- + ;check demo mode + ldx numberOfPlayers + dex +checkForHuman ; if all in skillTable other than 0 then switch to DEMO MODE + lda skillTable,x + beq peopleAreHere + dex + bpl checkForHuman + ; no people, just wait a bit + ;pause 150 + ldy #75 + jmp PauseYFrames + ; rts +peopleAreHere + jmp getkey ; jsr:rts +.endp + +;-------------------------------------------------- +MakeDarkScreen +;-------------------------------------------------- +; mva #0 dmactls ; dark screen + ; and wait one frame :) +;-------------------------------------------------- +.proc WaitOneFrame +;-------------------------------------------------- + wait ; or waitRTC ? + rts +.endp + +;-------------------------------------------------- +.proc PauseYFrames +; Y - number of frames to wait (divided by 2) +; pauses for maximally 510 frames (255 * 2) +;-------------------------------------------------- +@ jsr WaitOneFrame + jsr WaitOneFrame + dey + bne @- + rts +.endp + +;-------------------------------------------------- +.proc CheckExitKeys +;-------------------------------------------------- +; Checks keyboard and sets appropriate flags for exit procedures +; If START+OPTION is pressed - exit to GameOver screen +; If 'O' key is pressed - displays "Are you sure?" and - exit to GameOver screen +; If 'Esc' key is pressed - displays "Are you sure?" and - exit to Menu screen +; Just setting the right flags!!! + + rts +; +.endp +;-------------------------------------------------- +.proc ShellDelay + ldx flyDelay +DelayLoop + lda $d012 +@ cmp $d012 + beq @- + lda $d012 +@ cmp $d012 + beq @- + dex + bne DelayLoop +noShellDelay + rts +.endp +;-------------------------------------------------- +.proc RmtSongSelect +; starting song line 0-255 to A reg +;-------------------------------------------------- + rts +.endp +.proc CopyFromRom + rts +.endp +;-------------------------------------------------- + icl 'C64/interrupts.asm' +;---------------------------------------------- + icl 'constants.asm' +;---------------------------------------------- + icl 'C64/textproc.asm' +;---------------------------------------------- + icl 'grafproc.asm' + icl 'C64/gr_basics.asm' +;---------------------------------------------- + icl 'weapons.asm' +;---------------------------------------------- + icl 'ai.asm' +;---------------------------------------------- + icl 'artwork/talk.asm' +;---------------------------------------------- +TankFont + ins 'artwork/tanksv4.fnt',+0,384 ; 48 characters only +;---------------------------------------------- +font4x4 + ins 'artwork/font4x4s.bmp',+62 +;------------------------------------------------- +.proc CheckTankCheat + ldy #$07 + lda TankNr + asl + asl + asl ; 8 chars per name + tax +@ + lda CheatName,y + sec + sbc tanksnames,x + cmp #$27 + bne NoCheat + inx + dey + bpl @- +YesCheat + ldx TankNr + lda TanksWeaponsTableL,x + sta temp + lda TanksWeaponsTableH,x + sta temp+1 + lda #99 +@ iny + sta (temp),y + cpy #(number_of_weapons - 1) + bne @- +NoCheat + rts +.endp +CheatName + dta d" 008.T"+$27 +;---------------------------------------------- +.proc DLIinterruptBFG + pha + lda dliCounter + bne EndofBFGDLI + lda dliColorsFore + bit random + bmi @+ + lda DliColorBack +@ sta COLPF2 + lda dliColorsFore + bit random + bmi @+ + lda DliColorBack +@ sta COLPF1 +EndofBFGDLI + inc dliCounter + pla + rti +.endp +; ------------------------ +.proc BFGblink +; SetDLI DLIinterruptBFG ; blinking on + ldy #50 + jsr PauseYFrames +; SetDLI DLIinterruptGraph ; blinking off + rts +.endp +;---------------------------------------------- + icl 'constants_top.asm' +;---------------------------------------------- +NMI + INC $D020 ; change border colour, indication for a NMI + RTI ; exit interrupt + ; (not acknowledged!) diff --git a/scorchC64.prg b/scorchC64.prg new file mode 100644 index 0000000..95ab384 Binary files /dev/null and b/scorchC64.prg differ diff --git a/variables.asm b/variables.asm index 933ad6d..9038e5d 100644 --- a/variables.asm +++ b/variables.asm @@ -1,4 +1,4 @@ -; @com.wudsn.ide.asm.mainsourcefile=scorch.asm +; @com.wudsn.ide.asm.mainsourcefile=scorch.asm .IF *>0 ;this is a trick that prevents compiling this file alone ;===================================================== @@ -18,12 +18,12 @@ noMusic .ds 1 ;.by 0 ; 0 - play music, $ff - do not play music noSfx .ds 1 ;.by 0 ; 0 - play SFX, $ff - do not play SFX ;---------------------------------------------------- ; Color table for Game Over Screen (created in a gameover routine) - .ds 1 ;.by $00 ; labels line color + .ds 1 ;.by $00 ; labels line color GameOverColoursTable .ds MaxPlayers; .BYTE $80,$40,$c4,$20,$c0,$e4 ;---------------------------------------------------- TanksNames ; DO NOT ZERO ON GAME RESTART - ticket #24 ;:6 dta d" " - .ds 6*8 + .ds MaxPlayers*8 ;---------------------------------------------------- skilltable ; computer controlled players' skills (1-8), 0 - human (no cleaning, ticket #30) .DS MaxPlayers @@ -55,9 +55,9 @@ StatusBufferCopy variablesStart ; zeroing starts here ;===================================================== ;isInventory .ds 1 ; 0 - purchase, $ff - inventory -;-------------- +;-------------- drawFunction .ds 1 ; 0 - plot, %10000000 - LineLength (N), %01000000 - DrawCheck (V) -;-------------- +;-------------- noDeathCounter .ds 1 ;-------------- OptionsY .ds 1 ;vertical position of cursor on Options screen @@ -102,7 +102,7 @@ ResultsTable ;the results in the gameeeeee .DS MaxPlayers TempResults .DS MaxPlayers -;DirectHitsH ; one byte enough +;DirectHitsH ; one byte enough ; .DS MaxPlayers DirectHits .DS MaxPlayers @@ -125,9 +125,9 @@ BarrelLength ;length of the tank barrel - dont forget to set it to 6 at round st .DS MaxPlayers ActiveWeapon ;number of the selected weapon .DS MaxPlayers -ActiveDefenceWeapon ;number of the activated defence weapon - 0 +ActiveDefenceWeapon ;number of the activated defence weapon - 0 .DS MaxPlayers -AutoDefenseFlag ; 0 - not activated, >$7f - activated +AutoDefenseFlag ; 0 - not activated, >$7f - activated .DS MaxPlayers WeaponDepleted .DS 1 ; if 0 deactivate the weapon and switch to Baby Missile ;---------------------------------------------------- @@ -149,7 +149,7 @@ WindOrientation .DS 1 ;(0-right,1-left) ;---------------------------------------------------- ;Counter .DS 1 ;temporary Counter for outside loops ;HitFlag .DS 1 ;$ff when missile hit ground, $00 when no hit, $01-$06 tank index+1 when hit tank -WallsType .ds 1 ; bits 6 and 7: 00 - none, 01 - bump, 10 - wrap, 11 - boxy +WallsType .ds 1 ; bits 6 and 7: 00 - none, 01 - bump, 10 - wrap, 11 - boxy ;---------------------------------------------------- xtankstableL ;X positions of tanks (lower left point) .DS MaxPlayers @@ -159,15 +159,15 @@ ytankstable ;Y positions of tanks (lower left point) .DS MaxPlayers LowResDistances ; coarse tank positions divided by 4 (to be in just one byte) .DS MaxPlayers -JoyNumber ; Joystick port number (from 0 to 3) - .DS MaxPlayers -TankShape ; Tank shape number (from 0 to 2) - .DS MaxPlayers +JoyNumber ; Joystick port number (from 0 to 3) + .DS MaxPlayers +TankShape ; Tank shape number (from 0 to 2) + .DS MaxPlayers ;---------------------------------------------------- -TargetTankNr ; Target tank index (for AI routines) - .DS 1 -SecondTryFlag ; For precise AI aiming - .DS 1 +TargetTankNr ; Target tank index (for AI routines) + .DS 1 +SecondTryFlag ; For precise AI aiming + .DS 1 ;---------------------------------------------------- ;Erase .DS 1 ; if 1 only mask of the character is printed ; on the graphics screen. if 0 character is printed normally @@ -218,8 +218,8 @@ FallingSoundBit .DS 1 PreviousFall .DS 1 EndOfTheFallFlag .DS 1 ; in case of the infinite fall ;Parachute .DS 1 ; are you insured with parachute? -;FloatingAlt .DS 1 ; floating tank altitude -FunkyWallFlag = FloatingAlt ; reuse this variable in different weapon (Funky Bomb)! +;FloatingAlt .DS 1 ; floating tank altitude +FunkyWallFlag = FloatingAlt ; reuse this variable in different weapon (Funky Bomb)! PreferHumansFlag = FloatingAlt ; second reuse in AI Aim proc ;---------------------------------------------------- ;Flight @@ -235,7 +235,7 @@ MirvDown .DS [5] ; is given missile down? MirvMissileCounter .DS 1 ; missile Counter (mainly for X) SmokeTracerFlag .DS 1 ; if Smoketracer LaserFlag .DS 1 ; $ff if Laser -XposFlag .DS 1 ; bullet positon X (0 - on screen , %1000000 - off-screen) +XposFlag .DS 1 ; bullet positon X (0 - on screen , %1000000 - off-screen) YposFlag .DS 1 ; bullet positon Y (0 - on screen , %1000000 - over the screen , %0100000 - under the screen) ;---------------------------------------------------- ;CheckCollisionWithTank @@ -287,9 +287,9 @@ AfterBFGflag .DS 1 ; tables with indexes of weapons on the right lists ; OK (2022) so, L1 is list of offensive weapons, L2 - defensive IndexesOfWeaponsL1 - .ds (last_offensive_____ - first_offensive____+1) + .ds (last_offensive - first_offensive +1) IndexesOfWeaponsL2 - .ds (last_defensive_____ - first_defensive____+1) + .ds (last_defensive - first_defensive +1) ;---------------------------------------------------- ; variables storing amount of weapons on the first and second @@ -301,7 +301,7 @@ HowManyOnTheListDef .DS 1 ;PositionOnTheList ; pointer position on the list being displayed ; .DS 1 -LastWeapon +LastWeapon ; number of the last previously purchased weapon ; it is necessary when after purchase some weapon ; is removed from the list (because too expensive) @@ -341,19 +341,10 @@ LaserCoordinate .DS 8 ; 2,2,2,2 ; Let 0 be "baby missile" ; from $30 the defensive weapons begin TanksWeapons -TanksWeapon1 +.REPT MaxPlayers, #+1 +TanksWeapon:1 .DS number_of_weapons -TanksWeapon2 - .DS number_of_weapons -TanksWeapon3 - .DS number_of_weapons -TanksWeapon4 - .DS number_of_weapons -TanksWeapon5 - .DS number_of_weapons -TanksWeapon6 - .DS number_of_weapons - +.ENDR mountaintable ;table of mountains (size=screenwidth) .DS [screenwidth] .DS 1 ; additional byte for fallout (sometimes 1 pixel) @@ -370,9 +361,9 @@ TankTempY ;-------------- single round variables -------------- ;---------------------------------------------------- singleRoundVars -;-------------- +;-------------- ;escFlag .ds 1 ; 0 - Esc or O not pressed, $80 - Esc pressed, $40 - O pressed -;-------------- +;-------------- CurrentResult .DS 1 ;-------------- diff --git a/weapons.asm b/weapons.asm index e5f186e..38d2c7b 100644 --- a/weapons.asm +++ b/weapons.asm @@ -1,4 +1,4 @@ -; @com.wudsn.ide.asm.mainsourcefile=scorch.asm +; @com.wudsn.ide.asm.mainsourcefile=scorch.asm .IF *>0 ;this is a trick that prevents compiling this file alone ;-------------------------------------------------- @@ -8,7 +8,7 @@ ; ActiveWeapon(TankNr) - weapon that tank fires ;-------------------------------------------------- ;cleanup of the soil fall down ranges (left and right) - jsr ClearScreenSoilRange + jsr ClearScreenSoilRange ldx TankNr lda ActiveWeapon,x @@ -22,96 +22,96 @@ pha rts ExplosionRoutines - .word babymissile-1 ;Baby_Missile___;_00 - .word missile-1 ;Missile________;_01 - .word babynuke-1 ;Baby_Nuke______;_02 - .word nuke-1 ;Nuke___________;_03 - .word leapfrog-1 ;LeapFrog_______;_04 - .word funkybomb-1 ;Funky_Bomb_____;_05 - .word mirv-1 ;MIRV___________;_06 - .word deathshead-1 ;Death_s_Head___;_07 - .word napalm-1 ;Napalm_________;_08 - .word hotnapalm-1 ;Hot_Napalm_____;_09 - .word tracer-1 ;Tracer_________;_10 - .word tracer-1 ;Smoke_Tracer___;_11 - .word babyroller-1 ;Baby_Roller____;_12 - .word roller-1 ;Roller_________;_13 - .word heavyroller-1 ;Heavy_Roller___;_14 - .word riotcharge-1 ;Riot_Charge____;_15 - .word riotblast-1 ;Riot_Blast_____;_16 - .word riotbomb-1 ;Riot_Bomb______;_17 + .word babymissile-1 ;Baby_Missile ;_00 + .word missile-1 ;Missile ;_01 + .word babynuke-1 ;Baby_Nuke ;_02 + .word nuke-1 ;Nuke ;_03 + .word leapfrog-1 ;LeapFrog ;_04 + .word funkybomb-1 ;Funky_Bomb ;_05 + .word mirv-1 ;MIRV ;_06 + .word deathshead-1 ;Death_s_Head ;_07 + .word napalm-1 ;Napalm ;_08 + .word hotnapalm-1 ;Hot_Napalm ;_09 + .word tracer-1 ;Tracer ;_10 + .word tracer-1 ;Smoke_Tracer ;_11 + .word babyroller-1 ;Baby_Roller ;_12 + .word roller-1 ;Roller ;_13 + .word heavyroller-1 ;Heavy_Roller ;_14 + .word riotcharge-1 ;Riot_Charge ;_15 + .word riotblast-1 ;Riot_Blast ;_16 + .word riotbomb-1 ;Riot_Bomb ;_17 .word heavyriotbomb-1 ;Heavy_Riot_Bomb;_18 - .word babydigger-1 ;Baby_Digger____;_19 - .word digger-1 ;Digger_________;_20 - .word heavydigger-1 ;Heavy_Digger___;_21 - .word babysandhog-1 ;Baby_Sandhog___;_22 - .word sandhog-1 ;Sandhog________;_23 - .word heavysandhog-1 ;Heavy_Sandhog__;_24 - .word dirtclod-1 ;Dirt_Clod______;_25 - .word dirtball-1 ;Dirt_Ball______;_26 - .word tonofdirt-1 ;Ton_of_Dirt____;_27 - .word liquiddirt-1 ;Liquid_Dirt____;_28 - .word dirtcharge-1 ;Dirt_Charge____;_29 - .word BFG-1 ;Buy_me_________;_30 - .word laser-1 ;Laser__________;_31 + .word babydigger-1 ;Baby_Digger ;_19 + .word digger-1 ;Digger ;_20 + .word heavydigger-1 ;Heavy_Digger ;_21 + .word babysandhog-1 ;Baby_Sandhog ;_22 + .word sandhog-1 ;Sandhog ;_23 + .word heavysandhog-1 ;Heavy_Sandhog ;_24 + .word dirtclod-1 ;Dirt_Clod ;_25 + .word dirtball-1 ;Dirt_Ball ;_26 + .word tonofdirt-1 ;Ton_of_Dirt ;_27 + .word liquiddirt-1 ;Liquid_Dirt ;_28 + .word dirtcharge-1 ;Dirt_Charge ;_29 + .word BFG-1 ;Buy_me ;_30 + .word laser-1 ;Laser ;_31 VOID tracer rts .endp .proc BFG - mva #sfx_plasma_2_2 sfx_effect - jsr BFGblink - ; Kill all :) + mva #sfx_plasma_2_2 sfx_effect + jsr BFGblink + ; Kill all :) ldx NumberOfPlayers dex - lda #$00 + lda #$00 CheckNextTankBFG - cpx TankNr ; not me! - beq @+ + cpx TankNr ; not me! + beq @+ sta Energy,x @ dex bpl CheckNextTankBFG - stx AfterBFGflag ; $ff - rts + stx AfterBFGflag ; $ff + rts .endp ; ------------------------ .proc babymissile mva #11 ExplosionRadius GoBabyMissileSFX - mva #sfx_baby_missile sfx_effect + mva #sfx_baby_missile sfx_effect GoXmissile jmp xmissile .endp ; ------------------------ .proc missile ; mva #17 ExplosionRadius - bne babymissile.GoBabyMissileSFX + bne babymissile.GoBabyMissileSFX ; jmp xmissile .endp ; ------------------------ .proc babynuke mva #25 ExplosionRadius GoBabyNukeSFX - mva #sfx_nuke sfx_effect ; allways <>0 - bne babymissile.GoXmissile + mva #sfx_nuke sfx_effect ; allways <>0 + bne babymissile.GoXmissile ; jmp xmissile .endp ; ------------------------ .proc nuke mva #30 ExplosionRadius - bne babynuke.GoBabyNukeSFX + bne babynuke.GoBabyNukeSFX ; jmp xmissile .endp ; ------------------------ .proc leapfrog mva #17 ExplosionRadius -; mva #sfx_baby_missile sfx_effect +; mva #sfx_baby_missile sfx_effect ; jsr xmissile jsr babymissile.GoBabyMissileSFX - jsr SecondRepeat - + jsr SecondRepeat + SecondRepeat ; soil must fall down now! there is no other way... ; hide tanks or they fall down with soil @@ -126,7 +126,7 @@ SecondRepeat ror Force mva LeapFrogAngle Angle mva #sfx_funky_hit sfx_effect - sbw ytraj+1 #$05 ; next missiles start point goes 5 pixel UP to prevent multiple explosion at one point if tank is hit (4 pixels tank height + 1) + sbw ytraj+1 #$05 ; next missiles start point goes 5 pixel UP to prevent multiple explosion at one point if tank is hit (4 pixels tank height + 1) jsr Flight lda HitFlag beq EndOfLeapping @@ -145,17 +145,17 @@ EndOfLeapping .proc funkybomb ; mva #sfx_baby_missile sfx_effect mwa xtraj+1 xtrajfb - sbw ytraj+1 #$05 ytrajfb ; funky missiles start point goes 5 pixel UP to prevent multiple explosion at one point if tank is hit (4 pixels tank height + 1) + sbw ytraj+1 #$05 ytrajfb ; funky missiles start point goes 5 pixel UP to prevent multiple explosion at one point if tank is hit (4 pixels tank height + 1) ;central Explosion mva #21 ExplosionRadius jsr CalculateExplosionRange0 jsr xmissile.NoRangeCalc - + jsr SoilDown2 ; - jsr cleartanks ; maybe not? - mva #1 color - mva #0 FunkyWallFlag + jsr cleartanks ; maybe not? + mva #1 color + mva #0 FunkyWallFlag mva #5 FunkyBombCounter FunkyBombLoop mva #1 tracerflag @@ -174,19 +174,19 @@ FunkyBombLoop mwa ytrajfb ytraj+1 mva #sfx_funky_hit sfx_effect jsr Flight - mva #0 ExplosionRadius ; if no explosion (off screen) - ; if xdraw if over range then fix it - lda xdraw+1 - bpl NoOnLeftEdge - lda #0 - sta xdraw - sta xdraw+1 + mva #0 ExplosionRadius ; if no explosion (off screen) + ; if xdraw if over range then fix it + lda xdraw+1 + bpl NoOnLeftEdge + lda #0 + sta xdraw + sta xdraw+1 NoOnLeftEdge - cpw xdraw #screenwidth - bcc NoOnRightEdge - mwa #screenwidth xdraw + cpw xdraw #screenwidth + bcc NoOnRightEdge + mwa #screenwidth xdraw NoOnRightEdge - jsr CalculateExplosionRange ; add end of flight coordinates to soildown range + jsr CalculateExplosionRange ; add end of flight coordinates to soildown range lda HitFlag beq NoExplosionInFunkyBomb mva #sfx_baby_missile sfx_effect @@ -196,9 +196,9 @@ NoExplosionInFunkyBomb dec FunkyBombCounter bne FunkyBombLoop mva #0 tracerflag - lda FunkyWallFlag - beq NoWallsInFunky - jsr SetFullScreenSoilRange + lda FunkyWallFlag + beq NoWallsInFunky + jsr SetFullScreenSoilRange NoWallsInFunky rts .endp @@ -208,10 +208,10 @@ NoWallsInFunky mva #sfx_nuke sfx_effect jsr GoXmissileWithSaveXYdraw sbw xdraw #34 - mva #sfx_nuke sfx_effect + mva #sfx_nuke sfx_effect jsr GoXmissileWithSaveXYdraw adw xdraw #68 - mva #sfx_nuke sfx_effect + mva #sfx_nuke sfx_effect jsr GoXmissileWithSaveXYdraw sbw xdraw #34 ; @@ -219,14 +219,14 @@ NoWallsInFunky ;jsr CalculateExplosionRange cpw ydraw #screenHeight bcs NoUpperCircle - mva #sfx_nuke sfx_effect + mva #sfx_nuke sfx_effect jsr GoXmissileWithSaveXYdraw NoUpperCircle adw ydraw #68 ;jsr CalculateExplosionRange cpw ydraw #screenHeight bcs NoLowerCircle - mva #sfx_nuke sfx_effect + mva #sfx_nuke sfx_effect jsr GoXmissileWithSaveXYdraw NoLowerCircle mva #sfx_silencer sfx_effect @@ -242,121 +242,121 @@ GoXmissileWithSaveXYdraw .endp ; ------------------------ .proc napalm - mva #0 HotNapalmFlag ; in this weapon - flag: 0 - napalm, 1 - hotnapalm - beq xnapalm + mva #0 HotNapalmFlag ; in this weapon - flag: 0 - napalm, 1 - hotnapalm + beq xnapalm .endp ; ------------------------ .proc hotnapalm - mva #1 HotNapalmFlag ; in this weapon - flag: 0 - napalm, 1 - hotnapalm -; jmp xnapalm + mva #1 HotNapalmFlag ; in this weapon - flag: 0 - napalm, 1 - hotnapalm +; jmp xnapalm .endp ; ------------------------ .proc xnapalm mva #sfx_napalm sfx_effect - mva #(napalmRadius+4) ExplosionRadius ; real radius + 4 pixels (half characrer width) + mva #(napalmRadius+4) ExplosionRadius ; real radius + 4 pixels (half characrer width) jsr CalculateExplosionRange - ; - mwa xdraw xcircle ; store hitpoint for future repeats - ldy #30 ; repeat 30 times - sty magic -RepeatNapalm ; external loop (for fire animation) - mwa xcircle xdraw - sbw xdraw #(napalmRadius) ; 10 pixels on left side hit point - ldy #0 - sty magic+1 -RepeatFlame ; internal loop (draw flames) - ldy #0 - adw xdraw #mountaintable temp - sty ydraw+1 - lda (temp),y - sec - sbc #1 ; over ground - sta ydraw - lda xdraw - and HotNapalmFlag ; if hotnapalm and x is odd: - :2 asl ; modify y position 4 pixels up - ldy ydraw - sta ydraw - tya - sec - sbc ydraw - sta ydraw - sbw xdraw #4 ; half character correction - ; draw flame symbol - lda magic ; if last repeat - clear flames - beq LastNapalmRepeat - lda random - and #%00000110 - clc - adc #char_flame___________ - bne PutFlameChar + ; + mwa xdraw xcircle ; store hitpoint for future repeats + ldy #30 ; repeat 30 times + sty magic +RepeatNapalm ; external loop (for fire animation) + mwa xcircle xdraw + sbw xdraw #(napalmRadius) ; 10 pixels on left side hit point + ldy #0 + sty magic+1 +RepeatFlame ; internal loop (draw flames) + ldy #0 + adw xdraw #mountaintable temp + sty ydraw+1 + lda (temp),y + sec + sbc #1 ; over ground + sta ydraw + lda xdraw + and HotNapalmFlag ; if hotnapalm and x is odd: + :2 asl ; modify y position 4 pixels up + ldy ydraw + sta ydraw + tya + sec + sbc ydraw + sta ydraw + sbw xdraw #4 ; half character correction + ; draw flame symbol + lda magic ; if last repeat - clear flames + beq LastNapalmRepeat + lda random + and #%00000110 + clc + adc #char_flame + bne PutFlameChar LastNapalmRepeat - lda #char_clear_flame_____ ; clear flame symbol + lda #char_clear_flame ; clear flame symbol PutFlameChar - sta CharCode - ; check coordinates - cpw xdraw #(screenwidth-7) - bcs CharOffTheScreen - lda ydraw - cmp #7 - bcc CharOffTheScreen - cmp #(screenHeight-1) - bcs CharOffTheScreen - jsr TypeChar + sta CharCode + ; check coordinates + cpw xdraw #(screenwidth-7) + bcs CharOffTheScreen + lda ydraw + cmp #7 + bcc CharOffTheScreen + cmp #(screenHeight-1) + bcs CharOffTheScreen + jsr TypeChar CharOffTheScreen - adw xdraw #4 ; reverse half character correction (we need positon of character center) - adw xdraw #1 ; next char 1 pixels to right - inc magic+1 - lda magic+1 - cmp #(2*napalmRadius+1) ; 10 pixels on left, 10 pixels on right and 1 in center - jne RepeatFlame - dec magic - jpl RepeatNapalm - ; after napalm + adw xdraw #4 ; reverse half character correction (we need positon of character center) + adw xdraw #1 ; next char 1 pixels to right + inc magic+1 + lda magic+1 + cmp #(2*napalmRadius+1) ; 10 pixels on left, 10 pixels on right and 1 in center + jne RepeatFlame + dec magic + jpl RepeatNapalm + ; after napalm ;now we must check tanks in range ldx NumberOfPlayers - dex + dex BurnedCheckLoop lda eXistenZ,x beq EndNurnedCheckLoop ;here the tank exist - ; calculate right edge of the fire - adw xcircle #(napalmRadius+4+4) xdraw ; 10 pixels on right side hit point + half character width + correction - ; now we compare tank position with right edge of the fire (napalm) + ; calculate right edge of the fire + adw xcircle #(napalmRadius+4+4) xdraw ; 10 pixels on right side hit point + half character width + correction + ; now we compare tank position with right edge of the fire (napalm) lda XtankstableH,x - cmp xdraw+1 - bne @+ + cmp xdraw+1 + bne @+ lda XtankstableL,x - cmp xdraw + cmp xdraw @ - bcs TankOutOfFire - ; let's calculate left edge of the fire - sbw xcircle #(napalmRadius+TankWidth+4-4) xdraw ; 10 pixels on left + character width (tank) + half character - correction - bpl @+ - mwa #0 xdraw ; left screen edge + bcs TankOutOfFire + ; let's calculate left edge of the fire + sbw xcircle #(napalmRadius+TankWidth+4-4) xdraw ; 10 pixels on left + character width (tank) + half character - correction + bpl @+ + mwa #0 xdraw ; left screen edge @ - ; now we compare tank position with left edge of the fire (napalm) + ; now we compare tank position with left edge of the fire (napalm) lda XtankstableH,x - cmp xdraw+1 - bne @+ + cmp xdraw+1 + bne @+ lda XtankstableL,x - cmp xdraw + cmp xdraw @ - bcc TankOutOfFire + bcc TankOutOfFire - ldy #40 ; energy decrease (napalm) - but if hotnapalm: - lda HotNapalmFlag - beq NotHot - ldy #80 ; energy decrease (hotnapalm) + ldy #40 ; energy decrease (napalm) - but if hotnapalm: + lda HotNapalmFlag + beq NotHot + ldy #80 ; energy decrease (hotnapalm) NotHot - ; check shields ( joke :) ) + ; check shields ( joke :) ) jsr DecreaseEnergyX TankOutOfFire EndNurnedCheckLoop dex bpl BurnedCheckLoop mva #sfx_silencer sfx_effect - rts + rts .endp ; ------------------------ .proc babyroller @@ -367,13 +367,13 @@ GoRoller ; ------------------------ .proc roller ; mva #21 ExplosionRadius - bne babyroller.GoRoller ; 1 byte saved + bne babyroller.GoRoller ; 1 byte saved ; jmp xroller .endp ; ------------------------ .proc heavyroller mva #30 ExplosionRadius - bne babyroller.GoRoller ; 1 byte saved + bne babyroller.GoRoller ; 1 byte saved ; jmp xroller .endp ; ------------------------ @@ -386,7 +386,7 @@ GoRiotBomb ; ------------------------ .proc heavyriotbomb mva #29 ExplosionRadius - bne riotbomb.GoRiotBomb ; 4 bytes saved - optimization :) + bne riotbomb.GoRiotBomb ; 4 bytes saved - optimization :) ; jsr CalculateExplosionRange ; jmp xriotbomb .endp @@ -394,7 +394,7 @@ GoRiotBomb .proc babydigger mva #1 diggery ; how many branches (-1) GoBabydiggerSFX - mva #sfx_digger sfx_effect + mva #sfx_digger sfx_effect mva #0 sandhogflag mva #13 DigLong bne xdigger @@ -536,7 +536,7 @@ DiggerCharacter lda random and #$06 clc - adc #char_digger__________ + adc #char_digger adc sandhogflag sta CharCode cpw xdraw #(screenwidth-6) @@ -606,20 +606,20 @@ dirtLoop ; ------------------------ .proc liquiddirt mva #sfx_liquid_dirt sfx_effect - mwa #510 FillCounter + mwa #510 FillCounter ; ----- - mwa xdraw TempXfill + mwa xdraw TempXfill RepeatFill - mwa TempXfill xdraw - jsr checkRollDirection - ; HowMuchToFall - direction + mwa TempXfill xdraw + jsr checkRollDirection + ; HowMuchToFall - direction ; $FF - we are in a hole (flying in missile direction) ; 1 - right, 2 - left adw xdraw #mountaintable tempXROLLER ldy #0 lda (tempXROLLER),y sta HeightRol ; relative point - + RollinContinuesLiquid ; new point is set adw xdraw #mountaintable tempXROLLER @@ -638,10 +638,10 @@ UpNotYet2 cmp #1 beq HowMuchToFallRight3 .NOWARN dew xdraw - lda xdraw - and xdraw+1 - cmp #$ff ; like cpw xdraw #$ffff - ;ora xdraw+1 ; like cpw xdraw #$0000 + lda xdraw + and xdraw+1 + cmp #$ff ; like cpw xdraw #$ffff + ;ora xdraw+1 ; like cpw xdraw #$0000 jne RollinContinuesLiquid beq FillNow HowMuchToFallRight3 @@ -651,29 +651,29 @@ HowMuchToFallRight3 FillNow ; finally one pixel more ldy #0 - lda HowMuchToFall - bmi FillHole - cmp #1 - beq FillLeft - inw xdraw - inw xdraw ; tricky but we must rollback xdraw in proper direction + lda HowMuchToFall + bmi FillHole + cmp #1 + beq FillLeft + inw xdraw + inw xdraw ; tricky but we must rollback xdraw in proper direction FillLeft -.nowarn dew xdraw +.nowarn dew xdraw FillHole adw xdraw #mountaintable tempXROLLER - lda (tempXROLLER),y - sta ydraw - beq ToHighFill ; if we filled all playfield (very rare but possible) - dec ydraw ; one pixel up - lda ydraw - sta (tempXROLLER),y ;mountaintable update - mva #1 color - jsr plot.MakePlot + lda (tempXROLLER),y + sta ydraw + beq ToHighFill ; if we filled all playfield (very rare but possible) + dec ydraw ; one pixel up + lda ydraw + sta (tempXROLLER),y ;mountaintable update + mva #1 color + jsr plot.MakePlot ToHighFill .nowarn dew FillCounter - lda FillCounter - ora FillCounter+1 - jne RepeatFill + lda FillCounter + ora FillCounter+1 + jne RepeatFill rts .endp ; ------------------------ @@ -684,46 +684,46 @@ ToHighFill ldx TankNr lda AngleTable,x tay - + mwa EndOfTheBarrelX xbyte mva EndOfTheBarrelY ybyte mva #0 ybyte+1 - sta LaserFlag ; turn on gravity and wind after shot :) - + sta LaserFlag ; turn on gravity and wind after shot :) + mwa xdraw LaserCoordinate mwa ydraw LaserCoordinate+2 mwa xbyte LaserCoordinate+4 mwa ybyte LaserCoordinate+6 mva #sfx_lightning sfx_effect - + mva #%10000000 drawFunction ;the above switches Draw to measuring length jsr draw mva #0 drawFunction - lsr LineLength+1 ; LineLength / 8 - ror LineLength - lsr LineLength ; max line lenght is about 380 (9 bits) - lsr LineLength - sec - lda #60 - sbc LineLength - sta yc ; laser blink counter 60-(LineLength/8) + lsr LineLength+1 ; LineLength / 8 + ror LineLength + lsr LineLength ; max line lenght is about 380 (9 bits) + lsr LineLength + sec + lda #60 + sbc LineLength + sta yc ; laser blink counter 60-(LineLength/8) @ lda yc - and #$01 - eor #$01 + and #$01 + eor #$01 sta color mwa LaserCoordinate xdraw mwa LaserCoordinate+2 ydraw mwa LaserCoordinate+4 xbyte mwa LaserCoordinate+6 ybyte - mva #sfx_lightning sfx_effect + mva #sfx_lightning sfx_effect jsr draw dec yc bne @- - + mva #1 color mwa LaserCoordinate xdraw mwa LaserCoordinate+2 ydraw @@ -764,7 +764,7 @@ ExplosionLoop2 bcc ExplosionLoop2 mva #1 color - + ;check tanks' distance from the centre of the explosion mva #%10000000 drawFunction @@ -775,7 +775,7 @@ ExplosionLoop2 ;calculation ldx NumberOfPlayers - dex + dex DistanceCheckLoop lda eXistenZ,x jeq EndOfDistanceCheckLoop @@ -811,42 +811,40 @@ DistanceCheckLoop adc #1 :3 asl tay - ; check shields - lda ActiveDefenceWeapon,x - cmp #ind_Shield_________ ; one hit shield - beq UseShield - cmp #ind_Force_Shield___ ; shield with energy and parachute - beq UseShieldWithEnergy - cmp #ind_Heavy_Shield___ ; shield with energy - beq UseShieldWithEnergy - cmp #ind_Bouncy_Castle__ ; Auto Defence (it works only if hit ground next to tank. Tank hit is handled in Flight proc) - beq UseShieldWithEnergy - cmp #ind_Mag_Deflector__ ; Mag deflector (it works only if hit ground next to tank. Tank hit is handled in Flight proc) - beq UseShieldWithEnergy + ; check shields + lda ActiveDefenceWeapon,x + cmp #ind_Shield ; one hit shield + beq UseShield + cmp #ind_Force_Shield ; shield with energy and parachute + beq UseShieldWithEnergy + cmp #ind_Heavy_Shield ; shield with energy + beq UseShieldWithEnergy + cmp #ind_Bouncy_Castle ; Auto Defence (it works only if hit ground next to tank. Tank hit is handled in Flight proc) + beq UseShieldWithEnergy + cmp #ind_Mag_Deflector ; Mag deflector (it works only if hit ground next to tank. Tank hit is handled in Flight proc) + beq UseShieldWithEnergy jsr DecreaseEnergyX - jmp EndOfDistanceCheckLoop + jmp EndOfDistanceCheckLoop UseShieldWithEnergy - jsr DecreaseShieldEnergyX - cpy #0 ; is necessary to reduce tenk energy ? - beq ShieldCoveredTank + jsr DecreaseShieldEnergyX + cpy #0 ; is necessary to reduce tenk energy ? + beq ShieldCoveredTank jsr DecreaseEnergyX -ShieldCoveredTank - lda ShieldEnergy,x - jne EndOfDistanceCheckLoop -ShieldEnergy0 ; deactivate if no energy. it's like use one hit shield :) +ShieldCoveredTank + lda ShieldEnergy,x + jne EndOfDistanceCheckLoop +ShieldEnergy0 ; deactivate if no energy. it's like use one hit shield :) UseShield - mva #1 Erase - lda TankNr - pha ; store TankNr - stx TankNr ; store X in TankNr :) - jsr DrawTankNr ; now erase tank with shield (to erase shield) - lda #0 - sta ActiveDefenceWeapon,x ; deactivate defense weapons - sta Erase - jsr DrawTankNr ; draw tank without shield - ldx TankNr ; restore X value :) - pla - sta TankNr ; restore TankNr value :) + lda TankNr + pha ; store TankNr + stx TankNr ; store X in TankNr :) + jsr ClearTankNr ; now erase tank with shield (to erase shield) + lda #0 + sta ActiveDefenceWeapon,x ; deactivate defense weapons + jsr PutTankNr ; draw tank without shield + ldx TankNr ; restore X value :) + pla + sta TankNr ; restore TankNr value :) TankIsNotWithinTheRange EndOfDistanceCheckLoop dex @@ -874,8 +872,8 @@ rbombLoop .proc xroller ; ; now collisions are detected with modified draw routine ; therefore YDRAW value must be taken from mountaintable - jsr checkRollDirection - ; HowMuchToFall - direction + jsr checkRollDirection + ; HowMuchToFall - direction ; $FF - we are in a hole (flying in missile direction) ; 1 - right, 2 - left Rollin @@ -893,7 +891,7 @@ RollinContinues ldy #0 lda (tempXROLLER),y sta ydraw - sty ydraw+1 + sty ydraw+1 beq ExplodeNow cmp HeightRol beq UpNotYet @@ -904,7 +902,7 @@ UpNotYet sbc #1 sta ydraw ;check tank collision prior to PLOT - sty HitFlag ; set to 0 + sty HitFlag ; set to 0 jsr CheckCollisionWithTank @@ -917,8 +915,8 @@ UpNotYet beq HowMuchToFallRight2 .nowarn dew xdraw lda xdraw - ora xdraw+1 - jne RollinContinues ; like cpw xdraw #0 + ora xdraw+1 + jne RollinContinues ; like cpw xdraw #0 beq ExplodeNow HowMuchToFallRight2 inw xdraw @@ -936,7 +934,7 @@ ExplodeNow ; finally a little explosion mva #sfx_baby_missile sfx_effect jmp xmissile - rts + ; rts .endp ; -------------------------------------------------- .proc checkRollDirection @@ -953,7 +951,7 @@ ExplodeNow adw xdraw #mountaintable tempXROLLER lda (tempXROLLER),y sta ydraw - sty ydraw+1 + sty ydraw+1 lda vx+3 ; if horizontal velocity is negative then change the direction @@ -969,19 +967,19 @@ PositiveVelocity mva #$ff HowMuchToFall mva ydraw HeightRol SeekLeft - cpw tempXROLLER #mountaintable - beq GoRightNow ; "bounce" if we have on left end + cpw tempXROLLER #mountaintable + beq GoRightNow ; "bounce" if we have on left end .nowarn dew tempXROLLER lda (tempXROLLER),y ;fukk! beware of Y value cmp HeightRol HowMuchToFallLeft bcs GoRightNow - mva #1 HowMuchToFall + mva #1 HowMuchToFall GoRightNow adw xdraw #mountaintable tempXROLLER SeekRight - cpw tempXROLLER #(mountaintable+screenwidth) - beq HowMuchToFallKnown ; "stop" if we have on left end + cpw tempXROLLER #(mountaintable+screenwidth) + beq HowMuchToFallKnown ; "stop" if we have on left end inw tempXROLLER lda (tempXROLLER),y cmp HeightRol @@ -1001,7 +999,7 @@ HowMuchToFallKnown adc goleft sta HowMuchToFall DirectionChecked - rts + rts .endp ; -------------------------------------------------- @@ -1009,7 +1007,7 @@ DirectionChecked ; -------------------------------------------------- ; makes dirt on xdraw,ydraw position and of ExplosionRadius height mva #sfx_dirt_chrg_s sfx_effect - + mva #1 color NoColor ; jump here with color=0 to clean dirt mwa xdraw xcircle @@ -1081,17 +1079,16 @@ ContinueToCheckMaxForce2 lda MaxForceTableL,x sta ForceTableL,x @ - mva #0 Erase - jsr DisplayStatus ;all digital values like force, angle, wind, etc. jsr PutTankNameOnScreen +; jsr DisplayStatus ; There is no need anymore, it is always after PutTankNameOnScreen - jsr DrawTankNr + jsr PutTankNr jsr WaitOneFrame ; best after drawing a tank - bit TestFlightFlag - bpl @+ - jsr Shoot.AfterOffensiveText ; Lazy Darwin - aiming visualisation + bit TestFlightFlag + bpl @+ + jsr Shoot.AfterOffensiveText ; Lazy Darwin - aiming visualisation @ ;keyboard reading ; KBCODE keeps code of last keybi @@ -1101,18 +1098,18 @@ ContinueToCheckMaxForce2 ; $f3 - shift+key notpressed - ldx TankNr ; for optimize - ; Select and Option - lda CONSOL - tay - and #%00000101 ; Start + Option - beq QuitToGameover - tya - and #%00000100 - beq callActivation ; Option key - tya - and #%00000010 - jeq pressedTAB ; Select key + jsr CheckExitKeys ; Check for O, Esc or Start+Option keys + spl:rts ; exit if pressed 'Exit keys' + + ldx TankNr ; for optimize + ; Select and Option + lda CONSOL + tay + and #%00000100 + beq callActivation ; Option key + tya + and #%00000010 + jeq pressedTAB ; Select key lda SKSTAT cmp #$ff jeq checkJoy @@ -1122,58 +1119,40 @@ notpressed lda kbcode and #%10111111 ; SHIFT elimination - cmp #@kbcode._O ; $08 ; O - bne @+ - jsr AreYouSure - bit escFlag - bpl notpressed - ;---O pressed-quit game to game over screen--- -QuitToGameover - mva #$40 escFlag - rts -@ - cmp #@kbcode._esc ; 28 ; ESC - bne @+ - jsr AreYouSure - bit escFlag - bpl notpressed - ;---esc pressed-quit game--- - rts -@ cmp #@kbcode._A ; $3f ; A bne @+ callActivation ; Hide all tanks - after inventory they may have other shapes jsr ClearTanks - jsr DefensivesActivate - jmp afterInventory + jsr DefensivesActivate + jmp afterInventory -@ +@ cmp #@kbcode._I ; $0d ; I bne @+ callInventory ; Hide all tanks - after inventory they may have other shapes jsr ClearTanks - ; + ; mva #$ff isInventory jsr Purchase afterInventory - jsr MakeDarkScreen + jsr MakeDarkScreen jsr DisplayStatus - jsr SetMainScreen + jsr SetMainScreen jsr DrawTanks ;jsr WaitOneFrame ; not necessary - bit LazyFlag - bvc NoLazy - jsr LazyBoys + bit LazyFlag + bvc NoLazy + jsr LazyBoys NoLazy - bit SpyHardFlag - bpl NoSpyHard - jsr SpyHard + bit SpyHardFlag + bpl NoSpyHard + jsr SpyHard NoSpyHard RmtSong song_ingame mva #0 escFlag - jmp ReleaseAndLoop + jmp ReleaseAndLoop @ cmp #$80|@kbcode._up jeq CTRLPressedUp @@ -1183,15 +1162,15 @@ NoSpyHard jeq CTRLPressedTAB jumpFromStick - .IF TARGET = 800 - cmp #$80|17 ; Ctrl+Help - bne NoVdebugSwitch - lda Vdebug - eor #$ff - sta Vdebug - jmp ReleaseAndLoop -NoVdebugSwitch - .ENDIF + .IF TARGET = 800 + cmp #$80|17 ; Ctrl+Help + bne NoVdebugSwitch + lda Vdebug + eor #$ff + sta Vdebug + jmp ReleaseAndLoop +NoVdebugSwitch + .ENDIF and #$3f ;CTRL and SHIFT ellimination cmp #@kbcode._up ; $e jeq pressedUp @@ -1209,14 +1188,14 @@ NoVdebugSwitch jeq pressedM cmp #@kbcode._S ; $3e ; S jeq pressedS - .IF TARGET = 800 - cmp #61 ; G - bne EndKeys - jsr SelectNextGradient.NotWind - jmp ReleaseAndLoop - .ENDIF + .IF TARGET = 800 + cmp #61 ; G + bne EndKeys + jsr SelectNextGradient.NotWind + jmp ReleaseAndLoop + .ENDIF EndKeys - jmp notpressed + jmp notpressed checkJoy ;------------JOY------------- ;happy happy joy joy @@ -1226,7 +1205,7 @@ checkJoy cmp #$0f beq notpressedJoy tay - mva #0 ATRACT ; reset atract mode + mva #0 ATRACT ; reset atract mode lda joyToKeyTable,y jmp jumpFromStick notpressedJoy @@ -1242,14 +1221,14 @@ pressedUp spl:mva #0 pressTimer ; if >128 then reset to 0 cmp #25 ; 1/2s bcs CTRLPressedUp - - + + ;force increaseeee! - ;ldx TankNr ; optimized + ;ldx TankNr ; optimized inc ForceTableL,x bne CheckingMaxForce inc ForceTableH,x - + CheckingMaxForce mva #sfx_set_power_1 sfx_effect @@ -1270,7 +1249,7 @@ FurtherCheckMaxForce jmp BeforeFire CTRLPressedUp - ;ldx TankNr ; optimized + ;ldx TankNr ; optimized lda ForceTableL,x clc adc #10 @@ -1288,7 +1267,7 @@ pressedDown mva #sfx_set_power_1 sfx_effect - ;ldx TankNr ; optimized + ;ldx TankNr ; optimized dec ForceTableL,x lda ForceTableL,x cmp #$ff @@ -1305,7 +1284,7 @@ ForceGoesZero CTRLPressedDown mva #sfx_set_power_1 sfx_effect - ;ldx TankNr ; optimized + ;ldx TankNr ; optimized sec lda ForceTableL,x sbc #10 @@ -1316,27 +1295,27 @@ CTRLPressedDown jmp BeforeFire pressedRight - ;ldx TankNr ; optimized + ;ldx TankNr ; optimized lda pressTimer spl:mva #0 pressTimer ; if >128 then reset to 0 cmp #25 ; 1/2s bcs CTRLPressedRight mva #sfx_set_power_2 sfx_effect - mva #1 Erase - jsr DrawTankNr.BarrelChange + mva #1 Erase + jsr DrawTankNr.BarrelChange dec:lda AngleTable,x - cmp #255 ; -1 + cmp #255 ; -1 jne BeforeFire lda #180 sta AngleTable,x jmp BeforeFire CTRLPressedRight - ;ldx TankNr ; optimized + ;ldx TankNr ; optimized mva #sfx_set_power_2 sfx_effect - mva #1 Erase - jsr DrawTankNr.BarrelChange + mva #1 Erase + jsr DrawTankNr.BarrelChange lda AngleTable,x sec sbc #4 @@ -1346,18 +1325,18 @@ CTRLPressedRight lda #180 sta AngleTable,x jmp BeforeFire - + pressedLeft - ;ldx TankNr ; optimized + ;ldx TankNr ; optimized lda pressTimer spl:mva #0 pressTimer ; if >128 then reset to 0 cmp #25 ; 1/2s bcs CTRLPressedLeft mva #sfx_set_power_2 sfx_effect - mva #1 Erase - jsr DrawTankNr.BarrelChange + mva #1 Erase + jsr DrawTankNr.BarrelChange INC AngleTable,x lda AngleTable,x cmp #180 @@ -1367,10 +1346,10 @@ pressedLeft jmp BeforeFire CTRLPressedLeft - ;ldx TankNr ; optimized + ;ldx TankNr ; optimized mva #sfx_set_power_2 sfx_effect - mva #1 Erase - jsr DrawTankNr.BarrelChange + mva #1 Erase + jsr DrawTankNr.BarrelChange lda AngleTable,x clc adc #4 @@ -1383,14 +1362,14 @@ CTRLPressedLeft pressedTAB mva #sfx_purchase sfx_effect - ;ldx TankNr ; optimized - lda ActiveWeapon,x - cmp #last_offensive_____ ; the last possible offensive weapon - bne ?notlasttofirst - lda #first_offensive____ ; #0 + ;ldx TankNr ; optimized + lda ActiveWeapon,x + cmp #last_offensive ; the last possible offensive weapon + bne ?notlasttofirst + lda #first_offensive ; #0 sta ActiveWeapon,x - beq @+ ; allways = 0 -?notlasttofirst + beq @+ ; allways = 0 +?notlasttofirst inc ActiveWeapon,x @ lda ActiveWeapon,x @@ -1400,13 +1379,13 @@ pressedTAB CTRLpressedTAB mva #sfx_purchase sfx_effect - ;ldx TankNr ; optimized - lda ActiveWeapon,x - cmp #first_offensive____ ; #0 - bne ?notfirsttolast - lda #last_offensive_____ ; the last possible offensive weapon + ;ldx TankNr ; optimized + lda ActiveWeapon,x + cmp #first_offensive ; #0 + bne ?notfirsttolast + lda #last_offensive ; the last possible offensive weapon sta ActiveWeapon,x - bne @+ ; allways <> 0 + bne @+ ; allways <> 0 ?notfirsttolast dec ActiveWeapon,x @ @@ -1433,8 +1412,8 @@ ReleaseAndLoop pressedSpace ;================================= ;we shoot here!!! - lda #0 - sta ATRACT ; reset atract mode + lda #0 + sta ATRACT ; reset atract mode sta pressTimer ; reset jsr WaitForKeyRelease.StillWait lda pressTimer @@ -1454,7 +1433,7 @@ fire ;with much more separate blocks, but you know - ;- do not touch it if it works... - mva #0 TestFlightFlag + mva #0 TestFlightFlag ;the latest addition to this routine is ;displaying offensive texts! @@ -1468,26 +1447,26 @@ RandomizeOffensiveText ldy TankNr mva #$ff plot4x4color jsr DisplayOffensiveTextNr - + AfterOffensiveText - mva #0 LaserFlag ; $ff - Laser - ldx TankNr - lda ActiveWeapon,x - cmp #ind_Laser__________ ; laser - bne NotStrongShoot - ; Laser: (not)very strong - invisible - shot for laser beam end coordinates - bit Vdebug - bmi @+ - mva #0 color -@ lda #1 - sta Force - sta Force+1 - mva #$ff LaserFlag ; $ff - Laser - bne AfterStrongShoot + mva #0 LaserFlag ; $ff - Laser + ldx TankNr + lda ActiveWeapon,x + cmp #ind_Laser ; laser + bne NotStrongShoot + ; Laser: (not)very strong - invisible - shot for laser beam end coordinates + bit Vdebug + bmi @+ + mva #0 color +@ lda #1 + sta Force + sta Force+1 + mva #$ff LaserFlag ; $ff - Laser + bne AfterStrongShoot NotStrongShoot - jsr Table2Force - bit TestFlightFlag - bmi AfterStrongShoot + jsr Table2Force + bit TestFlightFlag + bmi AfterStrongShoot mva #sfx_shoot sfx_effect AfterStrongShoot lda AngleTable,x @@ -1498,29 +1477,29 @@ AfterStrongShoot ; to start where the tank's barrel ends ; (without it bullet would go from the left lower corner of the tank) ;ldx TankNr - - mwa EndOfTheBarrelX xtraj+1 - mva EndOfTheBarrely ytraj+1 + + mwa EndOfTheBarrelX xtraj+1 + mva EndOfTheBarrely ytraj+1 lda #0 sta Force+2 - sta ytraj+2 + sta ytraj+2 sta xtraj sta ytraj - ; checking if the shot is underground (no Flight but Hit :) ) - tay ; A=0 ! - adw xtraj+1 #mountaintable temp + ; checking if the shot is underground (no Flight but Hit :) ) + tay ; A=0 ! + adw xtraj+1 #mountaintable temp lda ytraj+1 - cmp (temp),y ; check collision with mountains + cmp (temp),y ; check collision with mountains bcs ShotUnderGround jsr Flight mva #1 color rts ShotUnderGround - mwa xtraj+1 xdraw ; but why not XHit and YHit !!!??? - mwa ytraj+1 ydraw - mva #$ff HitFlag - rts + mwa xtraj+1 xdraw ; but why not XHit and YHit !!!??? + mwa ytraj+1 ydraw + mva #$ff HitFlag + rts .endp ;-------------------------------------------------- @@ -1545,23 +1524,23 @@ ShotUnderGround ; smoke tracer :) ldy #0 - bit TestFlightFlag ; if test flight for AI or Lazy Darwin - bmi noSmokeTracer ; no Smoke Tracer display + bit TestFlightFlag ; if test flight for AI or Lazy Darwin + bmi noSmokeTracer ; no Smoke Tracer display ldx TankNr lda ActiveWeapon,x - cmp #ind_Smoke_Tracer___ ; Smoke tracer - bne noSmokeTracer - iny + cmp #ind_Smoke_Tracer ; Smoke tracer + bne noSmokeTracer + iny noSmokeTracer - sty SmokeTracerFlag + sty SmokeTracerFlag RepeatIfSmokeTracer -RepeatFlight +RepeatFlight mwa ytraj+1 Ytrajold+1 mwa xtraj+1 Xtrajold+1 mva #%01000000 drawFunction - lda #0 + lda #0 sta vx sta vx+1 sta vx+2 @@ -1573,7 +1552,7 @@ RepeatFlight ;vx calculation ;vx = sin(90-Angle) for Angle <=90 - ;vx = -sin(Angle-90) for 90 < Angle <= 180 + ;vx = -sin(Angle-90) for 90 < Angle <= 180 aslw Force ;Force = Force * 2 ;cos(Angle) (but we use sin table only so some shenanigans happen) @@ -1586,10 +1565,10 @@ RepeatFlight ;180 horizontally left ; (we have to set goleft used in rolling weapons) - + cpx #91 bcc angleUnder90 - + ;over 90 mva #1 goleft sec @@ -1604,7 +1583,7 @@ angleUnder90 lda #90 sbc Angle tax -@ +@ lda sintable,x ; cos(X) sta Multiplee ; *Force mwa Force Multiplier @@ -1631,9 +1610,9 @@ DoNotAdd rol Multiplier+2 dex bne MultiplyLoop - + mva #0 vx+3 - ; here in vx there is a number + ; here in vx there is a number ; xxxx.xx00 = sin(Angle)*Force ; negate it if going left lda goleft @@ -1648,7 +1627,7 @@ DoNotAdd ;vy = sin(Angle) for Angle <=90 ;vy = sin(180-Angle) for 90 < Angle <= 180 - lda #0 + lda #0 sta vy sta vy+1 sta vy+2 @@ -1656,7 +1635,7 @@ DoNotAdd ldx Angle cpx #91 bcc YangleUnder90 - + lda #180 sec sbc Angle @@ -1690,7 +1669,7 @@ DoNotAddY rol Multiplier+2 dex bne MultiplyLoopY - ; here in vy there is a number + ; here in vy there is a number ; yyyy.yy=cos(Angle)*Force mva #0 vy+3 ;vy=cos(Angle)*Force @@ -1708,8 +1687,8 @@ Loopi sbc vy+3 sta ytraj+2 - bit LaserFlag ; no gravity if Laser - bmi NoGravity + bit LaserFlag ; no gravity if Laser + bmi NoGravity ;vy=vy-g (again without least significant byte of vy) sec lda vy+1 @@ -1724,11 +1703,11 @@ Loopi bpl StillUp ; where we know that the bullet starts to fall down ; we check if it is MIRV and if so, jump to MIRV routine - bit TestFlightFlag - bmi NoTestForMIRV + bit TestFlightFlag + bmi NoTestForMIRV ldx TankNr lda ActiveWeapon,x - cmp #ind_MIRV___________ ; MIRV + cmp #ind_MIRV ; MIRV jeq MIRVdownLoop NoTestForMIRV NoGravity @@ -1745,8 +1724,8 @@ StillUp adc vx+3 sta xtraj+2 - bit LaserFlag ; no wind if Laser - bmi NoWind + bit LaserFlag ; no wind if Laser + bmi NoWind clc .rept 4 lda vx+# @@ -1760,47 +1739,51 @@ NoWind mwa ytraj+1 ybyte jsr draw ;key - bit LaserFlag - bmi LaserNoWalls - ; Check for walls - jsr MakeWalls - ; + bit LaserFlag + bmi LaserNoWalls + ; Check for walls + jsr MakeWalls + ; LaserNoWalls mwa xtraj+1 XtrajOld+1 mwa ytraj+1 YtrajOld+1 - bit TestFlightFlag - bmi nowait - bit LaserFlag ; faster laser prepare - bpl nolaserwait - bit Vdebug - bpl nowait + bit TestFlightFlag + bmi nowait + bit LaserFlag ; faster laser prepare + bpl nolaserwait + bit Vdebug + bpl nowait nolaserwait lda color - beq nonowait ; smoke tracer erases slowly - lda tracerflag - bne nowait ; funky bomb explotes fast ( tracerflag in real is funkyflag :) ) -nonowait + beq nonowait ; smoke tracer erases slowly + lda tracerflag + bne nowait ; funky bomb explotes fast ( tracerflag in real is funkyflag :) ) +nonowait jsr shellDelay - + ; + jsr CheckExitKeys ; Check for O, Esc or Start+Option keys + spl:rts ; exit if pressed 'Exit keys' + ldx TankNr + ; nowait lda HitFlag bne Hit - ; --- only for Laser - bit LaserFlag + ; --- only for Laser + bit LaserFlag bpl NoCheckEdgesForLaser - ; If laser fires, edges of the screen finish "flying" and laser hits. - lda ytraj+2 - bmi LaserHitEdge - cpw xtraj+1 #screenwidth ;+1 - bcc LaserNoHitEdge + ; If laser fires, edges of the screen finish "flying" and laser hits. + lda ytraj+2 + bmi LaserHitEdge + cpw xtraj+1 #screenwidth ;+1 + bcc LaserNoHitEdge LaserHitEdge mwa xdraw XHit mwa ydraw YHit - mva #$ff HitFlag ; screen edgs like ground (only for Laser) - jmp EndOfFlight + mva #$ff HitFlag ; screen edgs like ground (only for Laser) + jmp EndOfFlight LaserNoHitEdge - ; ------------------ + ; ------------------ NoCheckEdgesForLaser cpw ytraj+1 #screenheight+1 @@ -1814,17 +1797,17 @@ SkipCollisionCheck mwa xtraj+1 xdraw mwa ytraj+1 ydraw - - bit TestFlightFlag - bvc NoTestFlight - bit Vdebug - bpl NoUnplot - jsr WaitOneFrame ; visualize AI targeting - jmp YesUnPlot + + bit TestFlightFlag + bvc NoTestFlight + bit Vdebug + bpl NoUnplot + jsr WaitOneFrame ; visualize AI targeting + jmp YesUnPlot NoTestFlight - lda tracerflag + lda tracerflag bne NoUnPlot - + YesUnPlot jsr UnPlot @@ -1835,8 +1818,8 @@ NoUnPlot Hit mwa XHit xdraw mwa YHit ydraw - bit TestFlightFlag - bvs EndOfFlight + bit TestFlightFlag + bvs EndOfFlight jsr unPlot EndOfFlight mwa xdraw xcircle ; we must store for a little while @@ -1847,137 +1830,133 @@ EndOfFlight mwa xcircle xdraw mwa ycircle ydraw - ldy SmokeTracerFlag - beq EndOfFlight2 - dey - sty SmokeTracerFlag - jmp SecondFlight + ldy SmokeTracerFlag + beq EndOfFlight2 + dey + sty SmokeTracerFlag + jmp SecondFlight EndOfFlight2 - mva #0 tracerflag ; don't know why - - bit TestFlightFlag - jmi NoHitAtEndOfFight ; RTS only !!! - no defendsives check - ; and now check for defensive-aggressive weapon - lda HitFlag - jeq NoHitAtEndOfFight ; RTS only !!! - jmi NoTankHitAtEndOfFight - ; tank hit - increase direct hits points - ldx TankNr - inx - cpx HitFlag ; we don't count suicides :) - beq @+ - dex - inc DirectHits,x -; bne @+ ; one byte enough -; inc DirectHitsH,x + mva #0 tracerflag ; don't know why + + bit TestFlightFlag + jmi NoHitAtEndOfFight ; RTS only !!! - no defendsives check + ; and now check for defensive-aggressive weapon + lda HitFlag + jeq NoHitAtEndOfFight ; RTS only !!! + jmi NoTankHitAtEndOfFight + ; tank hit - increase direct hits points + ldx TankNr + inx + cpx HitFlag ; we don't count suicides :) + beq @+ + dex + inc DirectHits,x +; bne @+ ; one byte enough +; inc DirectHitsH,x @ - ; tank hit - check defensive weapon of this tank - tax - dex ; index of hitted tank in X - ldy TankNr - lda ActiveWeapon,y - cmp #ind_Tracer_________ ; defence not fire by tracers - beq JNoDefence - cmp #ind_Smoke_Tracer___ - beq JNoDefence - cmp #ind_Laser__________ ; Bouncy and Mag not fire by Laser - beq JNoDefence - lda ActiveDefenceWeapon,x - cmp #ind_Bouncy_Castle__ ; Auto Defence - jeq BouncyCastle - cmp #ind_Mag_Deflector__ ; Mag Deflector - beq MagDeflector + ; tank hit - check defensive weapon of this tank + tax + dex ; index of hitted tank in X + ldy TankNr + lda ActiveWeapon,y + cmp #ind_Tracer ; defence not fire by tracers + beq JNoDefence + cmp #ind_Smoke_Tracer + beq JNoDefence + cmp #ind_Laser ; Bouncy and Mag not fire by Laser + beq JNoDefence + lda ActiveDefenceWeapon,x + cmp #ind_Bouncy_Castle ; Auto Defence + jeq BouncyCastle + cmp #ind_Mag_Deflector ; Mag Deflector + beq MagDeflector JNoDefence - jmp NoDefence + jmp NoDefence MagDeflector - ; now run defensive-aggressive weapon - Mag Deflector! - ; get tank position - clc - lda xtankstableL,x - adc #$04 ; almost in tak center :) - sta XHit - lda xtankstableH,x - adc #$00 - sta XHit+1 - lda #$ff ; change to ground hit (we hope) - sta HitFlag - bit random ; left or right deflection ? - bpl RightDeflection + ; now run defensive-aggressive weapon - Mag Deflector! + ; get tank position + clc + lda xtankstableL,x + adc #$04 ; almost in tak center :) + sta XHit + lda xtankstableH,x + adc #$00 + sta XHit+1 + lda #$ff ; change to ground hit (we hope) + sta HitFlag + bit random ; left or right deflection ? + bpl RightDeflection LeftDeflection - sbw XHit #18 ; 18 pixels to left and explode... - bit XHit+1 ; if off-screen ... - bpl EndOfMagDeflector ; hit of course but we need RTS - adw XHit #36 ; change to right :) - jmp EndOfMagDeflector + sbw XHit #18 ; 18 pixels to left and explode... + bit XHit+1 ; if off-screen ... + bpl EndOfMagDeflector ; hit of course but we need RTS + adw XHit #36 ; change to right :) + jmp EndOfMagDeflector RightDeflection - adw XHit #18 ; 18 pixels to right and explode... - cpw XHit screenwidth ; if off-screen ... - bcs EndOfMagDeflector ; hit of course but we need RTS - sbw XHit #36 ; change to left + adw XHit #18 ; 18 pixels to right and explode... + cpw XHit screenwidth ; if off-screen ... + bcs EndOfMagDeflector ; hit of course but we need RTS + sbw XHit #36 ; change to left EndOfMagDeflector - mva #1 Erase - lda TankNr - pha ; store TankNr - stx TankNr ; store X in TankNr :) - jsr DrawTankNr ; now erase tank with shield (to erase shield) - lda #0 - sta ActiveDefenceWeapon,x ; deactivate used mag deflector weapon - sta ShieldEnergy,x - sta Erase - jsr DrawTankNr ; draw tank without shield - ldx TankNr ; restore X value :) - pla - sta TankNr ; restore TankNr value :) - mwa XHit xdraw ; why? !!! + lda TankNr + pha ; store TankNr + stx TankNr ; store X in TankNr :) + jsr ClearTankNr ; now erase tank with shield (to erase shield) + lda #0 + sta ActiveDefenceWeapon,x ; deactivate used mag deflector weapon + sta ShieldEnergy,x + jsr PutTankNr ; draw tank without shield + ldx TankNr ; restore X value :) + pla + sta TankNr ; restore TankNr value :) + mwa XHit xdraw ; why? !!! NoTankHitAtEndOfFight NoHitAtEndOfFight NoDefence - lsrw Force ; Force = Force / 2 - because earlier we multiplied by 2 - rts ; END !!! + lsrw Force ; Force = Force / 2 - because earlier we multiplied by 2 + rts ; END !!! BouncyCastle - ; now in Y we have number of of the attacking player (TankNr) ! - lda ActiveWeapon,y - ; if Bouncy Castle bounced Funky Bomb - whole screen in range of soil down - cmp #ind_Funky_Bomb_____ - bne @+ - jsr SetFullScreenSoilRange + ; now in Y we have number of of the attacking player (TankNr) ! + lda ActiveWeapon,y + ; if Bouncy Castle bounced Funky Bomb - whole screen in range of soil down + cmp #ind_Funky_Bomb + bne @+ + jsr SetFullScreenSoilRange @ mva #sfx_shield_on sfx_effect - ; now run defensive-aggressive weapon - Bouncy Castle (previously known as Auto Defence)! - mva #1 Erase - lda TankNr - pha ; store TankNr - stx TankNr ; store X in TankNr :) - jsr DrawTankNr ; now erase tank with shield (to erase shield) - lda #0 - sta ActiveDefenceWeapon,x ; deactivate used auto defense weapon - sta ShieldEnergy,x - sta xtraj ; prepare coordinates + ; now run defensive-aggressive weapon - Bouncy Castle (previously known as Auto Defence)! + lda TankNr + pha ; store TankNr + stx TankNr ; store X in TankNr :) + jsr ClearTankNr ; now erase tank with shield (to erase shield) + lda #0 + sta ActiveDefenceWeapon,x ; deactivate used auto defense weapon + sta ShieldEnergy,x + sta xtraj ; prepare coordinates sta ytraj -; sta xtraj+2 -; sta ytraj+2 - sta Erase - jsr DrawTankNr ; draw tank without shield -; ldx TankNr ; restore X value :) ... but we don't need X now .. - pla - sta TankNr ; restore TankNr value :) - sec - lda #180 - sbc LeapFrogAngle - sta Angle ; swap angle (LeapFrogAngle - because we have strored angle in this variable) - lsrw Force ; Force = Force / 2 - because earlier we multiplied by 2 - mwa XHit xtraj+1 - sbw YHit #5 ytraj+1 - mva #1 color - jmp RepeatFlight ; and repeat Fight +; sta xtraj+2 +; sta ytraj+2 + jsr PutTankNr ; draw tank without shield +; ldx TankNr ; restore X value :) ... but we don't need X now .. + pla + sta TankNr ; restore TankNr value :) + sec + lda #180 + sbc LeapFrogAngle + sta Angle ; swap angle (LeapFrogAngle - because we have strored angle in this variable) + lsrw Force ; Force = Force / 2 - because earlier we multiplied by 2 + mwa XHit xtraj+1 + sbw YHit #5 ytraj+1 + mva #1 color + jmp RepeatFlight ; and repeat Fight .endp .proc SecondFlight ; ---------------- copied code fragment from before firing. not too elegant. ; ---------------- get fire parameters again - ldx TankNr - jsr Table2Force + ldx TankNr + jsr Table2Force lda AngleTable,x sta Angle @@ -1986,22 +1965,22 @@ BouncyCastle ; to start where the tank's barrel ends ; (without it bullet would go from the left lower corner of the tank) ;ldx TankNr - - mwa EndOfTheBarrelX xtraj+1 - mva EndOfTheBarrely ytraj+1 + + mwa EndOfTheBarrelX xtraj+1 + mva EndOfTheBarrely ytraj+1 lda #0 sta Force+2 - sta ytraj+2 + sta ytraj+2 sta xtraj sta ytraj - sta color + sta color + - ldy #100 ; ??? - mva #1 tracerflag ; I do not know (I mean I think I know ;) ) - ; 10 years later - I do not know!!! + mva #1 tracerflag ; I do not know (I mean I think I know ;) ) + ; 10 years later - I do not know!!! ; 20 years later - still do not know :] - jmp Flight.RepeatIfSmokeTracer + jmp Flight.RepeatIfSmokeTracer .endp ; ------------------------------------------------- @@ -2078,18 +2057,18 @@ MIRVcopyParameters sta vx03+4 ; clearing ranges of soil down registers - jsr ClearScreenSoilRange + jsr ClearScreenSoilRange ldx #$FF ; it will turn 0 in a moment anyway stx MirvMissileCounter mrLoopi - ldx MirvMissileCounter - inx - cpx #5 - bne @+ - ldx #0 -@ stx MirvMissileCounter - + ldx MirvMissileCounter + inx + cpx #5 + bne @+ + ldx #0 +@ stx MirvMissileCounter + ; Y changes only for bullet number 0 ; because rest of the bullets have the same Y (height) @@ -2120,7 +2099,16 @@ mrLoopi sta vy+3 jsr ShellDelay - + ; + phx + jsr CheckExitKeys ; Check for O, Esc or Start+Option keys + bpl ExitnotPressed + plx + rts ; exit if pressed 'Exit keys' +ExitnotPressed + plx + ; + MIRVdoNotChangeY lda MirvDown,x ; if bullet is already down we go with the next one @@ -2146,63 +2134,63 @@ MIRVdoNotChangeY sta vx+# .endr - ; rules for a falling MIRV bulets. - ; if Y is negative and any X (bullet over the screen) - continue flying - ; if (Y>=0 and Y<=screenhight) and X>screenwidth (bullet off-screen on the left or right side) - continue flying - ; if (Y>=0 and Y<=screenhight) and X<=screenwidth (bullet on the screen) - check collision - ; if Y>screenhight and X>screenwidth (bullet under the screen on the left or right side) - stop flying without hit - ; if Y>screenhight and X<=screenwidth (bullet under the screen) - check collision (allways hit) - - ; check bullet position and set flags: - ; XposFlag - bullet positon X (0 - on screen , %1000000 - off-screen) - ; YposFlag - bullet positon Y (0 - on screen , %1000000 - over the screen , %0100000 - under the screen) - lda #$00 - sta XposFlag - sta YposFlag - lda ytraj+2 ; Y high byte - bpl @+ - mva #%10000000 YposFlag ; bullet over the screen (Y) - bmi MIRVsetXflag + ; rules for a falling MIRV bulets. + ; if Y is negative and any X (bullet over the screen) - continue flying + ; if (Y>=0 and Y<=screenhight) and X>screenwidth (bullet off-screen on the left or right side) - continue flying + ; if (Y>=0 and Y<=screenhight) and X<=screenwidth (bullet on the screen) - check collision + ; if Y>screenhight and X>screenwidth (bullet under the screen on the left or right side) - stop flying without hit + ; if Y>screenhight and X<=screenwidth (bullet under the screen) - check collision (allways hit) + + ; check bullet position and set flags: + ; XposFlag - bullet positon X (0 - on screen , %1000000 - off-screen) + ; YposFlag - bullet positon Y (0 - on screen , %1000000 - over the screen , %0100000 - under the screen) + lda #$00 + sta XposFlag + sta YposFlag + lda ytraj+2 ; Y high byte + bpl @+ + mva #%10000000 YposFlag ; bullet over the screen (Y) + bmi MIRVsetXflag @ - lda ytraj+1 ; Y low byte - cmp #screenheight - bcc MIRVsetXflag ; bullet on screen (Y) - mva #%01000000 YposFlag ; bullet under the screen (Y) + lda ytraj+1 ; Y low byte + cmp #screenheight + bcc MIRVsetXflag ; bullet on screen (Y) + mva #%01000000 YposFlag ; bullet under the screen (Y) MIRVsetXflag - lda xtraj02,x ; X high byte + lda xtraj02,x ; X high byte cmp #>screenwidth - bne @+ - lda xtraj01,x ; X low byte + bne @+ + lda xtraj01,x ; X low byte cmp #mountaintable sta temp+1 lda (temp),y - sec - sbc #1 + sec + sbc #1 sta ydraw sty ydraw+1 ;we know that y=0 jsr missile ; explode .... @@ -2317,61 +2305,61 @@ MIRValreadyAll ; temporary removing tanks from the screen (otherwise they will fall down with soil) jsr SoilDown2 - mva #$ff HitFlag ; but why ?? + mva #$ff HitFlag ; but why ?? rts .endp ; ------------------------------------------------- .proc MakeWalls ; ------------------------------------------------- - bit WallsType ; ; bits 6 and 7: 00 - none, 01 - bump, 10 - wrap, 11 - boxy - bpl WrapAndNone - bvc MakeBump - ; top bounce - bit ytraj+2 - bpl NoOnTop - bit vy+3 - bmi FlyingDown - sec - .rept 4 + bit WallsType ; ; bits 6 and 7: 00 - none, 01 - bump, 10 - wrap, 11 - boxy + bpl WrapAndNone + bvc MakeBump + ; top bounce + bit ytraj+2 + bpl NoOnTop + bit vy+3 + bmi FlyingDown + sec + .rept 4 lda #$00 sbc vy+# sta vy+# - .endr + .endr FlyingDown NoOnTop MakeBump - cpw xtraj+1 #screenwidth - bcc OnScreen - ; inverse vx (bouncing wall) - sec - .rept 4 + cpw xtraj+1 #screenwidth + bcc OnScreen + ; inverse vx (bouncing wall) + sec + .rept 4 lda #$00 sbc vx+# sta vx+# .endr - ; and bouce feapfrog :) - sec - lda #180 - sbc LeapFrogAngle - sta LeapFrogAngle ; swap angle (LeapFrogAngle) - inc FunkyWallFlag - rts + ; and bouce feapfrog :) + sec + lda #180 + sbc LeapFrogAngle + sta LeapFrogAngle ; swap angle (LeapFrogAngle) + inc FunkyWallFlag + rts WrapAndNone - bvc NoWall - cpw xtraj+1 #screenwidth - bcc OnScreen - ; (wrapping wall) - inc FunkyWallFlag - bit xtraj+2 - bmi LeftWrap + bvc NoWall + cpw xtraj+1 #screenwidth + bcc OnScreen + ; (wrapping wall) + inc FunkyWallFlag + bit xtraj+2 + bmi LeftWrap RightWrap - sbw xtraj+1 #screenwidth - rts + sbw xtraj+1 #screenwidth + rts LeftWrap - adw xtraj+1 #screenwidth + adw xtraj+1 #screenwidth OnScreen NoWall - rts + rts .endp ; ------------------------------------------------- .proc WhiteFlag @@ -2380,198 +2368,114 @@ NoWall ; and replaces Shoot and Flight routines ; X and TankNr - index of shooting tank ; ------------------------------------------------- - mva #sfx_death_begin sfx_effect - jsr FlashTank ; first we flash tank - mva #1 Erase - jsr DrawTankNr ; and erase tank - lda #0 - sta Erase - ldx TankNr - sta Energy,x ; clear tank energy - sta eXistenZ,x ; erase from existence - sta LASTeXistenZ,x ; to prevent explosion - sta ActiveDefenceWeapon,x ; deactivate White Flag - jsr PMoutofScreen - jsr drawtanks ; for restore PM + mva #sfx_death_begin sfx_effect + jsr FlashTank ; first we flash tank + jsr ClearTankNr ; and erase tank + lda #0 + sta Erase + ldx TankNr + sta Energy,x ; clear tank energy + sta eXistenZ,x ; erase from existence + sta LASTeXistenZ,x ; to prevent explosion + sta ActiveDefenceWeapon,x ; deactivate White Flag + jsr PMoutofScreen + jsr drawtanks ; for restore PM mva #sfx_silencer sfx_effect - rts + rts .endp -; ------------------------------------------------- -.proc AtomicWinter -; ------------------------------------------------- -; This routine is run from inside of the main loop -; and replaces Shoot and Flight routines -; X and TankNr - index of shooting tank -; ------------------------------------------------- - mva #sfx_sandhog sfx_effect -.IF FASTER_GRAF_PROCS = 1 - ldy #0 ; byte counter (from 0 to 39) -NextColumn - ; big loop - we repat internal loops for each column of bytes - sty magic - ldx #120 ; line counter (from 0 to 60 ) - ; first loop - inverse column of bytes for a while - ldy magic -NextLine1 - jsr InverseScreenByte - dex - dex - bpl NextLine1 - ; - jsr WaitOneFrame ; wait uses A only - ; second loop - inverse again and put random "snow" to column of bytes - ldx #120 - ldy magic - mva #$55 magic+1 -NextLine2 - jsr InverseScreenByte - lda random - ora magic+1 - and (temp),y - sta (temp),y - lda magic+1 - eor #$ff - sta magic+1 - dex - dex - bpl NextLine2 - ; and go to next column - iny - cpy #40 - bne NextColumn -.ELSE - mva #1 color - mwa #120 ydraw -NextLineSlow - lda #0 - sta xdraw - sta xdraw+1 -NextPixelSlow - bit random - bpl NoPlot - bvc NoPlot - jsr plot.MakePlot -NoPlot - inw xdraw - cpw xdraw #screenwidth - bne NextPixelSlow - dec ydraw - dec ydraw - bpl NextLineSlow -.ENDIF - ; and we have "snow" :) - lda #0 - ldx TankNr - sta ActiveDefenceWeapon,x ; deactivate Nuclear Winter - jsr SetFullScreenSoilRange - jsr SoilDown2.NoClearTanks - rts - - ; in order to optimize the fragment repeated in both internal loops - ; we save 15 bytes :) -InverseScreenByte - lda LineTableL,x - sta temp - lda LineTableH,x - sta temp+1 - lda (temp),y - eor #$ff - sta (temp),y - rts -.endp ; ------------------------------------------------- .proc AutoDefense ; ------------------------------------------------- ; This routine is run from inside of the main loop ; X - index of tank ; ------------------------------------------------- - jsr PrepareAIShoot.WepTableToTemp - jsr UseBattery - jsr TosserDefensives - rts + jsr PrepareAIShoot.WepTableToTemp + jsr UseBattery + jmp TosserDefensives + ; rts .endp ; ------------------------------------------------- .proc SpyHard ; ------------------------------------------------- - mvx TankNr TargetTankNr ; save + mvx TankNr TargetTankNr ; save RepeatSpy - mvx #0 TankNr - stx SpyHardFlag ; 0 - optimization + mvx #0 TankNr + stx SpyHardFlag ; 0 - optimization CheckNextTankSH - cpx TargetTankNr - beq ThisTankItsMe - lda Energy,x ; only active players + cpx TargetTankNr + beq ThisTankItsMe + lda Energy,x ; only active players beq ThisTankIsDead - ; run SpyHard for tank in X - jsr DisplaySpyInfo - jsr FlashTank -@ jsr GetKey + ; run SpyHard for tank in X + jsr DisplaySpyInfo + jsr FlashTank +@ jsr GetKey bit escFlag bmi SpyHardEnd - cmp #@kbcode._space ; $21 ; Space - beq SpyHardEnd - cmp #@kbcode._ret ; Return key (5200 - fire) - beq SpyHardEnd + cmp #@kbcode._space ; $21 ; Space + beq SpyHardEnd + cmp #@kbcode._ret ; Return key (5200 - fire) + beq SpyHardEnd cmp #@kbcode._left ; $6 - beq SelectNextTank + beq SelectNextTank cmp #@kbcode._right ; $07 ; cursor right - bne @- + bne @- ThisTankIsDead ThisTankItsMe SelectNextTank inc TankNr - ldx TankNr - cpx NumberOfPlayers + ldx TankNr + cpx NumberOfPlayers bne CheckNextTankSH - beq RepeatSpy + beq RepeatSpy SpyHardEnd - mvx TargetTankNr TankNr ; restore - jsr DisplaySpyInfo - rts + mvx TargetTankNr TankNr ; restore + jmp DisplaySpyInfo + ; rts .endp .proc DisplaySpyInfo lda TankStatusColoursTable,x sta COLOR2 ; set color of status line - jsr PutTankNameOnScreen - jsr DisplayStatus - rts + jmp PutTankNameOnScreen + ; jsr DisplayStatus ; There is no need anymore, it is always after PutTankNameOnScreen + ; rts .endp ; ------------------------------------------------- .proc LazyBoys ; ------------------------------------------------- mva #sfx_lazy_boys sfx_effect - jsr PrepareAIShoot - ldx TankNr - bit LazyFlag - bmi GoDarwin - jsr FindBestTarget2 ; find nearest tank neighbour - jsr LazyAim - lda #%00000000 ; set "visual aiming" off - beq EndLazy + jsr PrepareAIShoot + ldx TankNr + bit LazyFlag + bmi GoDarwin + jsr FindBestTarget2 ; find nearest tank neighbour + jsr LazyAim + lda #%00000000 ; set "visual aiming" off + beq EndLazy GoDarwin - jsr FindBestTarget3 ; find target with lowest energy - jsr LazyAim - lda #%10000000 + jsr FindBestTarget3 ; find target with lowest energy + jsr LazyAim + lda #%10000000 EndLazy - sta TestFlightFlag ; set "visual aiming" on - mva #0 LazyFlag - rts + sta TestFlightFlag ; set "visual aiming" on + mva #0 LazyFlag + rts .endp .proc LazyAim - ; aiming proc for Lazy ... weapons - ; as proc for memory optimisation - ; Y - target tan nr - ; A - target direction - sty TargetTankNr - ; aiming - jsr TakeAim ; direction still in A (0 - left, >0 - right) - lda Force - sta ForceTableL,x - lda Force+1 - sta ForceTableH,x - jsr MoveBarrelToNewPosition - rts + ; aiming proc for Lazy ... weapons + ; as proc for memory optimisation + ; Y - target tan nr + ; A - target direction + sty TargetTankNr + ; aiming + jsr TakeAim ; direction still in A (0 - left, >0 - right) + lda Force + sta ForceTableL,x + lda Force+1 + sta ForceTableH,x + jmp MoveBarrelToNewPosition + ; rts .endp ; ------------------------------------------------- .proc TankFlying @@ -2580,102 +2484,87 @@ EndLazy ; and replaces Shoot and Flight routines ; X and TankNr - index of flying tank ; ------------------------------------------------- - ; Let's designate the flight altitude. - jsr CheckMaxMountain - cmp #(12+18) ; tank with shield (12) and max alt (18) check - bcc IsToHigh - sbc #12 ; tank with shield high correction - bne StoreMaxAlt -IsToHigh - lda #18 + ; Let's designate the flight altitude. + jsr CheckMaxMountain + cmp #(12+18) ; tank with shield (12) and max alt (18) check + bcc IsToHigh + sbc #12 ; tank with shield high correction + bne StoreMaxAlt +IsToHigh + lda #18 StoreMaxAlt - sta FloatingAlt -; mva #18 FloatingAlt ; for testing + sta FloatingAlt +; mva #18 FloatingAlt ; for testing mva #sfx_plasma_2_2 sfx_effect - ; display text 4x4 - fuel full - - mwa #hoverFull LineAddress4x4 - mwa #((ScreenWidth/2)-((hoverFullEnd-hoverFull)*2)) LineXdraw ; centering - mva #hoverFullEnd-hoverFull-1 fx ; length - sec - lda FloatingAlt - sbc #12 - sta LineYdraw + ; display text 4x4 - fuel full + jsr SetFuelFullText jsr TypeLine4x4.variableLength - ldx TankNr - - ; TankNr in X reg. - ; now animate Up - mva #0 modify ; it's a counter + ldx TankNr + + ; TankNr in X reg. + ; now animate Up + mva #0 modify ; it's a counter TankGoUp - lda ytankstable,x - cmp FloatingAlt ; Floating altitude - bcc ReachSky - ; first erase old tank position - mva #1 Erase - jsr DrawTankNr - lda modify - cmp #5 - bcc NoEngineClear - mva #0 color - jsr DrawTankRocketEngine + lda ytankstable,x + cmp FloatingAlt ; Floating altitude + bcc ReachSky + ; first erase old tank position + jsr ClearTankNr + lda modify + cmp #5 + bcc NoEngineClear + mva #0 color + jsr DrawTankRocketEngine NoEngineClear - mva #0 Erase - dec ytankstable,x - inc modify - ; then draw tank on new position - jsr DrawTankNr - lda modify - cmp #5 - bcc NoEngine - lda random - and #%00000001 - sta color - jsr DrawTankRocketEngine + dec ytankstable,x + inc modify + ; then draw tank on new position + jsr PutTankNr + lda modify + cmp #5 + bcc NoEngine + lda random + and #%00000001 + sta color + jsr DrawTankRocketEngine NoEngine -; jsr WaitOneFrame - jmp TankGoUp +; jsr WaitOneFrame + jmp TankGoUp ReachSky - ; engine symbol erase - mva #0 color - jsr DrawTankRocketEngine + ; engine symbol erase + mva #0 color + jsr DrawTankRocketEngine - ; display text 4x4 - fuel full (clear text) - mwa #hoverFull LineAddress4x4 - mwa #((ScreenWidth/2)-((hoverFullEnd-hoverFull)*2)) LineXdraw ; centering - mva #(hoverFullEnd-hoverFull-1) fx ; length - sec - lda FloatingAlt - sbc #12 - sta LineYdraw + ; display text 4x4 - fuel full (clear text) + jsr SetFuelFullText lda #$00 jsr TypeLine4x4.staplot4x4color - ; and Soildown at the start (for correct mountaintable if tank was buried) - ; calculate range - ldx TankNr - sec - lda XtankstableL,x - sbc #2 - sta RangeLeft - lda XtankstableH,x - sbc #0 - sta RangeLeft+1 - clc - lda XtankstableL,x - adc #10 - sta RangeRight - lda XtankstableH,x - adc #0 - sta RangeRight+1 - ; hide tanks and ... - jsr SoilDown2 - jsr ClearScreenSoilRange - ldx TankNr + ; and Soildown at the start (for correct mountaintable if tank was buried) + ; calculate range + ldx TankNr + sec + lda XtankstableL,x + sbc #2 + sta RangeLeft + lda XtankstableH,x + sbc #0 + sta RangeLeft+1 + clc + lda XtankstableL,x + adc #10 + sta RangeRight + lda XtankstableH,x + adc #0 + sta RangeRight+1 + ; hide tanks and ... + jsr SoilDown2 + jsr ClearScreenSoilRange + ldx TankNr - ; check keyboard/joy and move tank left/right - code copied from BeforeFire + ; check keyboard/joy and move tank left/right - code copied from BeforeFire ;keyboard reading ; KBCODE keeps code of last keybi ; SKSTAT $ff - nothing pressed @@ -2684,27 +2573,24 @@ ReachSky ; $f3 - shift+key KeyboardAndJoyCheck mva #sfx_tank_move sfx_effect - lda ShieldEnergy,x - cmp #20 - bne LotOfFuel - - ; display text 4x4 - low fuel - mwa #hoverEmpty LineAddress4x4 - mwa #((ScreenWidth/2)-((hoverEmptyEnd-hoverEmpty)*2)) LineXdraw ; centering - mva #hoverEmptyEnd-hoverEmpty-1 fx ; length - sec - lda FloatingAlt - sbc #12 - sta LineYdraw + lda ShieldEnergy,x + cmp #20 + bne LotOfFuel + + ; display text 4x4 - low fuel + jsr SetLowFuelText jsr TypeLine4x4.variableLength - ldx TankNr LotOfFuel notpressed - ; let's animate "engine" - jsr DrawTankEngine - ; enimation ends - + jsr CheckExitKeys + spl:rts ;---Exit key pressed-quit game--- + ldx TankNr + + ; let's animate "engine" + jsr DrawTankEngine + ; enimation ends + lda SKSTAT cmp #$ff jeq checkJoy @@ -2714,14 +2600,6 @@ notpressed lda kbcode and #%00111111 ; CTRL and SHIFT elimination - cmp #@kbcode._esc ; 28 ; ESC - bne @+ - jsr AreYouSure - bit escFlag - bpl notpressed - ;---esc pressed-quit game--- - rts -@ jumpFromStick cmp #@kbcode._left ; $6 jeq pressedLeft @@ -2738,7 +2616,7 @@ checkJoy and #$0f cmp #$0f beq notpressedJoy - tay + tay lda joyToKeyTable,y jmp jumpFromStick notpressedJoy @@ -2749,121 +2627,112 @@ notpressedJoy pressedRight - lda ShieldEnergy,x - jeq pressedSpace - ldy #1 - jsr DecreaseShieldEnergyX - ; first erase old tank position - mva #1 Erase - jsr DrawTankNr - mva #0 Erase - lda XtankstableH,x - cmp #>(screenwidth-TankWidth-4) ; tank width correction +4 - bne @+ - lda XtankstableL,x - cmp #<(screenwidth-TankWidth-4) ; tank width correction +4 pixels -@ bcs RightScreenEdge - inc XtankstableL,x - sne:inc XtankstableH,x - jmp NoREdge + lda ShieldEnergy,x + jeq pressedSpace + ldy #1 + jsr DecreaseShieldEnergyX + ; first erase old tank position + jsr ClearTankNr + mva #0 Erase + lda XtankstableH,x + cmp #>(screenwidth-TankWidth-4) ; tank width correction +4 + bne @+ + lda XtankstableL,x + cmp #<(screenwidth-TankWidth-4) ; tank width correction +4 pixels +@ bcs RightScreenEdge + inc XtankstableL,x + sne:inc XtankstableH,x + jmp NoREdge RightScreenEdge mva #sfx_dunno sfx_effect NoREdge - mva #18 AngleTable,x - bne DrawFloatingTank ; then draw tank on new position + mva #18 AngleTable,x + bne DrawFloatingTank ; then draw tank on new position pressedLeft - lda ShieldEnergy,x - beq pressedSpace - ldy #1 - jsr DecreaseShieldEnergyX - ; first erase old tank position - mva #1 Erase - jsr DrawTankNr - mva #0 Erase - lda XtankstableH,x - cmp #0 - bne @+ - lda XtankstableL,x - cmp #5 ; 4 pixles from left edge -@ bcc LeftScreenEdge - dec XtankstableL,x - lda XtankstableL,x - cmp #$ff - sne:dec XtankstableH,x - jmp NoLEdge + lda ShieldEnergy,x + beq pressedSpace + ldy #1 + jsr DecreaseShieldEnergyX + ; first erase old tank position + jsr ClearTankNr + lda XtankstableH,x + cmp #0 + bne @+ + lda XtankstableL,x + cmp #5 ; 4 pixles from left edge +@ bcc LeftScreenEdge + dec XtankstableL,x + lda XtankstableL,x + cmp #$ff + sne:dec XtankstableH,x + jmp NoLEdge LeftScreenEdge mva #sfx_dunno sfx_effect NoLEdge - mva #162 AngleTable,x - ; then draw tank on new position + mva #162 AngleTable,x + ; then draw tank on new position DrawFloatingTank - jsr DrawTankNr - jsr DisplayStatus - jsr WaitOneFrame - jsr CalculateSoildown + jsr PutTankNr + jsr DisplayStatus + jsr WaitOneFrame + jsr CalculateSoildown jmp KeyboardAndJoyCheck pressedSpace - ; display text 4x4 - low fuel (clear text) - mwa #hoverEmpty LineAddress4x4 - mwa #((ScreenWidth/2)-((hoverEmptyEnd-hoverEmpty)*2)) LineXdraw ; centering - mva #hoverEmptyEnd-hoverEmpty-1 fx ; length - sec - lda FloatingAlt - sbc #12 - sta LineYdraw + ; display text 4x4 - low fuel (clear text) + jsr SetLowFuelText lda #$00 jsr TypeLine4x4.staplot4x4color - ldx TankNr + ldx TankNr ;================================= - ; left or right from center of screen ? - ldy #0 + ; left or right from center of screen ? + ldy #0 lda XtankstableH,x - cmp #>((screenwidth/2)-TankWidth) - bne @+ + cmp #>((screenwidth/2)-TankWidth) + bne @+ lda XtankstableL,x - cmp #<((screenwidth/2)-TankWidth) -@ bcc TankOnLeftSide + cmp #<((screenwidth/2)-TankWidth) +@ bcc TankOnLeftSide TankOnRightSide - dey + dey TankOnLeftSide - sty OverTankDir ; (0 go right, $ff go left) - ; now we have direction of bypassing tanks on screen + sty OverTankDir ; (0 go right, $ff go left) + ; now we have direction of bypassing tanks on screen - ; clear "engine pixels" under tank + ; clear "engine pixels" under tank mva #1 erase - jsr DrawTankEngine + jsr DrawTankEngine CheckForTanksBelow - lda XtankstableL,x - sta xdraw - lda XtankstableH,x - sta xdraw+1 - ldx NumberOfPlayers - dex + lda XtankstableL,x + sta xdraw + lda XtankstableH,x + sta xdraw+1 + ldx NumberOfPlayers + dex CheckCollisionWithTankLoop - cpx TankNr - beq ItIsMe - lda eXistenZ,x - beq DeadTank - ; now we use Y as low byte and A as high byte of checked position (left right edgs of shield) - ; it is tricky but fast and much shorter + cpx TankNr + beq ItIsMe + lda eXistenZ,x + beq DeadTank + ; now we use Y as low byte and A as high byte of checked position (left right edgs of shield) + ; it is tricky but fast and much shorter lda xtankstableL,x - sec - sbc #9 ; 2 pixels more on left side + tank width - tay - lda xtankstableH,x - sbc #0 - ; bmi ShieldOverLeftEdge ; I do not know whether to check it. Probably not :) !!! + sec + sbc #9 ; 2 pixels more on left side + tank width + tay + lda xtankstableH,x + sbc #0 + ; bmi ShieldOverLeftEdge ; I do not know whether to check it. Probably not :) !!! cmp xdraw+1 bne @+ cpy xdraw @ - bcs LeftFromTheTank - tya ;add 20 (tank size*2 +2 and +2) + bcs LeftFromTheTank + tya ;add 20 (tank size*2 +2 and +2) clc - adc #20 + adc #20 tay lda xtankstableH,x adc #0 @@ -2873,109 +2742,122 @@ CheckCollisionWithTankLoop @ bcc RightFromTheTank TankBelow - ; tank below - we must move our tank - ldx TankNr - ; first erase old tank position - mva #1 Erase - jsr DrawTankNr - mva #0 Erase - bit OverTankDir - bmi PassLeft + ; tank below - we must move our tank + ldx TankNr + ; first erase old tank position + jsr ClearTankNr + bit OverTankDir + bmi PassLeft PassRight - inc XtankstableL,x - sne:inc XtankstableH,x - mva #18 AngleTable,x - bne Bypassing + inc XtankstableL,x + sne:inc XtankstableH,x + mva #18 AngleTable,x + bne Bypassing PassLeft - dec XtankstableL,x - lda XtankstableL,x - cmp #$ff - sne:dec XtankstableH,x - mva #162 AngleTable,x + dec XtankstableL,x + lda XtankstableL,x + cmp #$ff + sne:dec XtankstableH,x + mva #162 AngleTable,x Bypassing - ; then draw tank on new position - jsr DrawTankNr - jmp CheckForTanksBelow + ; then draw tank on new position + jsr PutTankNr + jmp CheckForTanksBelow RightFromTheTank LeftFromTheTank DeadTank ItIsMe dex bpl CheckCollisionWithTankLoop - ldx TankNr + ldx TankNr mva #sfx_shield_off sfx_effect - mva #1 Erase - jsr DrawTankNr - mva #0 Erase - ; x correction for P/M - ; -- - .IF XCORRECTION_FOR_PM = 1 - lda XtankstableL,x - and #%11111110 ; correction for PM - sta XtankstableL,x - .ENDIF - ; -- + jsr ClearTankNr + mva #0 Erase + ; x correction for P/M + ; -- + .IF XCORRECTION_FOR_PM = 1 + lda XtankstableL,x + and #%11111110 ; correction for PM + sta XtankstableL,x + .ENDIF + ; -- GoDown - mwa #mountaintable temp - clc - lda temp - adc XtankstableL,x - sta temp - lda temp+1 - adc XtankstableH,x - sta temp+1 - adw temp #4 ; center of the tank - ldy #0 - lda (temp),y - sta OverTankDir ; not elegant!!! Reuse as height of tank flight + mwa #mountaintable temp + clc + lda temp + adc XtankstableL,x + sta temp + lda temp+1 + adc XtankstableH,x + sta temp+1 + adw temp #4 ; center of the tank + ldy #0 + lda (temp),y + sta OverTankDir ; not elegant!!! Reuse as height of tank flight FloatDown - lda ytankstable,x - cmp OverTankDir - bcs OnGround - ; first erase old tank position - mva #1 Erase - jsr DrawTankNr + lda ytankstable,x + cmp OverTankDir + bcs OnGround + ; first erase old tank position + jsr ClearTankNr jsr DrawTankParachute - mva #0 Erase - inc ytankstable,x - ; then draw tank on new position - jsr DrawTankNr + inc ytankstable,x + ; then draw tank on new position + jsr PutTankNr jsr DrawTankParachute - jsr WaitOneFrame - jmp FloatDown + jsr WaitOneFrame + jmp FloatDown OnGround - ; clear parachute - mva #1 Erase + ; clear parachute + mva #1 Erase jsr DrawTankParachute - mva #0 Erase + mva #0 Erase jsr WaitForKeyRelease - ; and Soildown at the end (for correct mountaintable) - ; If tank did not fly at maximum altitude there is no need to soildown to much - lda FloatingAlt - cmp #18 - beq NotHighest - jsr ClearScreenSoilRange + ; and Soildown at the end (for correct mountaintable) + ; If tank did not fly at maximum altitude there is no need to soildown to much + lda FloatingAlt + cmp #18 + beq NotHighest +SoilDownAfterLanding + jsr ClearScreenSoilRange NotHighest - ; calculate range - jsr CalculateSoildown - ; hide tanks and ... - jsr SoilDown2 - ldx TankNr - rts - + ; calculate range + jsr CalculateSoildown + ; hide tanks and ... + jsr SoilDown2 + ldx TankNr + rts + CalculateSoildown - ldx TankNr - clc - lda XtankstableL,x - adc #4 - sta xdraw - lda XtankstableH,x - adc #0 - sta xdraw+1 - mva #$04 ExplosionRadius - jsr CalculateExplosionRange - rts + ldx TankNr + clc + lda XtankstableL,x + adc #4 + sta xdraw + lda XtankstableH,x + adc #0 + sta xdraw+1 + mva #$04 ExplosionRadius + jmp CalculateExplosionRange + ; rts + +SetFuelFullText + mwa #hoverFull LineAddress4x4 + mwa #((ScreenWidth/2)-((hoverFullEnd-hoverFull)*2)) LineXdraw ; centering + mva #hoverFullEnd-hoverFull fx ; length + bne SetTextLevel ; !! length<>0 +SetLowFuelText + mwa #hoverEmpty LineAddress4x4 + mwa #((ScreenWidth/2)-((hoverEmptyEnd-hoverEmpty)*2)) LineXdraw ; centering + mva #hoverEmptyEnd-hoverEmpty fx ; length +SetTextLevel + sec + lda FloatingAlt + sbc #12 + sta LineYdraw + rts + .endp ; ------------------------------------------------- @@ -2989,28 +2871,28 @@ CalculateSoildown ; X - index of the hit tank ldx NumberOfPlayers - dex + dex CheckCollisionWithTankLoop - lda eXistenZ,x - beq DeadTank - ; first we test top and bottom (same with and without shield!) + lda eXistenZ,x + beq DeadTank + ; first we test top and bottom (same with and without shield!) lda ytankstable,x cmp ydraw ; check range bcc BelowTheTank ;(ytankstable,ytankstable+3) sbc #3 ; hitbox height cmp ydraw bcs OverTheTank - ; with or without shield ? + ; with or without shield ? + + lda ActiveDefenceWeapon,x + cmp #ind_Mag_Deflector ; first shielded weapon + bcc CheckCollisionWithNotShieldedTank + cmp #ind_Bouncy_Castle +1 ; last shielded weapon + bcc CheckCollisionWithShieldedTank ; tank with shield is bigger :) + + ;lda ShieldEnergy,x ; there is wrong method to check shield :) + ;bne CheckCollisionWithShieldedTank ; tank with shield is bigger :) - lda ActiveDefenceWeapon,x - cmp #ind_Mag_Deflector__ ; first shielded weapon - bcc CheckCollisionWithNotShieldedTank - cmp #ind_Bouncy_Castle__+1 ; last shielded weapon - bcc CheckCollisionWithShieldedTank ; tank with shield is bigger :) - - ;lda ShieldEnergy,x ; there is wrong method to check shield :) - ;bne CheckCollisionWithShieldedTank ; tank with shield is bigger :) - CheckCollisionWithNotShieldedTank lda xtankstableH,x cmp xdraw+1 @@ -3019,9 +2901,9 @@ CheckCollisionWithNotShieldedTank cmp xdraw @ bcs LeftFromTheTank - ; add 8 double byte - ; now we use Y as low byte and A as high byte of checked position (right edge of tank) - ; it is tricky but fast and much shorter + ; add 8 double byte + ; now we use Y as low byte and A as high byte of checked position (right edge of tank) + ; it is tricky but fast and much shorter clc lda xtankstableL,x adc #TankWidth @@ -3034,9 +2916,9 @@ CheckCollisionWithNotShieldedTank @ bcc RightFromTheTank TankHit - inx - stx HitFlag ; index of hit tank+1 - dex + inx + stx HitFlag ; index of hit tank+1 + dex mwa xdraw XHit mwa ydraw YHit rts ; in X there is an index of the hit tank @@ -3049,23 +2931,23 @@ DeadTank bpl CheckCollisionWithTankLoop rts CheckCollisionWithShieldedTank - ; now we use Y as low byte and A as high byte of checked position (left right edgs of shield) - ; it is tricky but fast and much shorter + ; now we use Y as low byte and A as high byte of checked position (left right edgs of shield) + ; it is tricky but fast and much shorter lda xtankstableL,x - sec - sbc #4 ; 5 pixels more on left side - tay - lda xtankstableH,x - sbc #0 - ; bmi ShieldOverLeftEdge ; I do not know whether to check it. Probably not :) !!! + sec + sbc #4 ; 5 pixels more on left side + tay + lda xtankstableH,x + sbc #0 + ; bmi ShieldOverLeftEdge ; I do not know whether to check it. Probably not :) !!! cmp xdraw+1 bne @+ cpy xdraw @ - bcs LeftFromTheTank - tya ;add 16 double byte + bcs LeftFromTheTank + tya ;add 16 double byte clc - adc #TankWidth+4+4 + adc #TankWidth+4+4 tay lda xtankstableH,x adc #0 @@ -3074,7 +2956,7 @@ CheckCollisionWithShieldedTank cpy xdraw @ bcc RightFromTheTank - bcs TankHit + bcs TankHit .endp ;-------------------------------------------------- CalculateExplosionRange0 @@ -3084,39 +2966,39 @@ CalculateExplosionRange0 ;(for the first or single explosion) ;zero soil fall out ranges - jsr ClearScreenSoilRange + jsr ClearScreenSoilRange ;-------------------------------------------------- .proc CalculateExplosionRange ;-------------------------------------------------- ;calculates total horizontal range of explosion by ;"summing up" ranges of all separate explosions - ; WeaponRangeRight = xdraw + ExplosionRadius - clc - lda xdraw - adc ExplosionRadius - sta WeaponRangeRight - lda xdraw+1 - adc #$00 - sta WeaponRangeRight+1 + ; WeaponRangeRight = xdraw + ExplosionRadius + clc + lda xdraw + adc ExplosionRadius + sta WeaponRangeRight + lda xdraw+1 + adc #$00 + sta WeaponRangeRight+1 ; adw xdraw ExplosionRadius WeaponRangeRight ; Pozor! ExplosionRadius is one byte now ; cpw WeaponRangeRight #screenwidth-1 - cmp #>(screenwidth-1) - bne @+ - lda WeaponRangeRight - cmp #<(screenwidth-1) -@ bcc NotOutOfTheScreenRight + cmp #>(screenwidth-1) + bne @+ + lda WeaponRangeRight + cmp #<(screenwidth-1) +@ bcc NotOutOfTheScreenRight mwa #screenwidth-1 WeaponRangeRight NotOutOfTheScreenRight - ; WeaponRangeLeft = xdraw - ExplosionRadius - sec - lda xdraw - sbc ExplosionRadius - sta WeaponRangeLeft - lda xdraw+1 - sbc #$00 - sta WeaponRangeLeft+1 + ; WeaponRangeLeft = xdraw - ExplosionRadius + sec + lda xdraw + sbc ExplosionRadius + sta WeaponRangeLeft + lda xdraw+1 + sbc #$00 + sta WeaponRangeLeft+1 ; sbw xdraw ExplosionRadius WeaponRangeLeft ; Pozor! ExplosionRadius is one byte now ; lda WeaponRangeLeft+1 bpl NotOutOfTheScreenLeft @@ -3135,27 +3017,27 @@ CheckRangeRight RangesChecked rts -.endp +.endp ;-------------------------------------------------- .proc SetFullScreenSoilRange ; whole screen in range of soil down ;-------------------------------------------------- - lda #0 - sta RangeLeft - sta RangeLeft+1 - mwa #screenwidth RangeRight - rts + lda #0 + sta RangeLeft + sta RangeLeft+1 + mwa #screenwidth RangeRight + rts .endp ;-------------------------------------------------- .proc ClearScreenSoilRange -; cleanup of the soil fall down ranges (left and right) +; cleanup of the soil fall down ranges (left and right) ;-------------------------------------------------- - mwa #screenwidth RangeLeft - lda #0 - sta RangeRight - sta RangeRight+1 - rts + mwa #screenwidth RangeLeft + lda #0 + sta RangeRight + sta RangeRight+1 + rts .endp ;-------------------------------------------------- .proc DecreaseWeaponBeforeShoot @@ -3175,7 +3057,7 @@ RangesChecked ; decreases 1 bullet from a weapon(A) of tank(TankNr) ;-------------------------------------------------- jsr HowManyBullets - beq noBullets ; no bullets - no decreasing (additional check) + beq noBullets ; no bullets - no decreasing (additional check) cpy #0 beq defaultWeapon ; no decreasing Baby Missile sec @@ -3190,7 +3072,7 @@ noBullets .proc HowManyBullets ; in: A <-- Weapon number, TankNr ; out: A <-- How many bullets in the weapon, Y: weapon number -; how many bullets weapon of tank(TankNr) has, Result in A +; how many bullets weapon of tank(TankNr) has, Result in A ;-------------------------------------------------- tay ldx TankNr @@ -3198,29 +3080,10 @@ noBullets sta weaponPointer lda TanksWeaponsTableH,x sta weaponPointer+1 - + lda (weaponPointer),y ; and we have number of bullets in A rts .endp -;-------------------------------------------------- -.proc ShellDelay - lda CONSOL - and #%00000101 ; Start + Option - bne @+ - mva #$40 escFlag -@ and #%00000001 - beq noShellDelay - ldx flyDelay -DelayLoop - lda VCOUNT -@ cmp VCOUNT - beq @- - dex - bne DelayLoop -noShellDelay - rts -.endp - + .ENDIF - \ No newline at end of file