Remote linking to avatars
Do not link to Suikosource images on forums, webpages, or anyplace else. If you wish to use the images, place them in your own webspace. We do not allow you to use them from our server.
Mystery items such as vases and paintings can be identified for free by the scroll shop.
Scroll Shop Bug
Bug Details
System(s) Playstation,
Bug TypeGameplay
Region Introduced
Patch Version2.01.065b

Regions Affected
The Scroll Shop, or Scribe, can turn your spare rune crystals into spell scrolls for a fee. It performs this function admirably. The bug with the shop is that it displays the names and descriptions of mystery items, such as vases, paintings, and ornaments in its menu. Ordinarily, these items can only be identified by an appraiser at a cost of a few hundred potch.

The Scroll Shop is handled by the module /CDROM/140_HONP/FUDAZUK.BIN. It seems that whoever was responsible for coding it did not get the memo covering changes in handling item data, or at least it was not updated along with all the other shops. It unintentionally identifies antiques because it uses routines that cannot under any circumstances handle unidentified items. The functions it calls will always return data for the actual item, instead of generalized data.

The main executable contains two functions that are used for getting item data. The first is at 0x80070348. It takes an address to an array of item data, the item type, and the actual item number as arguments. The reason for needing that first pointer is an open question. Most of the shop modules contain copies of the item data, and all of them have code that calls this function, passing a pointer to their own copy of the item data. This function does not take into account the possibility of unidentified items. It expects to receive a type from 1-7, with no quantity or unidentified flag included.

What is strange is that passing a zero, instead of a pointer to a "local" array of item data causes a more global set of data to be used. Why two copies of this data is desirable is not known for certain. It appears that the "global" data could have been a late addition, and Konami initially placed the array only in modules that needed it. This may have been a space-saving measure that turned into more trouble than it was worth.

The second function is at 0x80088D74. This function takes a type/quantity (including the unidentified flag) and an item ID. If the item is unidentified, it returns a dummy entry for the appropriate type of antique. When the item is identified, it actually calls the function previously described with a zero pointer. So it uses the global array by default.

Most of the shops contain two sets of routines. One that calls only the 0x80070348 function, and refers to the local item data. These routines appear to be dead code for the most part. Routines in the second set all call the 0x80088D74 function. For some reason, the Scroll Shop only includes the first set of routines, and no references at all exist for the more appropriate function.

RAM:80111480                 li      $s7, 0x8008DB48
RAM:80111488                 li      $s6, 0x80070348
RAM:80111490                 li      $s5, 0x8008D390
RAM:80111498                 li      $fp, 1
RAM:8011149C                 li      $s4, 0x8008E024
RAM:801114A4 loc_801114A4:                            # CODE XREF: sub_801113AC+1B8j
RAM:801114A4                 lbu     $v1, 0x17($s2)
RAM:801114A8                 nop
RAM:801114AC                 addiu   $v1, 1
RAM:801114B0                 sll     $v0, $v1, 3
RAM:801114B4                 subu    $v0, $v1
RAM:801114B8                 slt     $v0, $s0, $v0
RAM:801114BC                 beqz    $v0, loc_8011156C
RAM:801114C0                 move    $a1, $0
RAM:801114C4                 lw      $a0, 0x1C4($s2)
RAM:801114C8                 move    $a2, $s1
RAM:801114CC                 jalr    $s7
RAM:801114D0                 sw      $s7, -0x8AC($s3)
RAM:801114D4                 li      $v1, 0x80061000
RAM:801114DC                 la      $a0, unk_80114A44
RAM:801114E4                 sll     $v0, $s0, 1
RAM:801114E8                 addu    $v0, $v1
RAM:801114EC                 li      $v1, 0x8000
RAM:801114F0                 addu    $v0, $v1
RAM:801114F4                 sw      $s6, -0x8AC($s3)
RAM:801114F8                 lbu     $a1, 0x14AF($v0)
RAM:801114FC                 lbu     $a2, 0x14AE($v0)
RAM:80111500                 andi    $a1, 0x70
RAM:80111504                 jalr    $s6
RAM:80111508                 srl     $a1, 4

The above is a snippet of code from the Scroll Shop. When it needs to retrieve the item name and description for display, it calls 0x80070348, which cannot return things like "? vase".

The routines are in the main executable, and thus are always present. Both functions return references to the same type of data structure, and the only difference between calling them is that the better routine does not require us to supply the location of the item array. A fix can be accomplished by simply changing the code to call 0x80088D74, changing where the type/quantity and id are loaded (eliminating the code that sets up the pointer as a consequence), and removing the code that isolates the type bits.

.align 4
.openfile FUDAZUK.BIN, 0x8010DC50
.headersize 0
.org 0x80111480
.area 0x80111510-.
    li      $s7, 0x8008DB48
    li      $s6, 0x80088D74        ; replace sub 0x80070348
    li      $s5, 0x8008D390
    li      $fp, 1
    li      $s4, 0x8008E024
    lbu     $v1, 0x17($s2)
    addiu   $v1, 1
    sll     $v0, $v1, 3
    subu    $v0, $v1
    slt     $v0, $s0, $v0
    beqz    $v0, 0x8011156C
    move    $a1, $0
    lw      $a0, 0x1C4($s2)
    move    $a2, $s1
    jalr    $s7
    sw      $s7, -0x8AC($s3)
    li      $v1, 0x80061000
    li      $a0, 0x80114A44
    sll     $v0, $s0, 1

    addu    $v0, $v1
    li      $v1, 0x8000
    addu    $v0, $v1
    sw      $s6, -0x8AC($s3)
    lbu     $a0, 0x14AF($v0)    ; $a0 is type/quantity
    lbu     $a1, 0x14AE($v0)    ; $a1 is item
    nop                ; no longer need or want the andi
    jalr    $s6
    nop                ; or the srl that isolated the type bits
    move    $a1, $v0
.org 0x80111E60
.area 0x80111EE0-.
    li      $t0, 0x8008DB48
    sw      $t0, 0x20($sp)
    li      $fp, 0x80088D74        ; replace sub 0x80070348
    li      $s7, 0x8008D390
    li      $s6, 0x8008E024
    lbu     $v0, 0x16($s2)
    beq     $s0, $v0, 0x80111F4C
    move    $a1, $0
    andi    $s1, $s5, 0xFF
    lw      $a0, 0x1C4($s2)
    lw      $t0, 0x20($sp)
    move    $a2, $s1
    jalr    $t0
    sw      $t0, -0x8AC($s4)
    li      $v1, 0x80069000
    li      $a0, 0x80114A44
    sll     $v0, $s0, 1
    or      $v0, $v1
    sw      $fp, -0x8AC($s4)
    lbu     $a0, 0x14AF($v0)    ; $a0 is type/quantity
    lbu     $a1, 0x14AE($v0)    ; $a1 is item
    nop                ; no longer need or want the andi
    jalr    $fp
    nop                ; or the srl that isolated the type bits
    move    $a1, $v0