summaryrefslogtreecommitdiff
path: root/engine/menus/swap_items.asm
diff options
context:
space:
mode:
Diffstat (limited to 'engine/menus/swap_items.asm')
-rw-r--r--engine/menus/swap_items.asm149
1 files changed, 149 insertions, 0 deletions
diff --git a/engine/menus/swap_items.asm b/engine/menus/swap_items.asm
new file mode 100644
index 00000000..826fe60b
--- /dev/null
+++ b/engine/menus/swap_items.asm
@@ -0,0 +1,149 @@
+HandleItemListSwapping::
+ ld a, [wListMenuID]
+ cp ITEMLISTMENU
+ jp nz, DisplayListMenuIDLoop ; only rearrange item list menus
+ push hl
+ ld hl, wListPointer
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ inc hl ; hl = beginning of list entries
+ ld a, [wCurrentMenuItem]
+ ld b, a
+ ld a, [wListScrollOffset]
+ add b
+ add a
+ ld c, a
+ ld b, 0
+ add hl, bc ; hl = address of currently selected item entry
+ ld a, [hl]
+ pop hl
+ inc a
+ jp z, DisplayListMenuIDLoop ; ignore attempts to swap the Cancel menu item
+ ld a, [wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1)
+ and a ; has the first item to swap already been chosen?
+ jr nz, .swapItems
+; if not, set the currently selected item as the first item
+ ld a, [wCurrentMenuItem]
+ inc a
+ ld b, a
+ ld a, [wListScrollOffset] ; index of top (visible) menu item within the list
+ add b
+ ld [wMenuItemToSwap], a ; ID of item chosen for swapping (counts from 1)
+ ld c, 20
+ call DelayFrames
+ jp DisplayListMenuIDLoop
+.swapItems
+ ld a, [wCurrentMenuItem]
+ inc a
+ ld b, a
+ ld a, [wListScrollOffset]
+ add b
+ ld b, a
+ ld a, [wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1)
+ cp b ; is the currently selected item the same as the first item to swap?
+ jp z, DisplayListMenuIDLoop ; ignore attempts to swap an item with itself
+ dec a
+ ld [wMenuItemToSwap], a ; ID of item chosen for swapping (counts from 1)
+ ld c, 20
+ call DelayFrames
+ push hl
+ push de
+ ld hl, wListPointer
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ inc hl ; hl = beginning of list entries
+ ld d, h
+ ld e, l ; de = beginning of list entries
+ ld a, [wCurrentMenuItem]
+ ld b, a
+ ld a, [wListScrollOffset]
+ add b
+ add a
+ ld c, a
+ ld b, 0
+ add hl, bc ; hl = address of currently selected item entry
+ ld a, [wMenuItemToSwap] ; ID of item chosen for swapping (counts from 1)
+ add a
+ add e
+ ld e, a
+ jr nc, .noCarry
+ inc d
+.noCarry ; de = address of first item to swap
+ ld a, [de]
+ ld b, a
+ ld a, [hli]
+ cp b
+ jr z, .swapSameItemType
+.swapDifferentItems
+ ld [$ff95], a ; [$ff95] = second item ID
+ ld a, [hld]
+ ld [$ff96], a ; [$ff96] = second item quantity
+ ld a, [de]
+ ld [hli], a ; put first item ID in second item slot
+ inc de
+ ld a, [de]
+ ld [hl], a ; put first item quantity in second item slot
+ ld a, [$ff96]
+ ld [de], a ; put second item quantity in first item slot
+ dec de
+ ld a, [$ff95]
+ ld [de], a ; put second item ID in first item slot
+ xor a
+ ld [wMenuItemToSwap], a ; 0 means no item is currently being swapped
+ pop de
+ pop hl
+ jp DisplayListMenuIDLoop
+.swapSameItemType
+ inc de
+ ld a, [hl]
+ ld b, a
+ ld a, [de]
+ add b ; a = sum of both item quantities
+ cp 100 ; is the sum too big for one item slot?
+ jr c, .combineItemSlots
+; swap enough items from the first slot to max out the second slot if they can't be combined
+ sub 99
+ ld [de], a
+ ld a, 99
+ ld [hl], a
+ jr .done
+.combineItemSlots
+ ld [hl], a ; put the sum in the second item slot
+ ld hl, wListPointer
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ dec [hl] ; decrease the number of items
+ ld a, [hl]
+ ld [wListCount], a ; update number of items variable
+ cp 1
+ jr nz, .skipSettingMaxMenuItemID
+ ld [wMaxMenuItem], a ; if the number of items is only one now, update the max menu item ID
+.skipSettingMaxMenuItemID
+ dec de
+ ld h, d
+ ld l, e
+ inc hl
+ inc hl ; hl = address of item after first item to swap
+.moveItemsUpLoop ; erase the first item slot and move up all the following item slots to fill the gap
+ ld a, [hli]
+ ld [de], a
+ inc de
+ inc a ; reached the $ff terminator?
+ jr z, .afterMovingItemsUp
+ ld a, [hli]
+ ld [de], a
+ inc de
+ jr .moveItemsUpLoop
+.afterMovingItemsUp
+ xor a
+ ld [wListScrollOffset], a
+ ld [wCurrentMenuItem], a
+.done
+ xor a
+ ld [wMenuItemToSwap], a ; 0 means no item is currently being swapped
+ pop de
+ pop hl
+ jp DisplayListMenuIDLoop