; @com.wudsn.ide.asm.mainsourcefile=scorch.asm .IF *>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 jsr clearscreen ;let the screen be clean mwa #DisplayCopyRom temp mwa #display temp2 mwa #DisplayCopyEnd+1 modify jsr CopyFromROM mwa #OptionsDL dlptrs lda #%00111110 ; normal screen width, DL on, P/M on sta dmactls jsr SetPMWidth mva #TextBackgroundColor COLOR2 jsr ColorsOfSprites 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 lda mountainsDeltaTableH sta mountainDeltaH lda mountainsDeltaTableL sta mountainDeltaL mva #6 NumberOfPlayers jsr PMoutofScreen ;let P/M disappear ;jsr clearscreen ;let the screen be clean (clean-ish already) 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 @- jsr drawtanks ;finally draw tanks pla sta NumberOfPlayers ; -------- mva #0 OptionsY OptionsMainLoop jsr OptionsInversion jsr getkey bit escFlag spl:rts cmp #@kbcode._down ; $f ;cursor down bne OptionsNoDown inc:lda OptionsY cmp #maxoptions bne OptionsMainLoop mva #maxoptions-1 OptionsY jmp OptionsMainLoop OptionsNoDown cmp #@kbcode._up ; $e ;cursor up bne OptionsNoUp dec OptionsY bpl OptionsMainLoop mva #0 OptionsY jmp OptionsMainLoop OptionsNoUp cmp #@kbcode._left ; $6 ;cursor left bne OptionsNoLeft ldx OptionsY dec OptionsTable,X lda OptionsTable,X bpl OptionsMainLoop inc OptionsTable,X jmp OptionsMainLoop OptionsNoLeft cmp #@kbcode._right ; $7 ;cursor right bne OptionsNoRight ldx OptionsY inc OptionsTable,X lda OptionsTable,X cmp #5 ; number of columns in options bne OptionsMainLoop dec OptionsTable,X jmp OptionsMainLoop OptionsNoRight cmp #@kbcode._ret ; $c ;Return key bne OptionsNoReturn rts ; options selected OptionsNoReturn cmp #@kbcode._tab ; Tab key bne OptionsNoTab jsr SelectNextGradient OptionsNoTab jmp OptionsMainLoop .endp .proc SelectNextGradient 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 ;-------- ; inversing selected option (cursor) ;-------- .proc OptionsInversion YPos = temp2 XPos = temp2+1 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 tay ; Y is zero here... OptionsSetMainLoop ldx YPos ; Y position in the menu ;inversing the first few chars of the selected line (OptionsY) cpx OptionsY jsr _inverter cpy #nameWidth-1 bne OptionsSetMainLoop adw temp #nameWidth ldy #0 OptionsLoop lda XPos cmp OptionsTable,x jsr _inverter cpy #optionWidth ; width of the option highlight bne OptionsLoop ldy #0 ; next X position of the adw temp #optionWidth ; width of the option highlight inc:lda XPos cmp #5 ; number of options in a row bne OptionsLoop ; next line ;adw temp #nameWidth ; beginning of the next line mva #0 Xpos tay inc:lda Ypos cmp #maxOptions bne OptionsSetMainLoop rts _inverter beq invertme ; clean inversion otherwise lda (temp),y and #$7f ; clear the top bit sta (temp),y bpl @+ ; JMP invertme lda (temp),y ora #$80 ; set the top bit sta (temp),y @ ; next character in an option iny 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 ;------------------------------------------- ; 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 CopyFromPurchaseAndGameOver mwa #DisplayCopyPurchaseDlROM temp mwa #DisplayCopyPurchase temp2 mwa #DisplayCopyPurchaseEnd+1 modify jmp CopyFromROM ; jsr:rts .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. 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 GoToActivation mva #$ff LastWeapon SetDLI DLIinterruptText ; jsr SetDLI for text (purchase) screen jsr PMoutofScreen mwa #PurchaseDL dlptrs lda #@dmactl(narrow|dma) ; narrow screen width, DL on, P/M off sta dmactls lda #song_supermarket 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 tanknr :3 asl ; 8 chars per name tax NextChar03 lda tanksnames,x sta purchaseTextBuffer+7,y inx iny cpy #$08 bne NextChar03 ; displaying number of active controller port ldy JoystickNumber lda digits+1,y sta purchaseTextBuffer+17 ; and we display cash of the given player ; here we must jump in after each purchase ; to generate again list of available weapons AfterPurchase ; current cash display mva #sfx_purchase sfx_effect ldx tanknr lda moneyL,x sta decimal lda moneyH,x sta decimal+1 mwa #purchaseTextBuffer+26 displayposition jsr displaydec5 ; in xbyte there is the address of the line that ; is being processed now mwa #ListOfWeapons xbyte ldx #$00 ; index of the checked weapon stx HowManyOnTheListOff ; amounts of weapons (shells, bullets) in both lists stx HowManyOnTheListDef jsr CreateList bit isInventory ; bpl ChoosingItemForPurchase lda whichList bne PositionDefensive ; calculate positionOnTheList from the activeWeapon (offensives) ldx tankNr lda activeWeapon,x ldy #0 @ cmp IndexesOfWeaponsL1,y beq ?weaponfound iny cpy #(last_offensive_____ - first_offensive____)+1 ; maxOffensiveWeapons bne @- ; not found apparently? ; TODO: check border case (the last weapon) ldy #0 beq ?weaponFound ; jmp PositionDefensive jsr calcPosDefensive ?weaponFound ; weapon index in Y sty positionOnTheList 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 bpl @+ mva #0 escFlag jmp WaitForKeyRelease ; like jsr ... : rts @ cmp #@kbcode._tab ; $2c ; Tab jeq ListChange cmp #@kbcode._left ; $06 ; cursor left jeq ListChange cmp #@kbcode._ret ; $0c ; Return sne:rts cmp #@kbcode._up ; $e beq PurchaseKeyUp cmp #@kbcode._down ; $f beq PurchaseKeyDown cmp #@kbcode._space ; $21 ; Space jeq PurchaseWeaponNow cmp #@kbcode._right ; $07 ; cursor right jeq PurchaseWeaponNow bne ChoosingItemForPurchase PurchaseKeyUp lda WhichList bpl GoUpOffensive dec PositionOnTheList bpl EndUpX ldy HowManyOnTheListDef dey sty PositionOnTheList jmp MakeOffsetDown GoUpOffensive dec PositionOnTheList bpl MakeOffsetUp ldy HowManyOnTheListOff dey sty PositionOnTheList jmp MakeOffsetDown MakeOffsetUp ; If offset is larger than pointer position, ; it must be equal then. lda PositionOnTheList cmp OffsetDL1 bcs EndUpX ; do not modify the offset sta OffsetDL1 EndUpX jmp ChoosingItemForPurchase PurchaseKeyDown lda WhichList bpl GoDownOffensive inc:lda PositionOnTheList cmp HowManyOnTheListDef bne EndGoDownX ldy #0 sty PositionOnTheList beq MakeOffsetUp GoDownOffensive inc:lda PositionOnTheList cmp HowManyOnTheListOff bne MakeOffsetDown ldy #0 sty PositionOnTheList beq MakeOffsetUp MakeOffsetDown jsr _MakeOffsetDown EndGoDownX jmp ChoosingItemForPurchase _MakeOffsetDown lda OffsetDL1 clc adc #15 ;if offset+16 is lower than the position then it must =16 cmp PositionOnTheList bcs _EndGoDownX sec lda PositionOnTheList sbc #15 sta OffsetDL1 _EndGoDownX rts ; swapping the displayed list and setting pointer to position 0 ListChange mva #0 OffsetDL1 lda WhichList eor #%10000000 ; flip WhichList sta WhichList bne DeffensiveSelected mwa #ListOfWeapons WeaponsListDL lda isInventory beq @+ ; inventory jsr calcPosOffensive jsr _MakeOffsetDown ; set list screen offset jmp ChoosingItemForPurchase @ mva #0 PositionOnTheList jmp ChoosingItemForPurchase DeffensiveSelected mwa #ListOfDefensiveWeapons WeaponsListDL lda isInventory beq @+ jsr calcPosDefensive jmp ChoosingItemForPurchase @ mva #0 positionOnTheList jmp ChoosingItemForPurchase .endp ; ;-------------------------------------------------- .proc CreateList ;-------------------------------------------------- ; Creating full list of the available weapons for displaying ; in X there is an index of the weapon to be checked, ; in 'Xbyte' address of the first char in filled screen line CreateList stx temp ; index of a weapon will be necessary later ; checking if the weapon of the given index is present lda WeaponUnits,x jeq NoWeapon ldy tanknr bit isInventory jmi itIsInventory ; put "Purchase" on the screen mwa #PurchaseDescription PurActDescAddr ; and Title mwa #PurchaseTitle DLPurTitleAddr ; checking if we can afford buying this weapon ldx temp lda moneyH,y cmp WeaponPriceH,x bne @+ lda moneyL,y cmp WeaponPriceL,x @ jcc TooLittleCash ; we have enough cash and the weapon can be ; added to the list ; first parentheses and other special chars ; (it's easier this way) ;ldy #22 ;lda #08 ; "(" ;STA (XBYTE),y ;ldy #32 ;lda #09 ; ")" ;sta (xbyte),y ldy #24 lda #15 ; "/" sta (xbyte),y ldy #30 lda #16 ; "0" sta (xbyte),y ;now number of units (shells) to be purchased adw xbyte #22 displayposition ; 23 chars from the beginning of the line lda WeaponUnits,x sta decimal jsr displaybyte ldx temp ;getting back index of the weapon ; and now price of the weapon adw xbyte #25 displayposition ; 26 chars from the beginning of the line lda WeaponPriceL,x sta decimal lda WeaponPriceH,x sta decimal+1 jsr displaydec5 ldy #25 ; overwrite first digit (allways space - no digit :) ) lda #04 ; "$" sta (xbyte),y jmp notInventory itIsInventory ; put "Activate" on the screen mwa #ActivateDescription PurActDescAddr ; and Title mwa #InventoryTitle DLPurTitleAddr ldx temp lda TanksWeaponsTableL,y sta weaponPointer lda TanksWeaponsTableH,y sta weaponPointer+1 ldy temp lda (weaponPointer),y jeq noWeapon ; clear price area ldy #21 ; beginning of the price area lda #0 @ sta (XBYTE),y iny cpy #32 ; end of price bne @- notInventory ; number of posessed shells lda temp ; weapon index again jsr HowManyBullets sta decimal adw xbyte #1 displayposition jsr displaybyte ldx temp ;weapon index ; now symbol of the weapon lda WeaponSymbols,x ldy #$4 ; 4 chars from the beginning of the line sta (xbyte),y ; and now name of the weapon and finisheeeedd !!!! mva #0 temp+1 ; this number is only in X ; times 16 (it's length of the names of weapons) ldy #3 ; Rotate 4 times @ asl temp rol temp+1 dey bpl @- adw temp #NamesOfWeapons-6 weaponPointer ldy #6 ; from 6th char on screen @ lda (weaponPointer),y sta (xbyte),y iny cpy #(16+6) bne @- ; in X there is what we need (weapon index) ; If on screen after the purchase there is still ; present the weapon purchased recently, ; the pointer must point to it. bit lastWeapon bpl @+ ; if == $ff => first run, jump to top mva #0 PositionOnTheList beq NotTheSameAsLastTime @ cpx LastWeapon bne NotTheSameAsLastTime bit WhichList bmi @+ lda HowManyOnTheListOff sta PositionOnTheList jmp NotTheSameAsLastTime @ lda HowManyOnTheListDef sta PositionOnTheList NotTheSameAsLastTime ; increase appropriate counter txa cpx #last_offensive_____+1 bcs DefenceList ldy HowManyOnTheListOff sta IndexesOfWeaponsL1,y inc HowManyOnTheListOff bne NextLineOfTheList DefenceList ldy HowManyOnTheListDef sta IndexesOfWeaponsL2,y inc HowManyOnTheListDef ; If everything is copied then next line NextLineOfTheList adw xbyte #32 TooLittleCash NoWeapon ; next weapon. If no more weapons then finish! inx 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 jne CreateList ; offset may be only too big ; (because after purchase list will never be longer) ; check it and modify if necessary. ; If offset is larger than position of the pointer, ; it must be equal. lda PositionOnTheList cmp OffsetDL1 bcs WeHaveOffset ; do not modify offset sta OffsetDL1 WeHaveOffset ; now we have to erase empty position of both lists. ; Multiply number on list 1 by 32 and set address ; of the first erased char. lda HowManyOnTheListOff sta xbyte ; multiplier (temporarily here, it will be erased anyway) 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 tya ; now there is zero here sta (xbyte),y inw xbyte jmp ClearList1 ListCleared1 ; And the same we do with the second list ; Multiply number on list 1 by 32 and set address ; of the first erased char. lda HowManyOnTheListDef sta xbyte ; multiplier (temporarily here, it will be erased anyway) 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 #ListOfDefensiveWeapons ldy #0 ClearList2 cpw xbyte #ListOfDefensiveWeaponsEnd beq ListCleared2 tya ; now there is zero here sta (xbyte),y inw xbyte jmp ClearList2 ListCleared2 ; here we have pretty cool lists and there is no brute force ; screen clearing at each list refresh ; (it was very ugly - I checked it :) rts .endp ;-------------------------------------------------- .proc PurchaseWeaponNow ; weapon purchase routne increases number of possessed bullets ; decreases cash and jumps to screen refresh ;-------------------------------------------------- bit isInventory bmi inventorySelect bit WhichList bmi PurchaseDeffensive ; here we purchase the offensive weapon ldy PositionOnTheList lda IndexesOfWeaponsL1,y jmp PurchaseAll PurchaseDeffensive ldy PositionOnTheList lda IndexesOfWeaponsL2,y PurchaseAll ; after getting weapon index the routine is common for all ldx tanknr tay ; weapon index is in Y sec lda moneyL,x ; substracting from posessed money sbc WeaponPriceL,y ; of price of the given weapon sta moneyL,x lda moneyH,x sbc WeaponPriceH,y sta moneyH,x 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 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 GetRandomDefensive randomize ind_Battery________ last_defensive_____ tay ; lda WeaponUnits,y ; check if weapon exist ; beq GetRandomDefensive NoSuprise lda TanksWeaponsTableL,x sta weaponPointer lda TanksWeaponsTableH,x sta weaponPointer+1 clc lda (weaponPointer),y ; and we have number of posessed bullets of the weapon adc WeaponUnits,y sta (weaponPointer),y ; and we added appropriate number of bullets cmp #100 ; but there should be no more than 99 bullets bcc LessThan100 lda #99 sta (weaponPointer),y LessThan100 mva #0 PositionOnTheList ; to move the pointer to the top when no more monies jmp Purchase.AfterPurchase inventorySelect bit whichList bmi invSelectDef ldy PositionOnTheList lda IndexesOfWeaponsL1,y ldx tankNr sta activeWeapon,x jmp WaitForKeyRelease ; rts invSelectDef ldy PositionOnTheList lda IndexesOfWeaponsL2,y tay ldx tankNr cmp #ind_Battery________ bne NotBattery ; if activate battery, we do it differently mva #sfx_battery sfx_effect phy mva #99 Energy,x jsr MaxForceCalculate ply jmp DecreaseDefensive ; bypass activation NotBattery 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 :) jmp DecreaseDefensive ; bypass activation NoAutoDefense cmp #ind_Lazy_Boy_______ bne NoLazyBoy ; Lazy Boy - do it like battery mva #sfx_lazy_boys sfx_effect phy jsr PrepareAIShoot jsr FindBestTarget2 ; find nearest tank neighbour jsr LazyAim ply lda #%00000000 sta TestFlightFlag ; set "visual aiming" off jmp DecreaseDefensive ; bypass activation NoLazyBoy cmp #ind_Lazy_Darwin____ bne NoLazyDarwin ; Lazy Darwin - do it like battery mva #sfx_lazy_boys sfx_effect phy jsr PrepareAIShoot jsr FindBestTarget3 ; find target with lowest energy jsr LazyAim ply lda #%10000000 sta TestFlightFlag ; set "visual aiming" on jmp DecreaseDefensive ; bypass activation NoLazyDarwin 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 mva #LongBarrel BarrelLength,x bne DecreaseDefensive ; bypass activation NotBarrel cmp #ind_White_Flag_____ bne NotWhiteFlag cmp ActiveDefenceWeapon,x bne NoDeactivateWhiteFlag mva #sfx_white_flag sfx_effect lda #$00 ; if try to activate activated White Flag then deactivate Defence sta ActiveDefenceWeapon,x sta ShieldEnergy,x beq DefActivationEnd NotWhiteFlag NoDeactivateWhiteFlag ; activate new defensive sta ActiveDefenceWeapon,x ; set defensive energy lda DefensiveEnergy,y sta ShieldEnergy,x DecreaseDefensive ; decrease number of defensives lda TanksWeaponsTableL,x sta weaponPointer lda TanksWeaponsTableH,x sta weaponPointer+1 lda (weaponPointer),y sec sbc #1 sta (weaponPointer),y DefActivationEnd jmp WaitForKeyRelease ; 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 lda NewAngle sta AngleTable,x rts .endp ; ----------------------------------------------------- .proc calcPosDefensive ; calculate positionOnTheList from the activeWeapon (defensives) ldx tankNr lda ActiveDefenceWeapon,x beq ?noWeaponActive ldy #0 ; min defensive weapon @ cmp IndexesOfWeaponsL2,y beq ?weaponfound iny cpy #(last_defensive_____ - first_defensive____)+1 ; maxDefensiveWeapon bne @- ; not found apparently? ; TODO: check border case (the last weapon) ?noWeaponActive ldy #0 ?weaponFound cpy howManyOnTheListDef bcs ?noWeaponActive sty positionOnTheList rts .endp .proc calcPosOffensive ; calculate positionOnTheList from the activeWeapon (defensives) ldx tankNr lda ActiveWeapon,x beq ?noWeaponActive ldy #0 ; min defensive weapon @ cmp IndexesOfWeaponsL1,y beq ?weaponfound iny cpy #(last_offensive_____ - first_offensive____) ; maxOffensiveWeapon bne @- ; not found apparently? ; TODO: check border case (the last weapon) ?noWeaponActive ldy #0 ?weaponFound cpy howManyOnTheListOff bcs ?noWeaponActive 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 ldy #$00 EraseLoop tya ; lda #$00 sta (xbyte),y adw xbyte #32 ; narrow screen dex bpl EraseLoop ; now let's check which list is active now bit WhichList bpl CharToList1 ; we are on the second list (deffensive) ; so there is no problem with scrolling mwa #ListOfDefensiveWeapons xbyte ldx PositionOnTheList beq SelectList2 ; if there is 0 we add nothing AddLoop2 adw xbyte #32 ; narrow screen dex bne AddLoop2 SelectList2 lda #$7f ; little char (tab) - this is the pointer sta (xbyte),y ; now we clear up and down arrows indicating more content below or above screen ldx #EmptyLine stx MoreUpdl sty MoreUpdl+1 stx MoreDowndl sty MoreDowndl+1 rts CharToList1 ; we putchar on list 1 ; and later set-up list itself mwa #ListOfWeapons xbyte ldx PositionOnTheList beq SelectList1 ; if there is 0 we add nothing AddLoop1 adw xbyte #32 ; narrow screen dex bne AddLoop1 SelectList1 lda #$7f ; pointer = little char = (tab) sta (xbyte),y ; now moving the window basing on given offset mwa #ListOfWeapons xbyte ldx OffsetDL1 beq SetWindowList1 ; if zero then add nothing LoopWindow1 adw xbyte #32 ; narrow screen dex bne LoopWindow1 SetWindowList1 mwa xbyte WeaponsListDL ; and we change Display List ; we show screen line with arrows meaning that ; you can scroll the list up ldx #EmptyLine lda OffsetDL1 beq NoArrowUp ldx #MoreUp NoArrowUp stx MoreUpdl sty MoreUpdl+1 ; the same, bu scrolling down lda HowManyOnTheListOff ldx #EmptyLine sec sbc #17 ; ???? bmi NoArrowDown cmp OffsetDL1 bcc NoArrowDown ldx #MoreDown NoArrowDown stx MoreDowndl sty MoreDowndl+1 rts .endp ; ----------------------------------------------------- .proc EnterPlayerNames ;entering names of players mwa #NameDL dlptrs lda #%00110001 ; narrow screen width, DL on, P/M off sta dmactls SetDLI DLIinterruptText ; jsr SetDLI for text (names) screen 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 ; ----------------------------------------------------- jsr PMoutofScreen ; display tank number ldx tanknr lda skillTable,x sta difficultyLevel 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 cpy #8 bne @- endOfTankName @ lda NameAdr,y and #$7f bne LastNameChar dey bpl @- LastNameChar cpy #7 beq @+ iny @ sty PositionInName CheckKeys jsr HighlightLevel ; setting choosen level of the opponent (Moron, etc) ldx TankNr lda JoyNumber,x tay 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 jsr getkey bit escFlag spl:rts .IF TARGET = 800 ; only the A800 has a keyboard ; is the char to be recorded? ldx #keycodesEnd-keycodes ;table was 38 chars long IsLetter cmp keycodes,x beq YesLetter dex bpl IsLetter bmi CheckFurtherX01 ; if not in the table ; we check cursors and (Return) YesLetter lda scrcodes,x ; we have screen code of the char ldx PositionInName sta NameAdr,x inx cpx #$08 ; is there 8 characters? bne @+ dex @ stx PositionInName ; if not, we store jmp CheckKeys .ENDIF CheckFurtherX01 ; here we check Tab, Return and Del cmp #@kbcode._ret ; $0c ; Return jeq EndOfNick cmp #@kbcode._tab ; $2c ; Tab beq ChangeOfJoyUp cmp #@kbcode._right ; $7 ;cursor right beq ChangeOfLevelUp cmp #@kbcode._left ; $6 ;cursor left beq ChangeOfLevelDown cmp #@kbcode._down ; $f ;cursor down beq ChangeOfLevel3Up cmp #@kbcode._up ; $e ;cursor up beq ChangeOfLevel3Down 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 lda NameAdr,x and #$7f bne LastIsNotSpace ; last char not empty - first clear last char (no go back) NotLastChar dex LastIsNotSpace FirstChar stx PositionInName lda #0 sta NameAdr,x 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 jmp CheckKeys ;---- ChangeOfLevelUp ; change difficulty level of computer opponent inc:lda DifficultyLevel cmp #9 ; 9 levels are possible bne DoNotLoopLevelUp mva #$0 DifficultyLevel DoNotLoopLevelUp jmp CheckKeys ;---- ChangeOfLevelDown dec:lda DifficultyLevel bpl DoNotLoopLevelDown mva #$8 DifficultyLevel DoNotLoopLevelDown jmp CheckKeys ;---- ChangeOfLevel3Up adb DifficultyLevel #3 cmp #9 bcc DoNotLoopLevel3Up sbb DifficultyLevel #9 DoNotLoopLevel3Up jmp CheckKeys ;---- ChangeOfLevel3Down sbb DifficultyLevel #3 bpl @+ adb DifficultyLevel #9 @ jmp CheckKeys ;---- ChangeOfShapeUp 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...) mva #0 pressTimer ; reset WaitForLongPress lda STRIG0 ; wait only for joy long press bne ShortJoyPress lda pressTimer cmp #25 ; 1/2s bcc WaitForLongPress jsr EnterNameByJoy jmp CheckKeys ShortJoyPress ; storing name of the player and its level ; level of the computer opponent goes to ; the table of levels (difficulties) ldx tanknr lda 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 NameAdr,y and #$7F ; remove inverse (Cursor) dey bpl @- tay beq MakeDefaultName ldy #0 nextchar04 lda 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 CursorDisplay ldy #7 CursorLoop 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 @+ ora #$80 ; place cursor @ 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) SearchCharacter 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 CharacterFound ; 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 notpressedJoy ;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 NoRight 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 NoUp 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 GoToMainLoop sty PositionInName jmp EnterNameByJoy .endp ;-------------------------------------------------- .proc HighlightLevel ; this routine highlights the choosen ; level of the computer opponent ldx #8 ; 9 possible levels CheckNextLevel01 lda LevelNameBeginL,x ; address on the screen sta temp lda LevelNameBeginH,x sta temp+1 ldy #9 ; flip 10 chars to inverse video cpx DifficultyLevel ; is it the choosen level? bne NotThisLevel ; change to inverse, because it is it! InverseFurther lda (temp),y ora #$80 sta (temp),y dey bpl InverseFurther bmi CheckNextLevel ; Check Next Level NotThisLevel lda (temp),y and #$7f sta (temp),y dey bpl NotThisLevel CheckNextLevel dex bpl CheckNextLevel01 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 Display4x4AboveTank ; ; Displays texts using PutChar4x4 above tank and mountains. ; Pretty cool, eh! ;parameters are: ;Y - number of tank above which text is displayed ;fx - length of text ;LineAddress4x4 - address of the text ;lets calculate position of the text first! ;that's easy because we have number of tank ;and xtankstableL and H keep X position of a given tank lda xtankstableL,y sta temp lda xtankstableH,y sta temp+1 ;now we should substract length of the text-1 ;temp2 = (fx-1)*2 ldy fx dey tya asl sta temp2 mva #0 temp2+1 ;now we have HALF length in pixels ;stored in temp2 ;here we assume max length of text ;to display is 127 chars, but later it turns out it must be max 63! sbw temp temp2 ; here begin of the text is in TEMP !!!! ;now we should check overflows ;lda temp+1 ; opty bpl DOTNnotLessThanZero ;less than zero, so should be zero mwa #0 temp beq DOTNnoOverflow DOTNnotLessThanZero ;so check if end larger than screenwidth lda fx asl asl ;length in pixels - ;text length max 63 chars !!!!!!!! clc adc temp sta temp2 lda #0 adc temp+1 sta temp2+1 ;now in temp2 is end of the text in pixels ;so check if not greater than screenwitdth cpw temp2 #screenwidth bcc DOTNnoOverflow ;if end is greater than screenwidth ;then screenwidth - length is fine lda fx asl asl sta temp mva #0 temp+1 sec lda #<(screenwidth-1) sbc temp sta temp lda #>(screenwidth-1) sbc temp+1 sta temp+1 DOTNnoOverflow ;here in temp we have really good x position of text mwa temp LineXdraw ;now let's get y position ;we will try to put text as low as possible ;just above mountains (so mountaintable will be checked) lda fx asl asl tay ;in temp there still is X position of text ;if we add temp and Y we will get end of the text ;so, lets go through mountaintable and look for ;the lowest value within ;Mountaitable+temp and Mountaitable+temp+Y adw temp #MountainTable mva #screenheight temp2 ;initialisation of the lowest value DOTLowestMountainValueLoop lda (temp),y cmp temp2 bcs DOTOldLowestValue ;old lowest value ;new lowest value sta temp2 DOTOldLowestValue dey cpy #$ff bne DOTLowestMountainValueLoop sec lda temp2 sbc #(4+9) ;9 pixels above ground (and tanks...) sta LineYdraw jmp TypeLine4x4.noLengthNoColor ; rts .endp ;-------------------------------------------------------- .proc DisplayOffensiveTextNr ; ldx TextNumberOff lda talk.OffensiveTextTableL,x sta LineAddress4x4 lda talk.OffensiveTextTableH,x sta LineAddress4x4+1 inx ; the next text lda talk.OffensiveTextTableH,x sta temp+1 lda talk.OffensiveTextTableL,x sta temp ; opty possible ; substract address of the next text from previous to get text length sbw temp LineAddress4x4 temp2 mva temp2 fx ;jsr Display4x4AboveTank ;rts ; POZOR !!! .endp ;-------------------------------------------------------- .proc DisplayTankNameAbove ; lda tankNr :3 asl ; *8 clc adc #Tanksnames sta temp+1 ; TextAddress+1 mwa temp LineAddress4x4 ;find length of the tank's name ldy #7 @ lda (temp),y bne end_found dey bne @- end_found iny sty fx ldy tankNr jsr Display4x4AboveTank rts .endp ;------------------------------- .proc TypeLine4x4 ; ;------------------------------- ;this routine prints line of length `fx` ;address in LineAddress4x4 ;starting from LineXdraw, LineYdraw lda #14 ; default length of 4x4 texts sta fx variableLength lda #$ff ; $ff - visible characters, $00 - clearing staplot4x4color sta plot4x4color noLengthNoColor ldy #0 sty LineCharNr TypeLine4x4Loop ldy LineCharNr lda (LineAddress4x4),y and #$3f ;always CAPITAL letters sta CharCode4x4 mwa LineXdraw dx mva LineYdraw dy mva #0 dy+1 ; dy is 2 bytes value jsr PutChar4x4 ;type empty pixels as well! adw LineXdraw #4 inc:lda LineCharNr cmp fx bne TypeLine4x4Loop EndOfTypeLine4x4 rts .endp ;-------------------------------- .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 ;bottom frame mva ResultY LineYdraw jsr TL4x4_bottom jsr GetKey cmp #@kbcode._Y ; $2b ; "Y" bne @+ mva #$80 escFlag bne skip01 @ mva #0 escFlag skip01 jsr WaitForKeyRelease ;clean mva #3 di mva #4 ResultY @ mva #$ff plot4x4color mwa #lineClear LineAddress4x4 jsr _sep_opty dec di bne @- quit_areyousure rts .endp .proc _sep_opty mwa #((ScreenWidth/2)-(8*4)) LineXdraw ; centering mva ResultY LineYdraw jsr TypeLine4x4 adb ResultY #4 ;next line rts .endp ;-------------------------------- .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 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 sta ResultY loplop ;@ mwa #lineClear LineAddress4x4 jsr _sep_opty dec di bne loplop ;@- dec fs jne seppuku_loop quit_seppuku 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 WaitForKeyRelease jsr ClearScreen jsr ClearPMmemory jsr PrepareCredits jsr GameOverResultsClear jsr CopyFromPurchaseAndGameOver mwa #GameOverDL dlptrs 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 ColorsOfSprites mva #0 COLOR1 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 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 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 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 @- 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 ; puts name of the tank on the screen ldy #$03 lda TankNr :3 asl ; 8 chars per name tax NextChar lda tanksnames,x sta (temp),y inx iny cpy #$08+3 bne NextChar ; 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 ldx TankNr lda DirectHitsL,x sta decimal lda DirectHitsH,x sta decimal+1 adw temp #19 displayposition jsr displaydec5 mva #0 displayposition ; overwrite first digit ; put earned money on the screen ldx TankNr lda EarnedMoneyL,x sta decimal lda EarnedMoneyH,x sta decimal+1 adw temp #30 displayposition jsr displaydec5 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 AllLinesReady ldx #(MaxPlayers-1) MakeAllTanksVisible lda #99 sta eXistenZ,x lda #0 sta ActiveDefenceWeapon,x dex bpl MakeAllTanksVisible jsr SetStandardBarrels ; start music and animations RmtSong song_ending_looped ; initial tank positions randomization ldx #(MaxPlayers-1) ;maxNumberOfPlayers-1 @ jsr RandomizeTankPos dex bpl @- MainTanksFloatingLoop ; main tanks floating loop ldx #(MaxPlayers-1) ;maxNumberOfPlayers-1 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 NoEraseTank ldx TankNr inc Ytankstable,x lda ActiveDefenceWeapon,x beq NotFastTank :3 inc Ytankstable,x NotFastTank lda Ytankstable,x ; cmp #32 ; tank over screen - not visible cmp #(80-7) ; tank under screen - new tank randomize bcs TankUnderScreen cmp #(72-7) ; tank under screen but.... parachute bcs DrawOnlyParachute bcc TankOnScreen TankUnderScreen jsr RandomizeTankPos TankOnScreen jsr DrawTankNr DrawOnlyParachute lda ActiveDefenceWeapon,x bne FastTank jsr DrawTankParachute FastTank ; ldx TankNr dex bpl AllTanksFloatingDown jsr IsKeyPressed bne MainTanksFloatingLoop ; neverending loop mva #$00 ScrollFlag ; credits scroll off jsr MakeDarkScreen jsr GameOverResultsClear rts RandomizeTankPos randomize 10 (32-7) ; 10 not 8 - barrel !! :) sta Ytankstable,x randomize 0 180 sta AngleTable,x randomize 0 (49-8) and #%11111110 ; correction for PMG 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 rts NowFastTank lda #1 sta ActiveDefenceWeapon,x rts GameOverResultsClear 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 MainRewriteLoop 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 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 LastCharWritten 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 NextLine adw temp2 #40 jmp MainRewriteLoop EndOfCredits mwa #Credits DLCreditsAddr ; set address in DL to first line rts .endp ;------------------------------------------------- .proc DisplayStatus ;------------------------------------------------- ; displaying number of active controller port ldy JoystickNumber lda digits+1,y sta statusBuffer+17 ;--------------------- ;displaying symbol of the weapon ;--------------------- ;display name and symbol of the weapon ;statusBuffer+18 - symbol (1 char) ;statusBuffer+20 - quantity left ;statusBuffer+23 - name ldx TankNr ldy ActiveWeapon,x lda WeaponSymbols,y sta statusBuffer+19 ;--------------------- ;displaying quantity of the given weapon ;--------------------- lda ActiveWeapon,x jsr HowManyBullets sta decimal mwa #statusBuffer+21 displayposition jsr displaybyte ;--------------------- ;displaying name of the weapon ;--------------------- ldx TankNr lda ActiveWeapon,x sta temp ;get back number of the weapon mva #0 temp+1 ; times 16 (because this is length of weapon name) ldy #3 ; shift left 4 times @ aslw temp dey bpl @- adw temp #NamesOfWeapons ldy #15 @ lda (temp),y sta statusBuffer+24,y dey bpl @- ;--------------------- ;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 @ sta statusBuffer+80+21 lda #$08 ; ( sta statusBuffer+80+22 lda #$09 ; ) sta statusBuffer+80+39 lda ActiveDefenceWeapon,x bne ActiveDefence ; clear brackets lda #space sta statusBuffer+80+22 sta statusBuffer+80+39 mwa #emptyLine temp jmp ClearingOnly ActiveDefence sta temp ;get back number of the weapon mva #0 temp+1 ; times 16 (because this is length of weapon name) ldy #3 ; shift left 4 times @ aslw temp dey bpl @- adw temp #NamesOfWeapons ClearingOnly ldy #15 @ lda (temp),y sta statusBuffer+40+40+23,y dey bpl @- ;--------------------- ;displaying the energy of a tank ;--------------------- lda Energy,x sta decimal mwa #statusBuffer+48 displayposition jsr displaybyte ;--------------------- ;displaying the energy of a tank shield (if exist) ;--------------------- ; clear (if no shield) lda #space sta statusBuffer+40+10 sta statusBuffer+40+11 sta statusBuffer+40+12 sta statusBuffer+40+13 ; check shield energy and display it ldx TankNr lda ActiveDefenceWeapon,x beq NoDefenceWeapon lda ShieldEnergy,x beq NoShieldEnergy sta decimal ; displayed value lda #$08 ; ( sta statusBuffer+40+10 mwa #statusBuffer+40+11 displayposition jsr displaybyte lda #$09 ; ) sta statusBuffer+40+13 NoDefenceWeapon NoShieldEnergy ;========================= ;display Wind ;========================= mwa Wind temp lda Wind+3 ; highest byte of 4 byte wind bmi DisplayLeftWind lda #$7f ; (tab) char sta statusBuffer+80+20 lda #space sta statusBuffer+80+17 beq DisplayWindValue DisplayLeftWind sec ; Wind = -Wind lda #$00 sbc temp sta temp lda #$00 sbc temp+1 sta temp+1 lda #$7e ;(del) char sta statusBuffer+80+17 lda #space sta statusBuffer+80+20 DisplayWindValue :4 lsrw temp ;divide by 16 to have a nice value on a screen lda temp sta decimal mwa #statusBuffer+80+18 displayposition jsr displaybyte ;========================= ;display round number ;========================= lda CurrentRoundNr sta decimal mwa #statusBuffer+80+7 displayposition jsr displaybyte ;decimal (byte), displayposition (word) ;========================= ;display Force ;========================= ldx TankNr lda ForceTableL,x sta decimal lda ForceTableH,x sta decimal+1 mwa #statusBuffer+40+35 displayposition jsr displaydec5 ;========================= ;display Angle ;========================= displayAngle ldx TankNr lda AngleTable,x cmp #90 beq VerticallyUp bcs AngleToLeft AngleToRight ; now we have values from 0 to 89 and right angle sta decimal lda #$7f ; (tab) character sta statusBuffer+40+25 lda #space sta statusBuffer+40+22 beq AngleDisplay AngleToLeft sec lda #180 sbc AngleTable,x ; angles 180 - 91 converted to 0 - 89 sta decimal lda #$7e ;(del) char sta statusBuffer+40+22 lda #space sta statusBuffer+40+25 beq AngleDisplay VerticallyUp ; now we have value 90 sta decimal lda #space sta statusBuffer+40+25 sta statusBuffer+40+22 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 rts .endp ;------------------------------------------------- .proc RoundOverSprites ; fill sprites with bytes ldy numberOfPlayers dey lda gameOverSpritesTop,y sta temp ; clean the whole sprite lda #0 tax @ sta PMGraph+$400,x 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 @ sta PMGraph+$400,x sta PMGraph+$500,x inx cpx temp bne @- GOSbeg = 112 mva #GOSbeg hposp0 mva #GOSbeg+12 hposp0+1 mva #15 PCOLR0 sta PCOLR1 rts .endp .endif