Skip to content
View in the app

A better way to browse. Learn more.

ResHax

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.
Help us keep the site running.
Zero Tolerance for Disrespect

[Xbox] Conker Live and Reloaded models

Featured Replies

  • Localization

Perhaps. I just find it odd that everywhere else for the most part seems to do fine, but this is the one that seems to raise the most hell over material assignments. 

  • Replies 284
  • Views 33.4k
  • Created
  • Last Reply

Top Posters In This Topic

Most Popular Posts

  • Über Winfrey
    Über Winfrey

    I Finally got materials and textures to load dynamically, so far only works on Conker will have to work in some tweaks to support other models

  • Über Winfrey
    Über Winfrey

    I forgot all about this thread, I have skin weights imported, and level support

  • Über Winfrey
    Über Winfrey

    Here is an updated version of the script What Changed: Added shader type detection      Specular textures will now correctly pipe into the specular node      Textures with a Cutout Alpha now c

Posted Images

  • Localization
10 hours ago, MilesMontana said:

Hmm, noted. Kinda odd a bunch of those meshes went for one material when there's meant to be multiple, but I assume it's something to do with the way the file is set up versus the others? I never usually saw too many problems with the other maps, but that's the one that seems to fight the most.

image.thumb.png.ff9fdc38164f7cbc17f65177451179e7.pngthe textures are importing, it just looks like a bug with the material builder, which I'll ahve to figure out

  • Localization

I guess you've also seen the weirdness with BeachRunup as well then? Now that's some funky looking stuff.

  • Localization
2 minutes ago, MilesMontana said:

I guess you've also seen the weirdness with BeachRunup as well then? Now that's some funky looking stuff.

I haven't, only time I looked at them was when the script only imported the diffuse texture

  • Localization
2 hours ago, Über Winfrey said:

I haven't, only time I looked at them was when the script only imported the diffuse texture

image.thumb.png.a987c094f0c37373cd327121e4de5778.pngYeah, not exactly a pretty sight. Oddly more missing than expected.

 

  • Localization
8 hours ago, MilesMontana said:

image.thumb.png.a987c094f0c37373cd327121e4de5778.pngYeah, not exactly a pretty sight. Oddly more missing than expected.

 

hmmm, well shit, definitely didn't look like that last time I loaded it in, 
why these maps be so complicate, I'll look into it

so here's the issue, there are blocks of vertexbuffers that are not receiving faces because a previous vertexblock is stealing them, Which I thought I had fixed, I'll have to dig in and see whats going on

=== pushbuffers contents ===
[fallback-pb] assigned 0 fallback static pushbuffers
=== FACE BUILD ===
  'ndVertexBuffer2_00014328' → 32 faces, 16 blocks
  'ndVertexBuffer2_00014C68' → 4096 faces, 208 blocks
  'ndVertexBuffer2_00015ED8' → 1280 faces, 16 blocks
  'ndVertexBuffer2_00016AFC' → 384 faces, 48 blocks
  'ndVertexBuffer2_00017798' → 384 faces, 48 blocks
  'ndVertexBuffer2_00018418' → 1536 faces, 128 blocks
  'ndVertexBuffer2_000193D8' → 205792 faces, 1408 blocks
  'ndVertexBuffer2_00022934' → 55296 faces, 176 blocks
  'ndVertexBuffer2_00026888' → 80 faces, 48 blocks
  'ndVertexBuffer2_000276D8' → 0 faces, 0 blocks
  'ndVertexBuffer2_000281E8' → 64 faces, 32 blocks
  'ndVertexBuffer2_00028EE8' → 1024 faces, 144 blocks
  'ndVertexBuffer2_00029F28' → 640 faces, 112 blocks
  'ndVertexBuffer2_0002ABA8' → 1088 faces, 64 blocks
  'ndVertexBuffer2_0002BE48' → 592 faces, 96 blocks
  'ndVertexBuffer2_0002CE88' → 9008 faces, 528 blocks
  'ndVertexBuffer2_00030418' → 4624 faces, 288 blocks
  'ndVertexBuffer2_00031778' → 736 faces, 112 blocks
  'ndVertexBuffer2_00032538' → 784 faces, 64 blocks
  'ndVertexBuffer2_00033258' → 8736 faces, 176 blocks
  'ndVertexBuffer2_00034B28' → 768 faces, 128 blocks
  'ndVertexBuffer2_00035EC8' → 928 faces, 64 blocks
  'ndVertexBuffer2_00036D28' → 1664 faces, 144 blocks
  'ndVertexBuffer2_00038D28' → 0 faces, 0 blocks
  'ndVertexBuffer2_0003A548' → 17568 faces, 144 blocks
  'ndVertexBuffer2_0003C1C8' → 896 faces, 48 blocks
  'ndVertexBuffer2_0003D028' → 0 faces, 0 blocks
  'ndVertexBuffer2_0003DFB8' → 0 faces, 0 blocks
  'ndVertexBuffer2_0003F068' → 32 faces, 32 blocks
  'ndVertexBuffer2_000433C8' → 0 faces, 0 blocks
  'ndVertexBuffer2_00043D98' → 1344 faces, 32 blocks
  'ndVertexBuffer2_00044958' → 1792 faces, 32 blocks
  'ndVertexBuffer2_00045564' → 33 faces, 2 blocks
  'ndVertexBuffer2_00047188' → 224 faces, 32 blocks
  'ndVertexBuffer2_00048028' → 0 faces, 0 blocks
  'ndVertexBuffer2_00048EAC' → 0 faces, 0 blocks
  'ndVertexBuffer2_00049748' → 1152 faces, 48 blocks

Edited by Über Winfrey

  • Localization

Two steps forward, one step back ordeal. Strange that they were there before and as soon as you started figuring more out, it decides to then give more hell. 

  • Localization

I figured it out, Faces were a different format that I didn't add to implementation, which I'm working on now, I would have had this done sooner but I never thought about checking face table format, whoopsimage.thumb.png.05b3df64c021152a5bd380410908a6aa.png

Edited by Über Winfrey

  • Localization

Happens. At least you figured out what went wrong and got it the way you wanted it.

  • Localization

once I figure out what is going on with the material problem with the pub, I'll release the updated script

but if you want to update the script yourself to get the map mesh to load, here are the 2 functions that need to be  replaced

 

    def build_faces(self):
        import struct
        from collections import defaultdict

        print("=== FACE BUILD ===")
        total = 0

        if not hasattr(self, "_block_face_ranges"):
            self._block_face_ranges = defaultdict(list)
        else:
            self._block_face_ranges.clear()

        def _staticpush_ptr_from_table(table):
            if not table:
                return 0
            spb = table[0].get('staticpush_ptr') or table[0].get('spb_ptr') or 0
            if spb:
                return spb & 0xFFFFFFFF
            for e in table[:8]:
                spb = e.get('staticpush_ptr') or e.get('spb_ptr')
                if spb:
                    return spb & 0xFFFFFFFF
            return 0

        # Legacy fallback (GPU-id matching)
        def _blocks_from_face_tables_for_mesh(mk):
            out = []
            g2k = (getattr(self, 'gpu_to_buffer_key_pos', None) or
                   getattr(self, 'gpu_to_buffer_key_all', None) or
                   getattr(self, 'gpu_to_buffer_key', {}) or {})

            for ft in (getattr(self, "face_tables", None) or []):
                if not isinstance(ft, (list, tuple)) or len(ft) < 4:
                    continue
                table, gpu, spb_ptr, palette_idx = ft
                if g2k.get(gpu) == mk:
                    out.append({
                        'table': table,
                        'gpu': gpu,
                        'spb_ptr': spb_ptr,
                        'palette_idx': palette_idx,
                    })
            return out

        # Prefer distributor output (self.pushbuffers[mk]) first
        def _blocks_for_mesh(mk):
            pbins = getattr(self, "pushbuffers", None)
            if isinstance(pbins, dict) and pbins.get(mk):
                out = []
                for item in pbins[mk]:
                    # distributor usually stores (table, palette_idx) or dict
                    if isinstance(item, dict):
                        out.append(item)
                    elif isinstance(item, (list, tuple)) and len(item) >= 2:
                        table, palette_idx = item[0], item[1]
                        spb_ptr = item[2] if len(item) >= 3 else _staticpush_ptr_from_table(table)
                        out.append({
                            'table': table,
                            'gpu': item[3] if len(item) >= 4 else 0,
                            'spb_ptr': spb_ptr,
                            'palette_idx': palette_idx,
                        })
                if out:
                    return out

            return _blocks_from_face_tables_for_mesh(mk)

        for key, d in self.mesh_data.items():
            if not key.startswith(("ndVertexBuffer2_", "ndBlendShape2_")):
                continue

            verts = d.get('vertices', []) or []
            tris = []

            def add_strip_tris(strip, even_flip_base=0):
                base = len(tris)
                for i in range(2, len(strip)):
                    a, b, c = strip[i - 2], strip[i - 1], strip[i]
                    if a == b or a == c or b == c:
                        continue
                    if not (0 <= a < len(verts) and 0 <= b < len(verts) and 0 <= c < len(verts)):
                        continue
                    # flip winding every other tri
                    if ((i + even_flip_base) & 1) == 0:
                        tris.append((a, b, c))
                    else:
                        tris.append((b, a, c))
                return len(tris) - base

            def add_fan_tris(fan):
                base = len(tris)
                if len(fan) < 3:
                    return 0
                c = fan[0]
                for i in range(1, len(fan) - 1):
                    a, b = fan[i], fan[i + 1]
                    if c == a or c == b or a == b:
                        continue
                    if not (0 <= c < len(verts) and 0 <= a < len(verts) and 0 <= b < len(verts)):
                        continue
                    tris.append((c, a, b))
                return len(tris) - base

            self._block_face_ranges[key] = []

            blocks = _blocks_for_mesh(key)
            if not blocks:
                if not getattr(self, "_once_face_block_debug", False):
                    self._once_face_block_debug = True
                    print(
                        f"[build_faces] No blocks for '{key}'. "
                        f"pushbuffers[{key}]={len(getattr(self,'pushbuffers',{}).get(key,[]) if isinstance(getattr(self,'pushbuffers',{}),dict) else [])}, "
                        f"face_tables={len(getattr(self,'face_tables',[]) or [])}, "
                        f"g2k_pos={len(getattr(self,'gpu_to_buffer_key_pos',{}) or {})}, "
                        f"g2k_all={len(getattr(self,'gpu_to_buffer_key_all',{}) or {})}"
                    )

            for meta in blocks:
                table = meta.get('table', []) or []
                strip = []
                block_start = len(tris)
                even_flip_base = 0
                prim_mode = None  # track current begin mode

                for entry in table:
                    cmd = entry.get('cmd')
                    arg = entry.get('arg', 0)
                    payload = entry.get('payload', b"") or b""

                    if cmd == self.NV097_SET_BEGIN_END:
                        prim = self.parse_set_begin_end(arg, payload)

                        # BEGIN modes we support
                        if prim in (self.NV097_SET_BEGIN_END_OP_TRIANGLES,
                                    self.NV097_SET_BEGIN_END_OP_TRIANGLE_STRIP,
                                    self.NV097_SET_BEGIN_END_OP_TRIANGLE_FAN):
                            prim_mode = prim
                            strip.clear()
                            even_flip_base = 0

                        # END: flush whatever we collected
                        elif prim == self.NV097_SET_BEGIN_END_OP_END:
                            if strip:
                                if prim_mode == self.NV097_SET_BEGIN_END_OP_TRIANGLE_FAN:
                                    add_fan_tris(strip)
                                else:
                                    # TRIANGLES and STRIP both come through the same index stream here;
                                    # TRIANGLES in Conker is often encoded as strip-like batches,
                                    # so keep using strip triangulation unless you later want strict triples.
                                    add_strip_tris(strip, even_flip_base=even_flip_base)
                                strip.clear()
                            prim_mode = None

                    elif cmd == self.NV097_INDEX_U16:
                        # IMPORTANT: trust payload length, not arg bits
                        for off in range(0, len(payload) & ~1, 2):
                            strip.append(struct.unpack_from('<H', payload, off)[0])

                    elif cmd == self.NV097_INDEX_U32:
                        # IMPORTANT: trust payload length, not arg bits
                        for off in range(0, len(payload) & ~3, 4):
                            strip.append(struct.unpack_from('<I', payload, off)[0])

                # Table ended without END: flush
                if strip:
                    if prim_mode == self.NV097_SET_BEGIN_END_OP_TRIANGLE_FAN:
                        add_fan_tris(strip)
                    else:
                        add_strip_tris(strip, even_flip_base=even_flip_base)
                    strip.clear()

                count = len(tris) - block_start
                if count > 0:
                    spb_ptr = (meta.get('spb_ptr') or _staticpush_ptr_from_table(table)) & 0xFFFFFFFF
                    pb_addr = 0
                    if hasattr(self, "_table_abs_addr"):
                        pb_addr = self._table_abs_addr(table, spb_ptr) & 0xFFFFFFFF

                    self._block_face_ranges[key].append({
                        'pb_addr': pb_addr,
                        'start': block_start,
                        'count': count,
                        'spb_ptr': spb_ptr,
                        'shaderparam2_hint': meta.get('shaderparam2') or meta.get('sp2_ptr'),
                    })

            d['faces'] = tris
            print(f"  '{key}' → {len(tris)} faces, {len(self._block_face_ranges[key])} blocks")
            total += len(tris)

        print(f"Total faces: {total}")
    def process_pushbuffer_cmds(self, block_and_label):
        cmds, palette_idx = block_and_label
        # ensure we got a proper list
        if not isinstance(cmds, (list, tuple)) or not cmds:
            return

        spb_ptr = cmds[0].get('staticpush_ptr', 0)
        if getattr(self, "_last_spb_for_ids", None) != spb_ptr:
            self._last_spb_for_ids = spb_ptr
            self.last_gpu_ids = []          # clear carry-over at SPB boundary


        current_gpu_ids = []   # NEW SPB: unknown until we see 0x1720 inside THIS SPB
        current_gpu_ids = list(getattr(self, 'last_gpu_ids', []))
        current_table   = []
        current_block_start_abs = None 
        for entry in cmds:
            cmd     = entry['cmd']
            arg     = entry['arg']
            payload = entry['payload']
            sptr    = entry['staticpush_ptr']

            # --- 0) Debug decode hooks you already had (safe to keep) ---
           # if cmd == 0x0260:  # NV097_SET_COMBINER_ALPHA_ICW
               # print(f"[Pushbuffer][0x0260] Combiner Alpha ICW at SPB 0x{sptr:08X}, payload {len(payload)} bytes:")
               # self.decode_nv2a_combiner_icw(payload)
               # continue

            # --- 1) Vertex buffer bind → refresh GPU IDs, reset palette state ---
            if cmd == self.NV097_SET_VERTEX_DATA_ARRAY_OFFSET:
                self._palette_active = False
                self._palette_idx    = -1
                n_ids = len(payload) // 4
                current_gpu_ids = list(struct.unpack(f'<{n_ids}I', payload)) if n_ids else []
                self.last_gpu_ids = current_gpu_ids
                continue

            # --- 2) Begin/End handling: prim only lives inside this block ---
            if cmd == self.NV097_SET_BEGIN_END:
                prim = self.parse_set_begin_end(arg, payload)

                # BEGIN (TRIANGLES/STRIP): start a new table, seed absolute PB addr immediately
                if prim in (self.NV097_SET_BEGIN_END_OP_TRIANGLES,
                            self.NV097_SET_BEGIN_END_OP_TRIANGLE_STRIP,
                            self.NV097_SET_BEGIN_END_OP_TRIANGLE_FAN):
                    current_table = [entry]
                    current_block_start_abs = (
                        entry.get('payload_abs')
                        or entry.get('cmd_abs')
                        or entry.get('raw_abs')
                        or 0
                    )
                    continue

                # END: close the table (if open) and emit one per GPU id
                if prim == self.NV097_SET_BEGIN_END_OP_END and current_table:
                    current_table.append(entry)
                   # for gpu in (current_gpu_ids or [0]):
                      #  self.face_tables.append((current_table.copy(), gpu, sptr, palette_idx))
                if current_gpu_ids:
                    for gpu in current_gpu_ids:
                        self.face_tables.append((current_table.copy(), gpu, sptr, palette_idx))
                else:
                    # no 0x1720 seen in this SPB → keep it "unmatched" so fallback can assign by static_ptr chain
                    self.face_tables.append((current_table.copy(), 0xFFFFFFFF, sptr, palette_idx))

                    current_table = []
                    current_block_start_abs = 0   # ← reset for next table
                    continue

                # Other BEGIN/END variants while a table is open → keep as part of the table
                if current_table:
                    current_table.append(entry)
                    if not current_block_start_abs:
                        current_block_start_abs = (
                            entry.get('payload_abs')
                            or entry.get('cmd_abs')
                            or entry.get('raw_abs')
                            or 0
                        )
                continue  # NEVER let 'prim' leak below this point

            # --- 3) Indices inside an open table ---
            if cmd in (self.NV097_INDEX_U16, self.NV097_INDEX_U32) and current_table:
                current_table.append(entry)
                continue

            # --- 4) Any other commands: if a table is open, you can keep as context (optional) ---
            if current_table:
                current_table.append(entry)
                if not current_block_start_abs:
                    current_block_start_abs = (
                        entry.get('payload_abs')
                        or entry.get('cmd_abs')
                        or entry.get('raw_abs')
                        or 0
                    )
                continue  # NEVER let 'prim' leak below this point

            # --- 3) Indices inside an open table ---
            if cmd in (self.NV097_INDEX_U16, self.NV097_INDEX_U32) and current_table:
                current_table.append(entry)
                continue

            # --- 4) Any other commands just pass through; if a table is open, we usually
            #         keep them as context (optional). If you don’t want them, you can skip. ---
            if current_table:
                current_table.append(entry)
                if not current_block_start_abs:
                    current_block_start_abs = (
                        entry.get('payload_abs')
                        or entry.get('cmd_abs')
                        or entry.get('raw_abs')
                        or 0
                    )

These should get the maps to load now, the material issue with maps will still exist so be aware of that

Edited by Über Winfrey

Amazing work on everything so far, just wondering though, is it possible to create a noesis rbm import plugin? 

  • Localization
2 hours ago, MrFlath said:

Amazing work on everything so far, just wondering though, is it possible to create a noesis rbm import plugin? 

I doubt it, I'm not that knowledgeable with making things for Noesis

  • Localization

I did a full overhawul on the traversing, and now I'm getting the materials to show now, though there are some issues on Berri's room and the outside, I'll have to look into them to see whats bugging them

image.thumb.png.8085c3b2a120d1b10a4eeee7184a3dbe.png

You plan to upload these models when its all over? Looking for the Jugga one, that one damn

  • Localization
2 hours ago, MrFlath said:

You plan to upload these models when its all over? Looking for the Jugga one, that one damn

the script is in the thread, you could get her yourself

  • Localization
On 1/21/2026 at 9:00 PM, Über Winfrey said:

I did a full overhawul on the traversing, and now I'm getting the materials to show now, though there are some issues on Berri's room and the outside, I'll have to look into them to see whats bugging them

image.thumb.png.8085c3b2a120d1b10a4eeee7184a3dbe.png

Nice to see you got some progress rolling with it. Still confusing this is the one that puts up the biggest fight so far, but guess time will tell if something else comes along. Still solid work my dude. 

On 1/22/2026 at 9:40 AM, Über Winfrey said:

the script is in the thread, you could get her yourself

I couldnt, my blender is out of date and my pc sucks shit lol, I got the other one for blender 2.4 but I didnt get the damn thing to work 

  • Localization
12 hours ago, MrFlath said:

I couldnt, my blender is out of date and my pc sucks shit lol, I got the other one for blender 2.4 but I didnt get the damn thing to work 

Current script works for 4.0 onwards. It's not exactly impossible and pretty sure the thing can handle it if you just stick with Eevee, but I could be wrong.

  • Localization

Holy shit that was a pain in the ass to fix,  so the issue was that the first StaticPushBuffer was being forced onto the material builder, so during material assignment it caused misalignment, and anything that wasn't using the buffer that was used for the actual mesh drawing was tossed out
image.thumb.png.a0d94a67c5f79b58ea89fd1235e51e6a.pngimage.thumb.png.37765b3ca368b4b4bedb2fedd3f67b55.png

I also cut out a lot of fat, so the models don't drag down performance when loading them with materials on

  • Localization
19 hours ago, Über Winfrey said:

Holy shit that was a pain in the ass to fix,  so the issue was that the first StaticPushBuffer was being forced onto the material builder, so during material assignment it caused misalignment, and anything that wasn't using the buffer that was used for the actual mesh drawing was tossed out
image.thumb.png.a0d94a67c5f79b58ea89fd1235e51e6a.pngimage.thumb.png.37765b3ca368b4b4bedb2fedd3f67b55.png

I also cut out a lot of fat, so the models don't drag down performance when loading them with materials on

I'd believe it on the pain in the ass part. Congrats though on figuring it out and for finding a way to trim down performance issues.

  • 2 weeks later...
On 12/29/2025 at 9:10 PM, MilesMontana said:

Gotta love Windows bullshit.
image.png.0a46efc559da1b57cf42d960e8d4f5e5.pngimage.png.b6f85113d07a0148e5f67938b9a7c0ef.png

NVM, I got it to work. Some weird shit went on.

I've been trying for a bit to find anything on how I could get this program to work properly. Running win 11 and getting no results from the process. 
I followed along a bit earlier in the thread and was able to get "default.rbm.unpacked", I just keep bashing into the wall of "Access is denied."

I am illiterate unlike the previous individual, but a great desire to learn.

Screenshot 2026-02-05 010751.png

Screenshot 2026-02-05 010804.png

  • Localization
13 hours ago, Pooka_Hobgoblin said:

I've been trying for a bit to find anything on how I could get this program to work properly. Running win 11 and getting no results from the process. 
I followed along a bit earlier in the thread and was able to get "default.rbm.unpacked", I just keep bashing into the wall of "Access is denied."

I am illiterate unlike the previous individual, but a great desire to learn.

Screenshot 2026-02-05 010751.png

Screenshot 2026-02-05 010804.png

Okay, I might know the issue here. So,if you want to rip these things open, try this instead:

.Open command prompt, run in administrator mode in case since you know how Windows likes to be

.(Optional if you have other drives) Type the name of your drive like so: D: or whatever name it is followed by the colon.

.Type "cd "insert location of the decompiled game and the file you're trying to get here", but only the folder. Not the exact file just yet.

.Type clr_unpack default.rbm -d index

All you needed to do there was just not write the .exe part because it's weird that way. If done right, you should get a .mapped file out of it.

Hope this helps!

On 2/5/2026 at 2:32 PM, MilesMontana said:

Okay, I might know the issue here. So,if you want to rip these things open, try this instead:

.Open command prompt, run in administrator mode in case since you know how Windows likes to be

.(Optional if you have other drives) Type the name of your drive like so: D: or whatever name it is followed by the colon.

.Type "cd "insert location of the decompiled game and the file you're trying to get here", but only the folder. Not the exact file just yet.

.Type clr_unpack default.rbm -d index

All you needed to do there was just not write the .exe part because it's weird that way. If done right, you should get a .mapped file out of it.

Hope this helps!

It worked like a charm! Thank you for taking the time to help me with this. 
super stoked to have a proper reference for a later physical project I'd like to build

Screenshot 2026-02-07 003240.png

  • Localization
10 hours ago, Pooka_Hobgoblin said:

It worked like a charm! Thank you for taking the time to help me with this. 
super stoked to have a proper reference for a later physical project I'd like to build

Screenshot 2026-02-07 003240.png

Happy to help. It took me a bit to process how to do it myself as well the first time around, but the results are pretty good. Only level you might not have a good time with rn is the Beach running section since the current script doesn't have it fixed up, but the code was given for tweaking it. Otherwise, good luck with your project.

1 hour ago, MilesMontana said:

Happy to help. It took me a bit to process how to do it myself as well the first time around, but the results are pretty good. Only level you might not have a good time with rn is the Beach running section since the current script doesn't have it fixed up, but the code was given for tweaking it. Otherwise, good luck with your project.

I believe I saw the blanked sections as individual objects (Like the barb wire barrier)

It would make sense they are swapped out when obscured by the explosion

Thank you and everyone for this amazing project

Create an account or sign in to comment

Account

Navigation

Search

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.