Files
scorch_src/textproc.asm
T

2598 lines
57 KiB
NASM

; @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
jmp OptionsFinished
OptionsNoReturn
cmp #@kbcode._tab ; Tab key
bne OptionsNoTab
lda Gradient
eor #$80
sta Gradient
OptionsNoTab
jmp OptionsMainLoop
OptionsFinished
;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
;--------
; 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
;-------------------------------------------
; 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
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
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
ldy #>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
ldy #>EmptyLine
lda OffsetDL1
beq NoArrowUp
ldx #<MoreUp
ldy #>MoreUp
NoArrowUp
stx MoreUpdl
sty MoreUpdl+1
; the same, bu scrolling down
lda HowManyOnTheListOff
ldx #<EmptyLine
ldy #>EmptyLine
sec
sbc #17 ; ????
bmi NoArrowDown
cmp OffsetDL1
bcc NoArrowDown
ldx #<MoreDown
ldy #>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 ; TextAddress
lda #0
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