From 46c2a38c7c55ff01e8787dfd624cb1c771248b6c Mon Sep 17 00:00:00 2001 From: xCrystal Date: Wed, 1 Apr 2015 11:41:20 +0200 Subject: Rename battle files and split move effects Part 2 5.asm, 9.asm, and a.asm --- engine/battle/5.asm | 77 --------- engine/battle/9.asm | 190 ---------------------- engine/battle/a.asm | 39 ----- engine/battle/core.asm | 4 +- engine/battle/moveEffects/focus_energy_effect.asm | 24 +++ engine/battle/moveEffects/leech_seed_effect.asm | 39 +++++ engine/battle/moveEffects/substitute_effect.asm | 77 +++++++++ engine/battle/print_type.asm | 52 ++++++ engine/battle/save_trainer_name.asm | 112 +++++++++++++ main.asm | 8 +- 10 files changed, 311 insertions(+), 311 deletions(-) delete mode 100755 engine/battle/5.asm delete mode 100755 engine/battle/9.asm delete mode 100755 engine/battle/a.asm create mode 100644 engine/battle/moveEffects/focus_energy_effect.asm create mode 100644 engine/battle/moveEffects/leech_seed_effect.asm create mode 100644 engine/battle/moveEffects/substitute_effect.asm create mode 100644 engine/battle/print_type.asm create mode 100644 engine/battle/save_trainer_name.asm diff --git a/engine/battle/5.asm b/engine/battle/5.asm deleted file mode 100755 index ef3e1362..00000000 --- a/engine/battle/5.asm +++ /dev/null @@ -1,77 +0,0 @@ -SubstituteEffectHandler: ; 17dad (5:7dad) - ld c, 50 - call DelayFrames - ld hl, wBattleMonMaxHP - ld de, wPlayerSubstituteHP - ld bc, W_PLAYERBATTSTATUS2 - ld a, [H_WHOSETURN] - and a - jr z, .notEnemy - ld hl, wEnemyMonMaxHP - ld de, wEnemySubstituteHP - ld bc, W_ENEMYBATTSTATUS2 -.notEnemy - ld a, [bc] ;load flags - bit HasSubstituteUp, a ;user already has substitute? - jr nz, .alreadyHasSubstitute ;skip this code if so - ;user doesn't have a substitute [yet] - push bc - ld a, [hli] ;load max hp - ld b, [hl] - srl a ;max hp / 4, [quarter health to remove from user] - rr b - srl a - rr b - push de - ld de, wBattleMonHP - wBattleMonMaxHP - add hl, de ; point hl to current HP - pop de - ld a, b - ld [de], a ;save copy of HP to subtract in ccd7/ccd8 [how much HP substitute has] - ld a, [hld] ;load current hp - sub b ;subtract [max hp / 4] - ld d, a ;save low byte result in D - ld a, [hl] - sbc a, 0 ;borrow from high byte if needed - pop bc - jr c, .notEnoughHP ;underflow means user would be left with negative health - ;bug: note since it only brances on carry, it will possibly leave user with 0HP -.userHasZeroOrMoreHP - ldi [hl], a ;store high byte HP - ld [hl], d ;store low byte HP - ld h, b - ld l, c - set HasSubstituteUp, [hl] ;set bit 4 of flags, user now has substitute - ld a, [W_OPTIONS] ;load options - bit 7, a ;battle animation is enabled? - ld hl, PlayCurrentMoveAnimation ;animation enabled: 0F:7BA8 - ld b, BANK(PlayCurrentMoveAnimation) - jr z, .animationEnabled - ld hl, AnimationSubstitute ;animation disabled: 1E:56E0 - ld b, BANK(AnimationSubstitute) -.animationEnabled - call Bankswitch ;jump to routine depending on animation setting - ld hl, SubstituteText - call PrintText - ld hl, DrawHUDsAndHPBars - ld b, BANK(DrawHUDsAndHPBars) - jp Bankswitch -.alreadyHasSubstitute - ld hl, HasSubstituteText - jr .printText -.notEnoughHP - ld hl, TooWeakSubstituteText -.printText - jp PrintText - -SubstituteText: ; 17e1d (5:7e1d) - TX_FAR _SubstituteText - db "@" - -HasSubstituteText: ; 17e22 (5:7e22) - TX_FAR _HasSubstituteText - db "@" - -TooWeakSubstituteText: ; 17e27 (5:7e27) - TX_FAR _TooWeakSubstituteText - db "@" diff --git a/engine/battle/9.asm b/engine/battle/9.asm deleted file mode 100755 index e7265f41..00000000 --- a/engine/battle/9.asm +++ /dev/null @@ -1,190 +0,0 @@ -; [wd0b5] = pokemon ID -; hl = dest addr -PrintMonType: ; 27d6b (9:7d6b) - call GetPredefRegisters - push hl - call GetMonHeader - pop hl - push hl - ld a, [W_MONHTYPE1] - call PrintType - ld a, [W_MONHTYPE1] - ld b, a - ld a, [W_MONHTYPE2] - cp b - pop hl - jr z, EraseType2Text - ld bc, SCREEN_WIDTH * 2 - add hl, bc - -; a = type -; hl = dest addr -PrintType: ; 27d89 (9:7d89) - push hl - jr PrintType_ - -; erase "TYPE2/" if the mon only has 1 type -EraseType2Text: ; 27d8c (9:7d8c) - ld a, " " - ld bc, $13 - add hl, bc - ld bc, $6 - jp FillMemory - -PrintMoveType: ; 27d98 (9:7d98) - call GetPredefRegisters - push hl - ld a, [W_PLAYERMOVETYPE] -; fall through - -PrintType_: ; 27d9f (9:7d9f) - add a - ld hl, TypeNames - ld e, a - ld d, $0 - add hl, de - ld a, [hli] - ld e, a - ld d, [hl] - pop hl - jp PlaceString - -INCLUDE "text/type_names.asm" - -SaveTrainerName: ; 27e4a (9:7e4a) - ld hl,TrainerNamePointers - ld a,[W_TRAINERCLASS] - dec a - ld c,a - ld b,0 - add hl,bc - add hl,bc - ld a,[hli] - ld h,[hl] - ld l,a - ld de,wcd6d -.CopyCharacter - ld a,[hli] - ld [de],a - inc de - cp "@" - jr nz,.CopyCharacter - ret - -TrainerNamePointers: ; 27e64 (9:7e64) -; what is the point of these? - dw YoungsterName - dw BugCatcherName - dw LassName - dw W_TRAINERNAME - dw JrTrainerMName - dw JrTrainerFName - dw PokemaniacName - dw SuperNerdName - dw W_TRAINERNAME - dw W_TRAINERNAME - dw BurglarName - dw EngineerName - dw JugglerXName - dw W_TRAINERNAME - dw SwimmerName - dw W_TRAINERNAME - dw W_TRAINERNAME - dw BeautyName - dw W_TRAINERNAME - dw RockerName - dw JugglerName - dw W_TRAINERNAME - dw W_TRAINERNAME - dw BlackbeltName - dw W_TRAINERNAME - dw ProfOakName - dw ChiefName - dw ScientistName - dw W_TRAINERNAME - dw RocketName - dw CooltrainerMName - dw CooltrainerFName - dw W_TRAINERNAME - dw W_TRAINERNAME - dw W_TRAINERNAME - dw W_TRAINERNAME - dw W_TRAINERNAME - dw W_TRAINERNAME - dw W_TRAINERNAME - dw W_TRAINERNAME - dw W_TRAINERNAME - dw W_TRAINERNAME - dw W_TRAINERNAME - dw W_TRAINERNAME - dw W_TRAINERNAME - dw W_TRAINERNAME - dw W_TRAINERNAME - -YoungsterName: ; 27ec2 (9:7ec2) - db "YOUNGSTER@" -BugCatcherName: ; 27ecc (9:7ecc) - db "BUG CATCHER@" -LassName: ; 27ed8 (9:7ed8) - db "LASS@" -JrTrainerMName: ; 27edd (9:7edd) - db "JR.TRAINER♂@" -JrTrainerFName: ; 27ee9 (9:7ee9) - db "JR.TRAINER♀@" -PokemaniacName: ; 27ef5 (9:7ef5) - db "POKéMANIAC@" -SuperNerdName: ; 27f00 (9:7f00) - db "SUPER NERD@" -BurglarName: ; 27f0b (9:7f0b) - db "BURGLAR@" -EngineerName: ; 27f13 (9:7f13) - db "ENGINEER@" -JugglerXName: ; 27f1c (9:7f1c) - db "JUGGLER@" -SwimmerName: ; 27f24 (9:7f24) - db "SWIMMER@" -BeautyName: ; 27f2c (9:7f2c) - db "BEAUTY@" -RockerName: ; 27f33 (9:7f33) - db "ROCKER@" -JugglerName: ; 27f3a (9:7f3a) - db "JUGGLER@" -BlackbeltName: ; 27f42 (9:7f42) - db "BLACKBELT@" -ProfOakName: ; 27f4c (9:7f4c) - db "PROF.OAK@" -ChiefName: ; 27f55 (9:7f55) - db "CHIEF@" -ScientistName: ; 27f5b (9:7f5b) - db "SCIENTIST@" -RocketName: ; 27f65 (9:7f65) - db "ROCKET@" -CooltrainerMName: ; 27f6c (9:7f6c) - db "COOLTRAINER♂@" -CooltrainerFName: ; 27f79 (9:7f79) - db "COOLTRAINER♀@" - -FocusEnergyEffect_: ; 27f86 (9:7f86) - ld hl, W_PLAYERBATTSTATUS2 - ld a, [H_WHOSETURN] - and a - jr z, .notEnemy - ld hl, W_ENEMYBATTSTATUS2 -.notEnemy - bit GettingPumped, [hl] ; is mon already using focus energy? - jr nz, .alreadyUsing - set GettingPumped, [hl] ; mon is now using focus energy - callab PlayCurrentMoveAnimation - ld hl, GettingPumpedText - jp PrintText -.alreadyUsing - ld c, $32 - call DelayFrames - ld hl, PrintButItFailedText_ - ld b, BANK(PrintButItFailedText_) - jp Bankswitch - -GettingPumpedText: ; 27fb3 (9:7fb3) - db $0a - TX_FAR _GettingPumpedText - db "@" diff --git a/engine/battle/a.asm b/engine/battle/a.asm deleted file mode 100755 index a257d143..00000000 --- a/engine/battle/a.asm +++ /dev/null @@ -1,39 +0,0 @@ -LeechSeedEffect_: ; 2bea9 (a:7ea9) - callab MoveHitTest - ld a, [W_MOVEMISSED] ; W_MOVEMISSED - and a - jr nz, .asm_2bee7 - ld hl, W_ENEMYBATTSTATUS2 ; W_ENEMYBATTSTATUS2 - ld de, wEnemyMonType1 ; wcfea (aliases: wEnemyMonType) - ld a, [H_WHOSETURN] ; $fff3 - and a - jr z, .asm_2bec8 - ld hl, W_PLAYERBATTSTATUS2 ; W_PLAYERBATTSTATUS2 - ld de, wBattleMonType1 ; wd019 (aliases: wBattleMonType) -.asm_2bec8 - ld a, [de] - cp GRASS - jr z, .asm_2bee7 - inc de - ld a, [de] - cp GRASS - jr z, .asm_2bee7 - bit Seeded, [hl] - jr nz, .asm_2bee7 - set Seeded, [hl] - callab PlayCurrentMoveAnimation - ld hl, WasSeededText ; $7ef2 - jp PrintText -.asm_2bee7 - ld c, $32 - call DelayFrames - ld hl, EvadedAttackText ; $7ef7 - jp PrintText - -WasSeededText: ; 2bef2 (a:7ef2) - TX_FAR _WasSeededText - db "@" - -EvadedAttackText: ; 2bef7 (a:7ef7) - TX_FAR _EvadedAttackText - db "@" diff --git a/engine/battle/core.asm b/engine/battle/core.asm index bad8f831..48bed512 100755 --- a/engine/battle/core.asm +++ b/engine/battle/core.asm @@ -8369,8 +8369,8 @@ ParalyzeEffect: ; 3f9b1 (f:79b1) jp Bankswitch SubstituteEffect: ; 3f9b9 (f:79b9) - ld hl, SubstituteEffectHandler - ld b, BANK(SubstituteEffectHandler) + ld hl, SubstituteEffect_ + ld b, BANK(SubstituteEffect_) jp Bankswitch HyperBeamEffect: ; 3f9c1 (f:79c1) diff --git a/engine/battle/moveEffects/focus_energy_effect.asm b/engine/battle/moveEffects/focus_energy_effect.asm new file mode 100644 index 00000000..f01e61cc --- /dev/null +++ b/engine/battle/moveEffects/focus_energy_effect.asm @@ -0,0 +1,24 @@ +FocusEnergyEffect_: ; 27f86 (9:7f86) + ld hl, W_PLAYERBATTSTATUS2 + ld a, [H_WHOSETURN] + and a + jr z, .notEnemy + ld hl, W_ENEMYBATTSTATUS2 +.notEnemy + bit GettingPumped, [hl] ; is mon already using focus energy? + jr nz, .alreadyUsing + set GettingPumped, [hl] ; mon is now using focus energy + callab PlayCurrentMoveAnimation + ld hl, GettingPumpedText + jp PrintText +.alreadyUsing + ld c, $32 + call DelayFrames + ld hl, PrintButItFailedText_ + ld b, BANK(PrintButItFailedText_) + jp Bankswitch + +GettingPumpedText: ; 27fb3 (9:7fb3) + db $0a + TX_FAR _GettingPumpedText + db "@" diff --git a/engine/battle/moveEffects/leech_seed_effect.asm b/engine/battle/moveEffects/leech_seed_effect.asm new file mode 100644 index 00000000..a257d143 --- /dev/null +++ b/engine/battle/moveEffects/leech_seed_effect.asm @@ -0,0 +1,39 @@ +LeechSeedEffect_: ; 2bea9 (a:7ea9) + callab MoveHitTest + ld a, [W_MOVEMISSED] ; W_MOVEMISSED + and a + jr nz, .asm_2bee7 + ld hl, W_ENEMYBATTSTATUS2 ; W_ENEMYBATTSTATUS2 + ld de, wEnemyMonType1 ; wcfea (aliases: wEnemyMonType) + ld a, [H_WHOSETURN] ; $fff3 + and a + jr z, .asm_2bec8 + ld hl, W_PLAYERBATTSTATUS2 ; W_PLAYERBATTSTATUS2 + ld de, wBattleMonType1 ; wd019 (aliases: wBattleMonType) +.asm_2bec8 + ld a, [de] + cp GRASS + jr z, .asm_2bee7 + inc de + ld a, [de] + cp GRASS + jr z, .asm_2bee7 + bit Seeded, [hl] + jr nz, .asm_2bee7 + set Seeded, [hl] + callab PlayCurrentMoveAnimation + ld hl, WasSeededText ; $7ef2 + jp PrintText +.asm_2bee7 + ld c, $32 + call DelayFrames + ld hl, EvadedAttackText ; $7ef7 + jp PrintText + +WasSeededText: ; 2bef2 (a:7ef2) + TX_FAR _WasSeededText + db "@" + +EvadedAttackText: ; 2bef7 (a:7ef7) + TX_FAR _EvadedAttackText + db "@" diff --git a/engine/battle/moveEffects/substitute_effect.asm b/engine/battle/moveEffects/substitute_effect.asm new file mode 100644 index 00000000..e88def4a --- /dev/null +++ b/engine/battle/moveEffects/substitute_effect.asm @@ -0,0 +1,77 @@ +SubstituteEffect_: ; 17dad (5:7dad) + ld c, 50 + call DelayFrames + ld hl, wBattleMonMaxHP + ld de, wPlayerSubstituteHP + ld bc, W_PLAYERBATTSTATUS2 + ld a, [H_WHOSETURN] + and a + jr z, .notEnemy + ld hl, wEnemyMonMaxHP + ld de, wEnemySubstituteHP + ld bc, W_ENEMYBATTSTATUS2 +.notEnemy + ld a, [bc] ;load flags + bit HasSubstituteUp, a ;user already has substitute? + jr nz, .alreadyHasSubstitute ;skip this code if so + ;user doesn't have a substitute [yet] + push bc + ld a, [hli] ;load max hp + ld b, [hl] + srl a ;max hp / 4, [quarter health to remove from user] + rr b + srl a + rr b + push de + ld de, wBattleMonHP - wBattleMonMaxHP + add hl, de ; point hl to current HP + pop de + ld a, b + ld [de], a ;save copy of HP to subtract in ccd7/ccd8 [how much HP substitute has] + ld a, [hld] ;load current hp + sub b ;subtract [max hp / 4] + ld d, a ;save low byte result in D + ld a, [hl] + sbc a, 0 ;borrow from high byte if needed + pop bc + jr c, .notEnoughHP ;underflow means user would be left with negative health + ;bug: note since it only brances on carry, it will possibly leave user with 0HP +.userHasZeroOrMoreHP + ldi [hl], a ;store high byte HP + ld [hl], d ;store low byte HP + ld h, b + ld l, c + set HasSubstituteUp, [hl] ;set bit 4 of flags, user now has substitute + ld a, [W_OPTIONS] ;load options + bit 7, a ;battle animation is enabled? + ld hl, PlayCurrentMoveAnimation ;animation enabled: 0F:7BA8 + ld b, BANK(PlayCurrentMoveAnimation) + jr z, .animationEnabled + ld hl, AnimationSubstitute ;animation disabled: 1E:56E0 + ld b, BANK(AnimationSubstitute) +.animationEnabled + call Bankswitch ;jump to routine depending on animation setting + ld hl, SubstituteText + call PrintText + ld hl, DrawHUDsAndHPBars + ld b, BANK(DrawHUDsAndHPBars) + jp Bankswitch +.alreadyHasSubstitute + ld hl, HasSubstituteText + jr .printText +.notEnoughHP + ld hl, TooWeakSubstituteText +.printText + jp PrintText + +SubstituteText: ; 17e1d (5:7e1d) + TX_FAR _SubstituteText + db "@" + +HasSubstituteText: ; 17e22 (5:7e22) + TX_FAR _HasSubstituteText + db "@" + +TooWeakSubstituteText: ; 17e27 (5:7e27) + TX_FAR _TooWeakSubstituteText + db "@" diff --git a/engine/battle/print_type.asm b/engine/battle/print_type.asm new file mode 100644 index 00000000..38c701a8 --- /dev/null +++ b/engine/battle/print_type.asm @@ -0,0 +1,52 @@ +; [wd0b5] = pokemon ID +; hl = dest addr +PrintMonType: ; 27d6b (9:7d6b) + call GetPredefRegisters + push hl + call GetMonHeader + pop hl + push hl + ld a, [W_MONHTYPE1] + call PrintType + ld a, [W_MONHTYPE1] + ld b, a + ld a, [W_MONHTYPE2] + cp b + pop hl + jr z, EraseType2Text + ld bc, SCREEN_WIDTH * 2 + add hl, bc + +; a = type +; hl = dest addr +PrintType: ; 27d89 (9:7d89) + push hl + jr PrintType_ + +; erase "TYPE2/" if the mon only has 1 type +EraseType2Text: ; 27d8c (9:7d8c) + ld a, " " + ld bc, $13 + add hl, bc + ld bc, $6 + jp FillMemory + +PrintMoveType: ; 27d98 (9:7d98) + call GetPredefRegisters + push hl + ld a, [W_PLAYERMOVETYPE] +; fall through + +PrintType_: ; 27d9f (9:7d9f) + add a + ld hl, TypeNames + ld e, a + ld d, $0 + add hl, de + ld a, [hli] + ld e, a + ld d, [hl] + pop hl + jp PlaceString + +INCLUDE "text/type_names.asm" diff --git a/engine/battle/save_trainer_name.asm b/engine/battle/save_trainer_name.asm new file mode 100644 index 00000000..84ef1f69 --- /dev/null +++ b/engine/battle/save_trainer_name.asm @@ -0,0 +1,112 @@ +SaveTrainerName: ; 27e4a (9:7e4a) + ld hl,TrainerNamePointers + ld a,[W_TRAINERCLASS] + dec a + ld c,a + ld b,0 + add hl,bc + add hl,bc + ld a,[hli] + ld h,[hl] + ld l,a + ld de,wcd6d +.CopyCharacter + ld a,[hli] + ld [de],a + inc de + cp "@" + jr nz,.CopyCharacter + ret + +TrainerNamePointers: ; 27e64 (9:7e64) +; what is the point of these? + dw YoungsterName + dw BugCatcherName + dw LassName + dw W_TRAINERNAME + dw JrTrainerMName + dw JrTrainerFName + dw PokemaniacName + dw SuperNerdName + dw W_TRAINERNAME + dw W_TRAINERNAME + dw BurglarName + dw EngineerName + dw JugglerXName + dw W_TRAINERNAME + dw SwimmerName + dw W_TRAINERNAME + dw W_TRAINERNAME + dw BeautyName + dw W_TRAINERNAME + dw RockerName + dw JugglerName + dw W_TRAINERNAME + dw W_TRAINERNAME + dw BlackbeltName + dw W_TRAINERNAME + dw ProfOakName + dw ChiefName + dw ScientistName + dw W_TRAINERNAME + dw RocketName + dw CooltrainerMName + dw CooltrainerFName + dw W_TRAINERNAME + dw W_TRAINERNAME + dw W_TRAINERNAME + dw W_TRAINERNAME + dw W_TRAINERNAME + dw W_TRAINERNAME + dw W_TRAINERNAME + dw W_TRAINERNAME + dw W_TRAINERNAME + dw W_TRAINERNAME + dw W_TRAINERNAME + dw W_TRAINERNAME + dw W_TRAINERNAME + dw W_TRAINERNAME + dw W_TRAINERNAME + +YoungsterName: ; 27ec2 (9:7ec2) + db "YOUNGSTER@" +BugCatcherName: ; 27ecc (9:7ecc) + db "BUG CATCHER@" +LassName: ; 27ed8 (9:7ed8) + db "LASS@" +JrTrainerMName: ; 27edd (9:7edd) + db "JR.TRAINER♂@" +JrTrainerFName: ; 27ee9 (9:7ee9) + db "JR.TRAINER♀@" +PokemaniacName: ; 27ef5 (9:7ef5) + db "POKéMANIAC@" +SuperNerdName: ; 27f00 (9:7f00) + db "SUPER NERD@" +BurglarName: ; 27f0b (9:7f0b) + db "BURGLAR@" +EngineerName: ; 27f13 (9:7f13) + db "ENGINEER@" +JugglerXName: ; 27f1c (9:7f1c) + db "JUGGLER@" +SwimmerName: ; 27f24 (9:7f24) + db "SWIMMER@" +BeautyName: ; 27f2c (9:7f2c) + db "BEAUTY@" +RockerName: ; 27f33 (9:7f33) + db "ROCKER@" +JugglerName: ; 27f3a (9:7f3a) + db "JUGGLER@" +BlackbeltName: ; 27f42 (9:7f42) + db "BLACKBELT@" +ProfOakName: ; 27f4c (9:7f4c) + db "PROF.OAK@" +ChiefName: ; 27f55 (9:7f55) + db "CHIEF@" +ScientistName: ; 27f5b (9:7f5b) + db "SCIENTIST@" +RocketName: ; 27f65 (9:7f65) + db "ROCKET@" +CooltrainerMName: ; 27f6c (9:7f6c) + db "COOLTRAINER♂@" +CooltrainerFName: ; 27f79 (9:7f79) + db "COOLTRAINER♀@" diff --git a/main.asm b/main.asm index 958c774f..1c7f15f9 100755 --- a/main.asm +++ b/main.asm @@ -4825,7 +4825,7 @@ INCLUDE "engine/load_pokedex_tiles.asm" INCLUDE "engine/overworld/map_sprites.asm" INCLUDE "engine/overworld/emotion_bubbles.asm" INCLUDE "engine/evolve_trade.asm" -INCLUDE "engine/battle/5.asm" +INCLUDE "engine/battle/moveEffects/substitute_effect.asm" INCLUDE "engine/menu/pc.asm" @@ -5154,7 +5154,9 @@ TangelaPicBack:: INCBIN "pic/monback/tangelab.pic" SECTION "Battle (bank 9)", ROMX, BANK[$9] -INCLUDE "engine/battle/9.asm" +INCLUDE "engine/battle/print_type.asm" +INCLUDE "engine/battle/save_trainer_name.asm" +INCLUDE "engine/battle/moveEffects/focus_energy_effect.asm" SECTION "Pics 2", ROMX, BANK[PICS_2] @@ -5226,7 +5228,7 @@ MoltresPicBack:: INCBIN "pic/monback/moltresb.pic" SECTION "Battle (bank A)", ROMX, BANK[$A] -INCLUDE "engine/battle/a.asm" +INCLUDE "engine/battle/moveEffects/leech_seed_effect.asm" SECTION "Pics 3", ROMX, BANK[PICS_3] -- cgit v1.2.3