diff options
Diffstat (limited to 'src/mail.c')
-rw-r--r-- | src/mail.c | 767 |
1 files changed, 767 insertions, 0 deletions
diff --git a/src/mail.c b/src/mail.c new file mode 100644 index 000000000..3f9b675ab --- /dev/null +++ b/src/mail.c @@ -0,0 +1,767 @@ +#include "global.h" +#include "mail.h" +#include "asm.h" +#include "menu.h" +#include "palette.h" +#include "rom4.h" +#include "sprite.h" +#include "string_util.h" +#include "task.h" +#include "text.h" + +struct MailLayout { + u8 var0; + u8 var1; + u8 var2; + u8 var3; + u8 (*var4)[]; +}; + +struct Unk2000000 { + /* 0x00 */ u8 words[8][27]; + /* 0xEC */ u8 varD8[20]; + /* 0xEC */ MainCallback varEC; + /* 0xF0 */ MainCallback varF0; + /* 0xFF */ struct MailStruct *varF4; + /* 0xF8 */ u8 varF8; + /* 0xF9 */ u8 varF9; + /* 0xFA */ u8 varFA; + /* 0xFB */ u8 varFB; + /* 0xFC */ u8 varFC; + u8 padFD[1]; + /* 0xFE */ u8 varFE; + /* 0xFF */ u8 varFF; + /* 0x100 */ u8 var100; + u8 pad101[3]; + /* 0x104 */ MainCallback var104; + /* 0x108 */ MainCallback var108; + /* 0x10C */ struct MailLayout *var10C; +}; + +struct MailGraphics { + u16 (*palette)[]; + u8 (*tiles)[]; + u8 (*tileMap)[]; + u16 var0C; + u16 var0E; + u16 color10; + u16 color12; +}; + +enum { + LANGUAGE_JAPANESE = 0, + LANGUAGE_ENGLISH = 1, + LANGUAGE_GERMAN = 5, +}; + +enum { + ITEM_ORANGE_MAIL = 0x79, + ITEM_HARBOR_MAIL, + ITEM_GLITTER_MAIL, + ITEM_MECH_MAIL, + ITEM_WOOD_MAIL, + ITEM_WAVE_MAIL, + ITEM_BEAD_MAIL, + ITEM_SHADOW_MAIL, + ITEM_TROPIC_MAIL, + ITEM_DREAM_MAIL, + ITEM_FAB_MAIL, + ITEM_RETRO_MAIL, +}; + +extern struct Unk2000000 unk_2000000; +extern struct MailGraphics gMailGraphicsTable[]; +extern u16 gUnknown_083E562C[][2]; + +extern struct MailLayout gUnknown_083E5730[]; +extern struct MailLayout gUnknown_083E57A4[]; + +extern u8 gOtherText_From[]; + +static u8 sub_80F8A28(void); +// static void sub_80F8D50(void); +// static u8 *sub_80F8D7C(u8 *dest, u8 *src); +static void sub_80F8DA0(void); +static void sub_80F8E80(void); +static void sub_80F8F18(void); +static void sub_80F8F2C(void); +static void sub_80F8F58(void); +static void sub_80F8F78(void); +static void sub_80F8FB4(void); + +#ifdef NONMATCHING +void sub_80F890C(struct MailStruct *arg0, MainCallback arg1, bool8 arg2) { + u16 mailDesign; + u8 buffer[4]; + u8 local1; + + unk_2000000.varFF = 2; + + // Compiler uses [sub 1], while asm uses [ptr + FE] + unk_2000000.varFE = 1; + unk_2000000.var104 = (MainCallback) sub_80EB3FC; + unk_2000000.var108 = (MainCallback) ConvertEasyChatWordsToString; + + mailDesign = arg0->var20 - ITEM_ORANGE_MAIL; + + if (mailDesign <= 11) { + unk_2000000.varFA = arg0->var20 - ITEM_ORANGE_MAIL; + } else { + unk_2000000.varFA = 0; + arg2 = FALSE; + } + + switch (unk_2000000.var100) { + case 0: + default: + unk_2000000.var10C = &gUnknown_083E5730[unk_2000000.varFA]; + break; + + case 1: + unk_2000000.var10C = &gUnknown_083E57A4[unk_2000000.varFA]; + break; + } + + if (((sub_80A2D64(arg0->var1E, buffer) << 16) +0xFFFF0000) <= (410 << 16)) { + switch (unk_2000000.varFA) { + case 6: + unk_2000000.varFB = 1; + break; + + case 9: + unk_2000000.varFB = 2; + break; + + default: + unk_2000000.varFB = 0; + break; + } + } else { + unk_2000000.varFB = 0; + } + + + unk_2000000.varF4 = arg0; + unk_2000000.varEC = arg1; + unk_2000000.varF8 = arg2; + + SetMainCallback2(sub_80F8D50); +} +#else +__attribute__((naked)) +void sub_80F890C(struct MailStruct *arg0, MainCallback arg1, bool8 arg2) { + asm(".syntax unified\n\ + push {r4-r6,lr}\n\ + sub sp, 0x4\n\ + adds r4, r0, 0\n\ + adds r6, r1, 0\n\ + lsls r2, 24\n\ + lsrs r5, r2, 24\n\ + ldr r2, _080F8958 @ =0x02000000\n\ + adds r1, r2, 0\n\ + adds r1, 0xFF\n\ + movs r0, 0x2\n\ + strb r0, [r1]\n\ + adds r0, 0xFE\n\ + adds r1, r2, r0\n\ + movs r0, 0x1\n\ + strb r0, [r1]\n\ + movs r0, 0x82\n\ + lsls r0, 1\n\ + adds r1, r2, r0\n\ + ldr r0, _080F895C @ =sub_80EB3FC\n\ + str r0, [r1]\n\ + movs r0, 0x84\n\ + lsls r0, 1\n\ + adds r1, r2, r0\n\ + ldr r0, _080F8960 @ =ConvertEasyChatWordsToString\n\ + str r0, [r1]\n\ + ldrh r1, [r4, 0x20]\n\ + adds r0, r1, 0\n\ + subs r0, 0x79\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + cmp r0, 0xB\n\ + bhi _080F8964\n\ + subs r1, 0x79\n\ + adds r0, r2, 0\n\ + adds r0, 0xFA\n\ + strb r1, [r0]\n\ + b _080F896E\n\ + .align 2, 0\n\ +_080F8958: .4byte 0x02000000\n\ +_080F895C: .4byte sub_80EB3FC\n\ +_080F8960: .4byte ConvertEasyChatWordsToString\n\ +_080F8964:\n\ + adds r1, r2, 0\n\ + adds r1, 0xFA\n\ + movs r0, 0\n\ + strb r0, [r1]\n\ + movs r5, 0\n\ +_080F896E:\n\ + ldr r1, _080F8994 @ =0x02000000\n\ + movs r2, 0x80\n\ + lsls r2, 1\n\ + adds r0, r1, r2\n\ + ldrb r0, [r0]\n\ + cmp r0, 0\n\ + beq _080F8980\n\ + cmp r0, 0x1\n\ + beq _080F899C\n\ +_080F8980:\n\ + movs r0, 0x86\n\ + lsls r0, 1\n\ + adds r2, r1, r0\n\ + adds r0, r1, 0\n\ + adds r0, 0xFA\n\ + ldrb r0, [r0]\n\ + lsls r0, 3\n\ + ldr r1, _080F8998 @ =gUnknown_083E5730\n\ + b _080F89AC\n\ + .align 2, 0\n\ +_080F8994: .4byte 0x02000000\n\ +_080F8998: .4byte gUnknown_083E5730\n\ +_080F899C:\n\ + movs r0, 0x86\n\ + lsls r0, 1\n\ + adds r2, r1, r0\n\ + adds r0, r1, 0\n\ + adds r0, 0xFA\n\ + ldrb r0, [r0]\n\ + lsls r0, 3\n\ + ldr r1, _080F89DC @ =gUnknown_083E57A4\n\ +_080F89AC:\n\ + adds r0, r1\n\ + str r0, [r2]\n\ + ldrh r0, [r4, 0x1E]\n\ + mov r1, sp\n\ + bl sub_80A2D64\n\ + lsls r0, 16\n\ + ldr r1, _080F89E0 @ =0xffff0000\n\ + adds r0, r1\n\ + movs r1, 0xCD\n\ + lsls r1, 17\n\ + cmp r0, r1\n\ + bhi _080F89F8\n\ + ldr r0, _080F89E4 @ =0x02000000\n\ + adds r1, r0, 0\n\ + adds r1, 0xFA\n\ + ldrb r2, [r1]\n\ + adds r1, r0, 0\n\ + cmp r2, 0x6\n\ + beq _080F89E8\n\ + cmp r2, 0x9\n\ + beq _080F89F0\n\ + b _080F89FA\n\ + .align 2, 0\n\ +_080F89DC: .4byte gUnknown_083E57A4\n\ +_080F89E0: .4byte 0xffff0000\n\ +_080F89E4: .4byte 0x02000000\n\ +_080F89E8:\n\ + adds r2, r1, 0\n\ + adds r2, 0xFB\n\ + movs r0, 0x1\n\ + b _080F8A00\n\ +_080F89F0:\n\ + adds r2, r1, 0\n\ + adds r2, 0xFB\n\ + movs r0, 0x2\n\ + b _080F8A00\n\ +_080F89F8:\n\ + ldr r1, _080F8A20 @ =0x02000000\n\ +_080F89FA:\n\ + adds r2, r1, 0\n\ + adds r2, 0xFB\n\ + movs r0, 0\n\ +_080F8A00:\n\ + strb r0, [r2]\n\ + adds r0, r1, 0\n\ + adds r0, 0xF4\n\ + str r4, [r0]\n\ + subs r0, 0x8\n\ + str r6, [r0]\n\ + adds r0, 0xC\n\ + strb r5, [r0]\n\ + ldr r0, _080F8A24 @ =sub_80F8D50\n\ + bl SetMainCallback2\n\ + add sp, 0x4\n\ + pop {r4-r6}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_080F8A20: .4byte 0x02000000\n\ +_080F8A24: .4byte sub_80F8D50\n\ + .syntax divided\n"); +} + +#endif + +#define RETURN_UP_STATE break +#define RETURN_SKIP_STATE return FALSE + +static u8 sub_80F8A28(void) { + switch (gMain.state) { + case 0: + SetVBlankCallback(NULL); + remove_some_task(); + REG_DISPCNT = 0; + RETURN_UP_STATE; + + case 1: CpuFill16(0, (void *) OAM, OAM_SIZE); + RETURN_UP_STATE; + + case 2: + ResetPaletteFade(); + RETURN_UP_STATE; + + case 3: + ResetTasks(); + RETURN_UP_STATE; + + case 4: + ResetSpriteData(); + RETURN_UP_STATE; + + case 5: + FreeAllSpritePalettes(); + REG_BG0HOFS = 0; + REG_BG0VOFS = 0; + REG_BG1HOFS = 0; + REG_BG1VOFS = 0; + REG_BG2VOFS = 0; + REG_BG2HOFS = 0; + REG_BG3HOFS = 0; + REG_BG3VOFS = 0; + REG_BLDCNT = 0; + REG_BLDALPHA = 0; + RETURN_UP_STATE; + + case 6: + SetUpWindowConfig(&gWindowConfig_81E6DFC); + RETURN_UP_STATE; + + case 7: + MultistepInitMenuWindowBegin(&gWindowConfig_81E6DFC); + RETURN_UP_STATE; + + case 8: + if (MultistepInitMenuWindowContinue() == 0) { + return FALSE; + } + RETURN_UP_STATE; + + case 9: + MenuZeroFillScreen(); + RETURN_UP_STATE; + + case 10: CpuFill16(1, (void *) (VRAM + 0x4800), 0x800); + RETURN_UP_STATE; + + case 11: + LoadPalette(gMailGraphicsTable[unk_2000000.varFA].palette, 0, 16 * 2); + RETURN_UP_STATE; + + case 12: + LZ77UnCompVram(gMailGraphicsTable[unk_2000000.varFA].tileMap, (void *) (VRAM + 0x4000)); + RETURN_UP_STATE; + + case 13: + LZ77UnCompVram(gMailGraphicsTable[unk_2000000.varFA].tiles, (void *) (VRAM)); + + gPlttBufferUnfaded[241] = gMailGraphicsTable[unk_2000000.varFA].color10; + gPlttBufferUnfaded[248] = gMailGraphicsTable[unk_2000000.varFA].color12; + gPlttBufferUnfaded[10] = gUnknown_083E562C[gSaveBlock2.playerGender][0]; + gPlttBufferUnfaded[11] = gUnknown_083E562C[gSaveBlock2.playerGender][1]; + RETURN_UP_STATE; + + case 14: + if (unk_2000000.varF8 != 0) { + sub_80F8DA0(); + } + RETURN_UP_STATE; + + case 15: + if (unk_2000000.varF8 != 0) { + sub_80F8E80(); + } + + SetVBlankCallback(sub_80F8F18); + gPaletteFade.bufferTransferDisabled = 1; + RETURN_UP_STATE; + + case 16: { + u16 local1; + + local1 = sub_809D4A8(unk_2000000.varF4->var1E); + + switch (unk_2000000.varFB) { + case 1: + sub_809D580(local1); + unk_2000000.varFC = sub_809D3A4(local1, SpriteCallbackDummy, 96, 128, 0); + break; + + case 2: + sub_809D580(local1); + unk_2000000.varFC = sub_809D3A4(local1, SpriteCallbackDummy, 40, 128, 0); + break; + } + RETURN_UP_STATE; + } + + case 17: + if (sub_8055870() != TRUE) { + RETURN_UP_STATE; + } + RETURN_SKIP_STATE; + + case 18: + REG_BG0CNT = 0x9F08; + REG_BG1CNT = 0x0801; + REG_BG2CNT = 0x0902; + REG_BLDCNT = 0; + REG_DISPCNT = DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON | DISPCNT_BG1_ON | DISPCNT_BG2_ON | DISPCNT_OBJ_ON; + BeginNormalPaletteFade(-1, 0, 16, 0, 0); + gPaletteFade.bufferTransferDisabled = 0; + unk_2000000.varF0 = sub_80F8F58; + return TRUE; + + default: + return FALSE; + } + + gMain.state += 1; + return FALSE; +} + +void sub_80F8D50(void) { + do { + if (sub_80F8A28() == 1) { + SetMainCallback2(sub_80F8F2C); + return; + } + } while (sub_80F9344() != 1); +} + +u8 *sub_80F8D7C(u8 *dest, u8 *src) { + u16 length; + + StringCopy(dest, src); + sub_814A568(dest); + + length = StringLength(dest); + + return dest + length; +} + +#ifdef NONMATCHING +static void sub_80F8DA0(void) { + u8 local0; + + local0 = unk_2000000.var10C->var0; + + // No idea what's happening in this loop. + if (local0 <= 0) { + u8 i; + u8 i2 = 0; + + for (i = 0; i < unk_2000000.var10C->var0; i++) { + ConvertEasyChatWordsToString(unk_2000000.words[i], &unk_2000000.varF4->words[i2], + ((*unk_2000000.var10C->var4)[i] << 28) >> 30, 1); + i2 += ((*unk_2000000.var10C->var4)[i] << 28) >> 30; + } + } + + if (unk_2000000.var100 == LANGUAGE_JAPANESE) { + u8 *ptr; + u16 length; + + ptr = sub_80F8D7C(unk_2000000.varD8, unk_2000000.varF4->var12); + StringCopy(ptr, gOtherText_From); + + length = StringLength(unk_2000000.varD8); + + unk_2000000.varF9 = unk_2000000.var10C->var2 - length; + } else { + u8 *ptr; + + ptr = StringCopy(unk_2000000.varD8, gOtherText_From); + sub_80F8D7C(ptr, unk_2000000.varF4->var12); + + unk_2000000.varF9 = unk_2000000.var10C->var2; + } +} +#else +__attribute__((naked)) +static void sub_80F8DA0(void) { + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r8\n\ + push {r7}\n\ + movs r6, 0\n\ + movs r5, 0\n\ + ldr r2, _080F8E3C @ =0x02000000\n\ + movs r0, 0x86\n\ + lsls r0, 1\n\ + adds r1, r2, r0\n\ + ldr r0, [r1]\n\ + ldrb r0, [r0]\n\ + cmp r5, r0\n\ + bcs _080F8E04\n\ + mov r8, r2\n\ + adds r7, r1, 0\n\ +_080F8DBE:\n\ + lsls r0, r5, 3\n\ + subs r0, r5\n\ + lsls r0, 2\n\ + subs r0, r5\n\ + add r0, r8\n\ + mov r1, r8\n\ + adds r1, 0xF4\n\ + lsls r2, r6, 1\n\ + ldr r1, [r1]\n\ + adds r1, r2\n\ + ldr r2, [r7]\n\ + ldr r2, [r2, 0x4]\n\ + lsls r4, r5, 2\n\ + adds r2, r4, r2\n\ + ldr r2, [r2]\n\ + lsls r2, 28\n\ + lsrs r2, 30\n\ + movs r3, 0x1\n\ + bl ConvertEasyChatWordsToString\n\ + ldr r1, [r7]\n\ + ldr r0, [r1, 0x4]\n\ + adds r4, r0\n\ + ldr r0, [r4]\n\ + lsls r0, 28\n\ + lsrs r0, 30\n\ + adds r0, r6, r0\n\ + lsls r0, 24\n\ + lsrs r6, r0, 24\n\ + adds r0, r5, 0x1\n\ + lsls r0, 16\n\ + lsrs r5, r0, 16\n\ + ldrb r1, [r1]\n\ + cmp r5, r1\n\ + bcc _080F8DBE\n\ +_080F8E04:\n\ + ldr r2, _080F8E40 @ =0x020000d8\n\ + adds r4, r2, 0\n\ + subs r4, 0xD8\n\ + adds r0, r2, 0\n\ + adds r0, 0x28\n\ + ldrb r0, [r0]\n\ + cmp r0, 0\n\ + bne _080F8E48\n\ + ldr r1, [r2, 0x1C]\n\ + adds r1, 0x12\n\ + adds r0, r2, 0\n\ + bl sub_80F8D7C\n\ + adds r2, r0, 0\n\ + ldr r1, _080F8E44 @ =gOtherText_From\n\ + bl StringCopy\n\ + ldr r0, _080F8E40 @ =0x020000d8\n\ + bl StringLength\n\ + movs r2, 0x86\n\ + lsls r2, 1\n\ + adds r1, r4, r2\n\ + ldr r1, [r1]\n\ + ldrb r1, [r1, 0x2]\n\ + subs r1, r0\n\ + b _080F8E6A\n\ + .align 2, 0\n\ +_080F8E3C: .4byte 0x02000000\n\ +_080F8E40: .4byte 0x020000d8\n\ +_080F8E44: .4byte gOtherText_From\n\ +_080F8E48:\n\ + ldr r1, _080F8E7C @ =gOtherText_From\n\ + adds r0, r2, 0\n\ + bl StringCopy\n\ + adds r2, r0, 0\n\ + adds r0, r4, 0\n\ + adds r0, 0xF4\n\ + ldr r1, [r0]\n\ + adds r1, 0x12\n\ + adds r0, r2, 0\n\ + bl sub_80F8D7C\n\ + movs r1, 0x86\n\ + lsls r1, 1\n\ + adds r0, r4, r1\n\ + ldr r0, [r0]\n\ + ldrb r1, [r0, 0x2]\n\ +_080F8E6A:\n\ + adds r0, r4, 0\n\ + adds r0, 0xF9\n\ + strb r1, [r0]\n\ + pop {r3}\n\ + mov r8, r3\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_080F8E7C: .4byte gOtherText_From\n\ + .syntax divided\n"); +} +#endif + +#ifdef NONMATCHING +static void sub_80F8E80(void) { + u16 pos; + + if (unk_2000000.var10C->var0 > 0) { + u8 xPos; + u8 yPos; + + for (pos = 0; pos < unk_2000000.var10C->var0; pos++) { + if (unk_2000000.words[pos][0] == 0xFF) { + continue; + } + + if (unk_2000000.words[pos][0] == 0x00) { + continue; + } + + // I assume the words are some kind of bitfield. Again, no idea what's going on here. + MenuPrint(unk_2000000.words[pos], xPos, yPos); + + } + } + + MenuPrint(unk_2000000.varD8, unk_2000000.varF9, unk_2000000.var10C->var1); +} +#else +__attribute__((naked)) +static void sub_80F8E80(void) { + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r8\n\ + push {r7}\n\ + movs r6, 0\n\ + movs r4, 0\n\ + ldr r1, _080F8F10 @ =0x02000000\n\ + movs r0, 0x86\n\ + lsls r0, 1\n\ + adds r2, r1, r0\n\ + ldr r0, [r2]\n\ + ldrb r0, [r0]\n\ + cmp r4, r0\n\ + bcs _080F8EF6\n\ + mov r8, r1\n\ + adds r7, r2, 0\n\ +_080F8E9E:\n\ + lsls r0, r4, 3\n\ + subs r0, r4\n\ + lsls r0, 2\n\ + subs r0, r4\n\ + mov r1, r8\n\ + adds r5, r0, r1\n\ + ldrb r0, [r5]\n\ + cmp r0, 0xFF\n\ + beq _080F8EE8\n\ + cmp r0, 0\n\ + beq _080F8EE8\n\ + ldr r2, [r7]\n\ + ldr r1, [r2, 0x4]\n\ + lsls r0, r4, 2\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + lsls r3, r0, 24\n\ + lsrs r3, 28\n\ + lsls r0, 30\n\ + lsrs r0, 30\n\ + adds r0, r6, r0\n\ + lsls r0, 24\n\ + lsrs r6, r0, 24\n\ + ldrb r2, [r2, 0x3]\n\ + lsrs r1, r2, 4\n\ + adds r1, r3\n\ + lsls r2, 28\n\ + lsrs r2, 28\n\ + adds r2, r6, r2\n\ + lsls r2, 24\n\ + lsrs r2, 24\n\ + adds r0, r5, 0\n\ + bl MenuPrint\n\ + adds r0, r6, 0x2\n\ + lsls r0, 24\n\ + lsrs r6, r0, 24\n\ +_080F8EE8:\n\ + adds r0, r4, 0x1\n\ + lsls r0, 16\n\ + lsrs r4, r0, 16\n\ + ldr r0, [r7]\n\ + ldrb r0, [r0]\n\ + cmp r4, r0\n\ + bcc _080F8E9E\n\ +_080F8EF6:\n\ + ldr r0, _080F8F14 @ =0x020000d8\n\ + adds r1, r0, 0\n\ + adds r1, 0x21\n\ + ldrb r1, [r1]\n\ + ldr r2, [r0, 0x34]\n\ + ldrb r2, [r2, 0x1]\n\ + bl MenuPrint\n\ + pop {r3}\n\ + mov r8, r3\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_080F8F10: .4byte 0x02000000\n\ +_080F8F14: .4byte 0x020000d8\n\ + .syntax divided\n"); +} +#endif + +static void sub_80F8F18(void) { + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); +} + +static void sub_80F8F2C(void) { + if(unk_2000000.varFB != 0) { + AnimateSprites(); + BuildOamBuffer(); + } + + unk_2000000.varF0(); +} + +static void sub_80F8F58(void) { + u8 local0; + + local0 = UpdatePaletteFade(); + if(local0 == 0) { + unk_2000000.varF0 = sub_80F8F78; + } +} + +static void sub_80F8F78(void) { + if (gMain.newKeys & (A_BUTTON | B_BUTTON)) { + BeginNormalPaletteFade(-1, 0, 0, 16, 0); + unk_2000000.varF0 = sub_80F8FB4; + } +} + +static void sub_80F8FB4(void) { + u16 local1; + + if (UpdatePaletteFade()) { + return; + } + + SetMainCallback2(unk_2000000.varEC); + switch (unk_2000000.varFB) { + case 2: + case 1: + local1 = sub_809D4A8(unk_2000000.varF4->var1E); + sub_809D608(local1); + + sub_809D510(&gSprites[unk_2000000.varFC]); + break; + } + + memset(&unk_2000000, 0, 0x110); + ResetPaletteFade(); +} |