示例#1
0
文件: health.py 项目: loopfz/LADXR
def upgradeHealthContainers(rom):
    # Reuse 2 unused shop messages for the heart containers.
    rom.texts[0x2A] = formatText("You found a {HEART_CONTAINER}!")
    rom.texts[0x2B] = formatText("You lost a heart!")

    rom.patch(0x03,
              0x19DC,
              ASM("""
        ld   de, $59D8
        call $3BC0
    """),
              ASM("""
        ld   a, $05  ; renderHeartPiece
        rst  8
    """),
              fill_nop=True)
    rom.patch(0x03,
              0x19F0,
              ASM("""
        ld   hl, $DB5B
        inc  [hl]
        ld   hl, $DB93
        ld   [hl], $FF
    """),
              ASM("""
        ld   a, $06 ; giveItemMultiworld
        rst  8
        ld   a, $0A ; messageForItemMultiworld
        rst  8
skip:
    """),
              fill_nop=True)  # add heart->remove heart on heart container
示例#2
0
文件: shop.py 项目: loopfz/LADXR
 def patch(self, rom, option, *, multiworld=None):
     assert multiworld is None
     if self.__index == 0:
         rom.patch(0x04, 0x37C5, "08", "%02X" % (CHEST_ITEMS[option]))
         rom.texts[0x030] = formatText("Deluxe {%s} 200 {RUPEES}!" %
                                       (option),
                                       ask="Buy  No Way")
     elif self.__index == 1:
         rom.patch(0x04, 0x37C6, "02", "%02X" % (CHEST_ITEMS[option]))
         rom.texts[0x02C] = formatText("{%s} Only 980 {RUPEES}!" % (option),
                                       ask="Buy  No Way")
示例#3
0
 def patch(self, rom, option, *, multiworld=None):
     assert multiworld is None
     if self.__index == 0:
         rom.patch(0x04, 0x37C5, "08", "%02X" % (CHEST_ITEMS[option]))
         rom.texts[0x030] = formatText(b"Deluxe %s 200 Rupees!" %
                                       (INVENTORY_NAME[option]),
                                       ask=b"Buy  No Way")
     elif self.__index == 1:
         rom.patch(0x04, 0x37C6, "02", "%02X" % (CHEST_ITEMS[option]))
         rom.texts[0x02C] = formatText(b"%s Only 980 Rupees!" %
                                       (INVENTORY_NAME[option]),
                                       ask=b"Buy  No Way")
示例#4
0
def addHints(rom, rnd, spots):
    spots = list(sorted(filter(lambda spot: spot.item in hint_items, spots), key=lambda spot: spot.nameId))
    text_ids = hint_text_ids.copy()
    rnd.shuffle(text_ids)
    for text_id in text_ids:
        if len(spots) > 0:
            spot_index = rnd.randint(0, len(spots) - 1)
            spot = spots.pop(spot_index)
            hint = rnd.choice(hints).format("{%s}" % (spot.item), spot.metadata.area)
        else:
            hint = rnd.choice(hints).format(*rnd.choice(useless_hint))
        rom.texts[text_id] = formatText(hint)

    for text_id in range(0x200, 0x20C, 2):
        rom.texts[text_id] = formatText("Read this book?", ask="YES  NO")
示例#5
0
def addHints(rom, rnd, spots):
    spots = list(filter(lambda spot: spot.item in hint_items, spots))
    text_ids = hint_text_ids.copy()
    rnd.shuffle(text_ids)
    for text_id in text_ids:
        if len(spots) > 0:
            spot_index = rnd.randint(0, len(spots) - 1)
            spot = spots.pop(spot_index)
            hint = rnd.choice(hints).format(INVENTORY_NAME[spot.item].decode("ascii"), spot.metadata.area)
        else:
            hint = rnd.choice(hints).format(*rnd.choice(useless_hint))
        rom.texts[text_id] = formatText(hint.encode("ascii"))

    for text_id in range(0x200, 0x20C, 2):
        rom.texts[text_id] = formatText(b"Read this book?", ask=b"YES  NO")
    def setupUi(self, Dialog, db, course, chapter, userName):
        threading.stack_size(1228800)  #multiple of 4kB
        super().setupUi(Dialog)
        print("\n \n CHAPTER IS", chapter)
        print(chapter == "1 espace")
        if (userName == "chloé"):
            self.answerInput.selectAll()
            self.answerInput.setFontPointSize(14)
            self.questionInput.selectAll()
            self.questionInput.setFontPointSize(14)
            #self.textSlLabel.setVisible(False)
            #self.buttonSlLabel.setVisible(False)
            #self.textPoliceSlider.setVisible(False)
            #self.buttonPoliceSlider.setVisible(False)

        self.dialog = Dialog
        self.__action = ""
        self.__question = ""
        self.__answer = ""
        self.__relPathToDatabase = db
        self.__course = course
        self.__chapter = chapter
        self.__userName = userName
        self.__formatQ = []
        self.__formatA = []
        self.confirmButton.pressed.connect(
            lambda: utils.buttonPressed(self.confirmButton))
        self.confirmButton.released.connect(
            lambda: utils.buttonReleased(self.confirmButton))
        self.confirmButton.clicked.connect(self.finish)
        self.cancelButton.pressed.connect(
            lambda: utils.buttonPressed(self.cancelButton))
        self.cancelButton.released.connect(
            lambda: utils.buttonReleased(self.cancelButton))
        self.cancelButton.clicked.connect(self.cancel)
        self.newCardButton.pressed.connect(
            lambda: utils.buttonPressed(self.newCardButton))
        self.newCardButton.released.connect(
            lambda: utils.buttonReleased(self.newCardButton))
        self.newCardButton.clicked.connect(self.newCard)
        #self.textPoliceSlider.setValue(50)
        #self.textPoliceSlider.valueChanged.connect(self.changeTextPolice)
        #self.buttonPoliceSlider.setValue(50)
        #self.buttonPoliceSlider.valueChanged.connect(self.changeButtonPolice)
        self.formatMenuQ.currentIndexChanged.connect(
            lambda: utils.formatText(self.formatMenuQ, self.questionInput))
        self.formatMenuA.currentIndexChanged.connect(
            lambda: utils.formatText(self.formatMenuA, self.answerInput))
示例#7
0
文件: assembler.py 项目: loopfz/LADXR
 def insertString(self, string):
     if string.startswith('"') and string.endswith('"'):
         self.__result += string[1:-1].encode("ascii")
     elif string.startswith("m\"") and string.endswith("\""):
         self.__result += utils.formatText(string[2:-1].replace("|", "\n"))
     else:
         raise SyntaxError
示例#8
0
def upgradeTunicFairy(rom):
    rom.texts[0x268] = formatText(b"Welcome, #####. I admire you for coming this far.")
    rom.texts[0x0CC] = formatText(b"Got the Red Tunic! You can change Tunics at the phone booths.")
    rom.texts[0x0CD] = formatText(b"Got the Blue Tunic! You can change Tunics at the phone booths.")

    rom.patch(0x36, 0x111C, 0x1133, ASM("""
        call $3B12
        ld  a, [$DDE1]
        and $10
        jr  z, giveItems
        ld   [hl], $09
        ret

giveItems:
        ld  a, [$DDE1]
        or  $10
        ld  [$DDE1], a
    """), fill_nop=True)
    rom.patch(0x36, 0x1139, 0x1144, ASM("""
        ld  a, [$51BF]
        ldh [$F1], a
        ld  a, $02
        rst 8
        ld  a, $03
        rst 8
    """), fill_nop=True)

    rom.patch(0x36, 0x1162, 0x1192, ASM("""
        ld  a, [$51C0]
        ldh [$F1], a
        ld  a, $02
        rst 8
        ld  a, $03
        rst 8
        call $3B12
        ret
    """), fill_nop=True)

    rom.patch(0x36, 0x119D, 0x11A2, "", fill_nop=True)
    rom.patch(0x36, 0x11B5, 0x11BE, ASM("""
        ; Skip to the end ignoring all the tunic giving animation.
        call $3B12
        ld   [hl], $09
    """), fill_nop=True)

    rom.banks[0x36][0x11BF] = 0x87
    rom.banks[0x36][0x11C0] = 0x88
示例#9
0
def data_from_html_table(table):
    rows = table.find_all('tr')
    data = []
    for row in rows[0:15]:
        cols = row.find_all('td')
        value = re.sub(' +', ' ', cols[1].text.strip())
        data.append(formatText(value))
        if (len(cols) == 4):
            data.append(cols[3].text.strip())
    data.append(rows[15].find('select').text.strip())
    return data
def sentimentAnalysisExecute(sentence):
    obj = {}
    sentence = ut.formatText(sentence)
    # res = analyzingSentence(sentence)
    [vectorSentimentValues, arrWords] = analyzingSentence(sentence)
    # print("*", vectorSentimentValues, arrWords)
    semtinentOfSentence = predictSentence(sentence, vectorSentimentValues)
    obj["sentence"] = sentence
    obj["score"] = vectorSentimentValues.values[0, :].tolist()
    obj["predict"] = semtinentOfSentence
    obj["corpus"] = arrWords
    return obj
示例#11
0
    def patch(self, rom, option, *, multiworld=None):
        assert multiworld is None

        if self.give_bowwow:
            option = BOWWOW
            rom.texts[0xC8] = formatText(b"Got BowWow!")

        if option != SHIELD:
            rom.patch(
                5, 0x0CDA, ASM("ld a, $22"), ASM("ld a, $00")
            )  # do not change links sprite into the one with a shield

        super().patch(rom, option)
示例#12
0
文件: madBatter.py 项目: loopfz/LADXR
def upgradeMadBatter(rom):
    # Normally the madbatter won't do anything if you have full capacity. Remove that check.
    rom.patch(0x18, 0x0F05, 0x0F1D, "", fill_nop=True)
    # Remove the code that finds which upgrade to apply,
    rom.patch(0x18, 0x0F9E, 0x0FC4, "", fill_nop=True)
    rom.patch(0x18, 0x0FD2, 0x0FD8, "", fill_nop=True)

    # Finally, at the last step, give the item and the item message.
    rom.patch(0x18, 0x1016, 0x101B, "", fill_nop=True)
    rom.patch(0x18, 0x101E, 0x1051, ASM("""
        ; Mad batter rooms are E0,E1 and E2, load the item type from a table in the rom
        ; which only has 3 entries, and store it where bank 3E wants it.
        ldh a, [$F6] ; current room
        and $0F
        ld  d, $00
        ld  e, a
        ld  hl, $4F90
        add hl, de
        ld  a, [hl]
        ldh [$F1], a
    
        ; Give item
        ld  a, $06 ; giveItemMultiworld
        rst 8
        ; Message
        ld  a, $0A ; showMessageMultiworld
        rst 8
        ; Force the dialog at the bottom
        ld  a, [$C19F]
        or  $80
        ld  [$C19F], a
    """), fill_nop=True)
    # Setup the default items
    rom.patch(0x18, 0x0F90, "406060", "848586")

    rom.texts[0xE2] = formatText("You can now carry more Magic Powder!")
    rom.texts[0xE3] = formatText("You can now carry more Bombs!")
    rom.texts[0xE4] = formatText("You can now carry more Arrows!")
示例#13
0
def reduceMessageLengths(rom):
    # Into text from Marin. Got to go fast, so less text. (This intro text is very long)
    rom.texts[0x01] = formatText(b"Let's a go!")

    # Reduce length of a bunch of common texts
    rom.texts[0xEA] = formatText(b"You've got a Guardian Acorn!")
    rom.texts[0xEB] = rom.texts[0xEA]
    rom.texts[0xEC] = rom.texts[0xEA]
    rom.texts[0x08] = formatText(b"You got a Piece of Power!")
    rom.texts[0xEF] = formatText(b"You found a Secret Seashell!")
    rom.texts[0xA7] = formatText(b"You've got the Compass!")

    rom.texts[0x07] = formatText(b"You need the nightmare key!")
    rom.texts[0x8C] = formatText(b"You need a key!")  # keyhole block
示例#14
0
文件: tarin.py 项目: dragonc0/LADXR
def updateTarin(rom):
    # Do not give the shield.
    rom.patch(0x05, 0x0CD0, ASM("""
        ld   d, $04
        call $5321
        ld   a, $01
        ld   [$DB44], a 
    """), "", fill_nop=True)

    # Instead of showing the usual "your shield back" message, give the proper message and give the item.
    rom.patch(0x05, 0x0CDE, ASM("""
        ld   a, $91
        call $2385
    """), ASM("""
        ld   a, $0B ; GiveItemAndMessageForRoom
        rst  8
    """), fill_nop=True)

    rom.patch(0x05, 0x0CF0, ASM("""
        xor  a
        ldh  [$F1], a
        ld   de, $4CC6
        call $3C77
    """), ASM("""
        ld   a, $0C ; RenderItemForRoom
        rst  8
        xor  a
        ldh  [$F1], a
    """), fill_nop=True)

    # Set the room status to finished. (replaces a GBC check)
    rom.patch(0x05, 0x0CAB, 0x0CB0, ASM("""
        ld a, $20
        call $36C4
    """), fill_nop=True)

    # Instead of checking for the shield level to put you in the bed, check the room flag.
    rom.patch(0x05, 0x1202, ASM("ld a, [$DB44]\nand a"), ASM("ldh a, [$F8]\nand $20"))
    rom.patch(0x05, 0x0C6D, ASM("ld a, [$DB44]\nand a"), ASM("ldh a, [$F8]\nand $20"))

    # If the starting item is picked up, load the right palette when entering the room
    rom.patch(0x21, 0x0176, ASM("ld a, [$DB48]\ncp $01"), ASM("ld a, [$DAA3]\ncp $A1"), fill_nop=True)
    rom.patch(0x05, 0x0C94, "FF473152C5280000", "FD2ED911CE100000")
    rom.patch(0x05, 0x0CB0, ASM("ld hl, $DC88"), ASM("ld hl, $DC80"))

    # Patch the text that Tarin uses to give your shield back.
    rom.texts[0x54] = formatText(b"#####, it is dangerous to go alone!\nTake this!")
示例#15
0
    def patch(self, rom, option, *, multiworld=None):
        assert multiworld is None

        if self.give_bowwow:
            option = BOWWOW
            rom.texts[0xC8] = formatText("Got BowWow!")

        if option != SHIELD:
            rom.patch(
                5, 0x0CDA, ASM("ld a, $22"), ASM("ld a, $00")
            )  # do not change links sprite into the one with a shield

        if option in (MAGIC_POWDER, BOMB):
            re = RoomEditor(rom, 0x0A2)
            re.entities.append((1, 3, 0x41))
            re.store(rom)

        super().patch(rom, option)
def postTopic(title, content_json, channel, created_at, username, api_key,
              topic_id):

    #Set the API user context as the username of whoever wrote the original topic
    headers = {"Api-Key": api_key, "Api-Username": username}

    #Set the POST body
    body = {
        'title': title,
        'raw': formatText(content_json),
        'category': channel,
        'created_at': created_at
    }

    #Make the API call to the posts endpoint
    r = requests.post(url='https://community.retool.com/posts.json',
                      data=body,
                      headers=headers)

    #Declare the topic_mappings dataframe as global to we can write to it
    global topic_mappings

    #If the response object has a 'topic_id' key, it was successful; append a row to topic mappings
    try:
        discourse_topic_id = json.loads(r.text)['topic_id']
        #Use for debugging
        # print("Topic ID: " + str(discourse_topic_id))
        topic_mappings = topic_mappings.append(
            {
                'topic_id': topic_id,
                'discourse_topic_id': discourse_topic_id,
                'posts_posted': False
            },
            ignore_index=True)
    #If the request wasn't successful
    except:
        #If it's a rate limit error, write the new data to the topic mappings csv and get outta here
        try:
            if r['error_type'] == 'rate_limit':
                topic_mappings.to_csv('topic_mappings.csv')
                raise
        #If it's another kind of error, let it go and print the response text
        except:
            print(json.loads(r.text))
示例#17
0
def postPost(api_key, username, discourse_topic_id, content_json, created_at):

    #Set the API user context as the username of whoever wrote the original topic
    headers = {"Api-Key": api_key, "Api-Username": username}

    #Define POST body (gee, a lot of the word "post" in here)
    post_body = {
        'topic_id': discourse_topic_id,
        'raw': formatText(content_json),
        'created_at': created_at
    }

    #Use for debugging if you'd like
    #print("Topic ID: "  + str(discourse_topic_id))

    #POST message
    r = requests.post('https://community.retool.com/posts.json',
                      data=post_body,
                      headers=headers)

    #Declare the topic_mappings dataframe as global to we can write to it
    global topic_mappings

    #If the post was successfully created, the response will have 'id' in it
    if 'id' in json.loads(r.text).keys():
        print("Post successfully added")
    #If we got rate limited, the response will have 'error_type' in it
    elif 'error_type' in json.loads(r.text).keys():
        time.sleep(60)
    #If there's a different type of error, print the response
    else:
        print(r.text)

    #Set posts_posted in topic_mappings to True
    idx = topic_mappings[topic_mappings['discourse_topic_id'] ==
                         discourse_topic_id].index[0]
    topic_mappings.loc[idx, 'posts_posted'] = True
    #Write the new information to the topic mappings CSV
    topic_mappings.to_csv('topic_mappings.csv')
示例#18
0
 def setupUi(self, dialog, username, data, database, databaseFile, itemsToStudy, isRandom, spacingMistakes, minPointsRequired):
     threading.stack_size(1228800) #multiple of 4kB
     super().setupUi(dialog)
     self.__userName = username
     self.__isRandom = isRandom
     self.__dialog = dialog
     self.__data = data
     self.__database = database
     self.__databaseFile = databaseFile
     self.__itemsToStudy = []
     for s in itemsToStudy : #splitting string to get parent and child in a list
         i = s.split("{")
         if len(i) > 1:
             self.__itemsToStudy.append(i)
         else:
             self.__itemsToStudy.append(i[0])
     self.__indexChapter = 0
     self.__index = -1
     self.__nOfQuestions = 0
     self.__course = self.__itemsToStudy[0] if type(self.__itemsToStudy[0]) is str else self.__itemsToStudy[0][0]
     self.__chapter = None if type(self.__itemsToStudy[0]) is str else self.__itemsToStudy[0][1]
     self.__nOfCoursesToStudy = len([item for item in self.__itemsToStudy if (type(item) is str)])
     lCoursesToStudy = []
     self.__nOfChaptersToStudy = len([item for item in self.__itemsToStudy if type(item) is not str])
     for item in self.__itemsToStudy :
         if type(item) is not str :
             if item[0] not in lCoursesToStudy :
                 lCoursesToStudy.append(item[0])
                 self.__nOfCoursesToStudy += 1
         else : #item is a course
             self.__nOfChaptersToStudy += self.getNumberOfChapters(item)
     self.__question = ""
     self.__answer = ""
     self.__formatA = []
     self.__formatQ = []
     self.__coursesDone = 0
     self.__chaptersDone = 0
     self.__neededWork = []
     self.__playbackCounter = 0
     self.__spacingMistakes = spacingMistakes if spacingMistakes > 2 else 3
     self.__unAnsweredQuestions = []
     self.getAllQuestionsByIndex()
     self.__pointsRequired = 1
     if minPointsRequired > 1 :
         self.__pointsRequired = minPointsRequired
     #self.__pointsRequired = 2 if isRandom else 1
     self.__prevQIsWrong = False
     self.__qActive = True
     self.validateQButton.setVisible(False)
     self.needWorkButton.setVisible(False)
     self.cancelChangeButton.setVisible(False)
     self.validateChangeButton.setVisible(False)
     self.formatMenu.setVisible(False)
     self.nextQuestion()
     self.viewAnswerButton.clicked.connect(self.viewAnswer)
     self.stopButton.clicked.connect(self.stop)
     self.needWorkButton.clicked.connect(self.needsWork)
     self.validateQButton.clicked.connect(self.validateQuestion)
     self.validateChangeButton.clicked.connect(self.validateChange)
     self.cancelChangeButton.clicked.connect(self.cancelChange)
     self.editButton.clicked.connect(self.edit)
     self.formatMenu.currentIndexChanged.connect(lambda:utils.formatText(self.formatMenu, self.displayQA))
     for button in self.__dialog.findChildren(QtWidgets.QPushButton):
         button.pressed.connect(lambda:utils.buttonPressed(button))
         button.released.connect(lambda:utils.buttonReleased(button))
示例#19
0
 def assemble(self, line):
     if ";" in line:
         line = line[:line.find(";")]
     input_line = line.strip()
     line = line.strip().replace("\t", " ").upper()
     while "  " in line:
         line = line.strip().replace("  ", " ")
     if line.endswith(":"):
         line = line[:-1]
         if line.startswith("."):
             assert self.__scope + line not in self.__label, "Duplicate label: %s" % (self.__scope + line)
             self.__label[self.__scope + line] = len(self.__result)
         else:
             assert "." not in line, line
             assert line not in self.__label, "Duplicate label: %s" % (line)
             self.__label[line] = len(self.__result)
             self.__scope = line
         return
     if len(line) < 1:
         return
     if " " in line:
         mnemonic, params = line.split(" ", 1)
         params = list(map(str.strip, params.split(",")))
     else:
         mnemonic = line
         params = []
     if mnemonic == "NOP":
         assert len(params) == 0, line
         self.__result.append(0x00)
     elif mnemonic == "HALT":
         assert len(params) == 0, line
         self.__result.append(0x76)
     elif mnemonic == "STOP":
         assert len(params) == 0, line
         self.__result.append(0x10)
     elif mnemonic == "DI":
         assert len(params) == 0, line
         self.__result.append(0xF3)
     elif mnemonic == "EI":
         assert len(params) == 0, line
         self.__result.append(0xFB)
     elif mnemonic == "RLA":
         assert len(params) == 0, line
         self.__result.append(0x17)
     elif mnemonic == "RLCA":
         assert len(params) == 0, line
         self.__result.append(0x07)
     elif mnemonic == "RRA":
         assert len(params) == 0, line
         self.__result.append(0x1f)
     elif mnemonic == "RRCA":
         assert len(params) == 0, line
         self.__result.append(0x0f)
     elif mnemonic == "DAA":
         assert len(params) == 0, line
         self.__result.append(0x27)
     elif mnemonic == "SCF":
         assert len(params) == 0, line
         self.__result.append(0x37)
     elif mnemonic == "CPL":
         assert len(params) == 0, line
         self.__result.append(0x2F)
     elif mnemonic == "CCF":
         assert len(params) == 0, line
         self.__result.append(0x3F)
     elif mnemonic == "JP":
         if len(params) == 2:
             flag = FLAGS[params[0]]
             self.__result.append(0xC2 | flag)
             self.__result += self.toWord(params[1])
         elif len(params) == 1:
             if params[0] == "HL":
                 self.__result.append(0xE9)
             else:
                 self.__result.append(0xC3)
                 self.__result += self.toWord(params[0])
         else:
             raise RuntimeError("Cannot ASM: %s" % (line))
     elif mnemonic == "JR":
         if len(params) == 2:
             self.__result.append(0x20 | FLAGS[params[0]])
             params.pop(0)
         else:
             self.__result.append(0x18)
         assert len(params) == 1, line
         if params[0].startswith("$"):
             self.__result.append(self.toByte(params[0]))
         else:
             if params[0].startswith("."):
                 assert self.__scope is not None, line
                 params[0] = self.__scope + params[0]
             self.__link[len(self.__result)] = (Assembler.LINK_REL8, params[0])
             self.__result.append(0)
     elif mnemonic == "RETI":
         self.__result.append(0xD9)
     elif mnemonic == "RET":
         if len(params) == 0:
             self.__result.append(0xC9)
         elif len(params) == 1:
             self.__result.append(0xC0 | FLAGS[params[0]])
         else:
             raise RuntimeError("Cannot ASM: %s" % (line))
     elif mnemonic == "RST":
         assert len(params) == 1, line
         value = int(params[0], 16)
         assert (value & 0x07) == 0, line
         assert 0 <= value < 0x40, line
         self.__result.append(0xC7 + value)
     elif mnemonic == "PUSH":
         assert len(params) == 1, line
         if params[0] == "BC":
             self.__result.append(0xC5)
         elif params[0] == "DE":
             self.__result.append(0xD5)
         elif params[0] == "HL":
             self.__result.append(0xE5)
         elif params[0] == "AF":
             self.__result.append(0xF5)
         else:
             raise RuntimeError("Cannot ASM: %s" % (line))
     elif mnemonic == "POP":
         assert len(params) == 1, line
         if params[0] == "BC":
             self.__result.append(0xC1)
         elif params[0] == "DE":
             self.__result.append(0xD1)
         elif params[0] == "HL":
             self.__result.append(0xE1)
         elif params[0] == "AF":
             self.__result.append(0xF1)
         else:
             raise RuntimeError("Cannot ASM: %s" % (line))
     elif mnemonic == "LDI":
         assert len(params) == 2, line
         if params[0] == "A" and params[1] == "[HL]":
             self.__result.append(0x2A)
         elif params[0] == "[HL]" and params[1] == "A":
             self.__result.append(0x22)
         else:
             raise RuntimeError("Cannot ASM: %s" % (line))
     elif mnemonic == "LDD":
         assert len(params) == 2, line
         if params[0] == "A" and params[1] == "[HL]":
             self.__result.append(0x3A)
         elif params[0] == "[HL]" and params[1] == "A":
             self.__result.append(0x32)
         else:
             raise RuntimeError("Cannot ASM: %s" % (line))
     elif mnemonic == "LD":
         assert len(params) == 2, line
         dst = REGS.get(params[0])
         src = REGS.get(params[1])
         if params[0] == "A" and src is None and params[1].startswith("[") and params[1].endswith("]"):
             if params[1] == "[BC]":
                 self.__result.append(0x0A)
             elif params[1] == "[DE]":
                 self.__result.append(0x1A)
             elif params[1] == "[C]":
                 self.__result.append(0xF2)
             else:
                 self.__result.append(0xFA)
                 self.__result += self.toWord(params[1][1:-1])
         elif params[1] == "A" and dst is None and params[0].startswith("[") and params[0].endswith("]"):
             if params[0] == "[BC]":
                 self.__result.append(0x02)
             elif params[0] == "[DE]":
                 self.__result.append(0x12)
             elif params[0] == "[C]":
                 self.__result.append(0xE2)
             else:
                 self.__result.append(0xEA)
                 self.__result += self.toWord(params[0][1:-1])
         elif params[1] == "SP" and dst is None and params[0].startswith("[") and params[0].endswith("]"):
             self.__result.append(0x08)
             self.__result += self.toWord(params[0][1:-1])
         elif params[0] == "BC":
             self.__result.append(0x01)
             self.__result += self.toWord(params[1])
         elif params[0] == "DE":
             self.__result.append(0x11)
             self.__result += self.toWord(params[1])
         elif params[0] == "HL":
             self.__result.append(0x21)
             self.__result += self.toWord(params[1])
         elif params[0] == "SP" and params[1] == "HL":
             self.__result.append(0xF9)
         elif params[0] == "SP":
             self.__result.append(0x31)
             self.__result += self.toWord(params[1])
         elif dst is not None and src is not None:
             assert src != 6 or dst != 6, line
             self.__result.append(0x40 | src | (dst << 3))
         elif dst is not None:
             self.__result.append(0x06 | (dst << 3))
             self.__result.append(self.toByte(params[1]))
         else:
             raise RuntimeError("Cannot ASM: %s" % (line))
     elif mnemonic == "ADD":
         assert len(params) == 2, line
         src = REGS.get(params[1])
         if params[0] == "A" and src is not None:
             self.__result.append(0x80 | src)
         elif params[0] == "A":
             self.__result.append(0xC6)
             self.__result.append(self.toByte(params[1]))
         elif params[0] == "HL" and params[1] == "BC":
             self.__result.append(0x09)
         elif params[0] == "HL" and params[1] == "DE":
             self.__result.append(0x19)
         elif params[0] == "HL" and params[1] == "HL":
             self.__result.append(0x29)
         elif params[0] == "HL" and params[1] == "SP":
             self.__result.append(0x39)
         elif params[0] == "SP":
             self.__result.append(0xE8)
             self.__result.append(self.toByte(params[1]))
         else:
             raise RuntimeError("Cannot ASM: %s" % (line))
     elif mnemonic == "SUB":
         assert len(params) == 1, line
         reg = REGS.get(params[0])
         if reg is not None:
             self.__result.append(0x90 | reg)
         else:
             self.__result.append(0xD6)
             self.__result.append(self.toByte(params[0]))
     elif mnemonic == "ADC":
         assert len(params) == 2, line
         assert params[0] == 'A', line
         reg = REGS.get(params[1])
         if reg is not None:
             self.__result.append(0x88 | reg)
         else:
             self.__result.append(0xCE)
             self.__result.append(self.toByte(params[1]))
     elif mnemonic == "SBC":
         assert len(params) == 2, line
         assert params[0] == 'A', line
         reg = REGS.get(params[1])
         if reg is not None:
             self.__result.append(0x98 | reg)
         else:
             self.__result.append(0xDE)
             self.__result.append(self.toByte(params[1]))
     elif mnemonic == "XOR":
         assert len(params) == 1, line
         reg = REGS.get(params[0])
         if reg is not None:
             self.__result.append(0xA8 | reg)
         else:
             self.__result.append(0xEE)
             self.__result.append(self.toByte(params[0]))
     elif mnemonic == "AND":
         assert len(params) == 1, line
         reg = REGS.get(params[0])
         if reg is not None:
             self.__result.append(0xA0 | reg)
         else:
             self.__result.append(0xE6)
             self.__result.append(self.toByte(params[0]))
     elif mnemonic == "OR":
         assert len(params) == 1, line
         reg = REGS.get(params[0])
         if reg is not None:
             self.__result.append(0xB0 | reg)
         else:
             self.__result.append(0xF6)
             self.__result.append(self.toByte(params[0]))
     elif mnemonic == "CP":
         assert len(params) == 1, line
         reg = REGS.get(params[0])
         if reg is not None:
             self.__result.append(0xB8 | reg)
         else:
             self.__result.append(0xFE)
             self.__result.append(self.toByte(params[0]))
     elif mnemonic == "INC":
         assert len(params) == 1, line
         reg = REGS.get(params[0])
         if reg is not None:
             self.__result.append(0x04 | (reg << 3))
         elif params[0] == "BC":
             self.__result.append(0x03)
         elif params[0] == "DE":
             self.__result.append(0x13)
         elif params[0] == "HL":
             self.__result.append(0x23)
         elif params[0] == "SP":
             self.__result.append(0x33)
         else:
             raise RuntimeError("Cannot ASM: %s" % (line))
     elif mnemonic == "DEC":
         assert len(params) == 1, line
         reg = REGS.get(params[0])
         if reg is not None:
             self.__result.append(0x05 | (reg << 3))
         elif params[0] == "BC":
             self.__result.append(0x0B)
         elif params[0] == "DE":
             self.__result.append(0x1B)
         elif params[0] == "HL":
             self.__result.append(0x2B)
         elif params[0] == "SP":
             self.__result.append(0x3B)
         else:
             raise RuntimeError("Cannot ASM: %s" % (line))
     elif mnemonic == "LDH":
         assert len(params) == 2, line
         if params[0] == "A" and params[1].startswith("[") and params[1].endswith("]"):
             self.__result.append(0xF0)
             self.__result.append(self.toByte(params[1][1:-1]))
         elif params[1] == "A" and params[0].startswith("[") and params[0].endswith("]"):
             self.__result.append(0xE0)
             self.__result.append(self.toByte(params[0][1:-1]))
         else:
             raise RuntimeError("Cannot ASM: %s" % (line))
     elif mnemonic == "BIT":
         assert len(params) == 2, line
         reg = REGS[params[1]]
         bit = int(params[0])
         assert 0 <= bit < 8, line
         self.__result.append(0xCB)
         self.__result.append(0x40 | reg | (bit << 3))
     elif mnemonic == "RES":
         assert len(params) == 2, line
         reg = REGS[params[1]]
         bit = int(params[0])
         assert 0 <= bit < 8
         self.__result.append(0xCB)
         self.__result.append(0x80 | reg | (bit << 3))
     elif mnemonic == "SET":
         assert len(params) == 2
         reg = REGS[params[1]]
         bit = int(params[0])
         assert 0 <= bit < 8
         self.__result.append(0xCB)
         self.__result.append(0xC0 | reg | (bit << 3))
     elif mnemonic == "RLC":
         assert len(params) == 1
         reg = REGS[params[0]]
         self.__result.append(0xCB)
         self.__result.append(0x00 | reg)
     elif mnemonic == "RRC":
         assert len(params) == 1
         reg = REGS[params[0]]
         self.__result.append(0xCB)
         self.__result.append(0x08 | reg)
     elif mnemonic == "RL":
         assert len(params) == 1
         reg = REGS[params[0]]
         self.__result.append(0xCB)
         self.__result.append(0x10 | reg)
     elif mnemonic == "RR":
         assert len(params) == 1
         reg = REGS[params[0]]
         self.__result.append(0xCB)
         self.__result.append(0x18 | reg)
     elif mnemonic == "SLA":
         assert len(params) == 1
         reg = REGS[params[0]]
         self.__result.append(0xCB)
         self.__result.append(0x20 | reg)
     elif mnemonic == "SRA":
         assert len(params) == 1
         reg = REGS[params[0]]
         self.__result.append(0xCB)
         self.__result.append(0x28 | reg)
     elif mnemonic == "SWAP":
         assert len(params) == 1
         reg = REGS[params[0]]
         self.__result.append(0xCB)
         self.__result.append(0x30 | reg)
     elif mnemonic == "SRL":
         assert len(params) == 1
         reg = REGS[params[0]]
         self.__result.append(0xCB)
         self.__result.append(0x38 | reg)
     elif mnemonic == "CALL":
         if len(params) == 1:
             self.__result.append(0xCD)
             self.__result += self.toWord(params[0])
         elif len(params) == 2:
             flag = FLAGS[params[0]]
             self.__result.append(0xC4 | flag)
             self.__result += self.toWord(params[1])
         else:
             raise RuntimeError("Cannot ASM: %s" % (line))
     elif mnemonic == "DB":
         for param in map(str.strip, input_line[2:].strip().split(",")):
             if param.startswith("\"") and param.endswith("\""):
                 self.__result += param[1:-1].encode("ascii")
             elif param.startswith("m\"") and param.endswith("\""):
                 self.__result += utils.formatText(param[2:-1].encode("ascii"))
             else:
                 self.__result.append(self.toByte(param.strip()))
     elif mnemonic == "DW":
         for byte in params:
             self.__result += self.toWord(byte)
     else:
         raise RuntimeError("Cannot ASM: %s" % (line))
示例#20
0
def addBank3E(rom, seed):
    # No default text for getting the bow, so use an unused slot.
    rom.texts[0x89] = formatText("Found the {BOW}!")
    rom.texts[0xD9] = formatText(
        "Found the {BOOMERANG}!")  # owl text slot reuse
    rom.texts[0xBE] = rom.texts[
        0x111]  # owl text slot reuse to get the master skull message in the first dialog group
    rom.texts[0xC8] = formatText(
        "Found {BOWWOW}! Which monster put him in a chest? He is a good boi, and waits for you at the Swamp."
    )
    rom.texts[0xC9] = 0xC0A0  # Custom message slot
    rom.texts[0xCA] = formatText("Found {ARROWS_10}!")
    rom.texts[0xCB] = formatText("Found a {SINGLE_ARROW}... joy?")

    # Create a trampoline to bank 0x3E in bank 0x00.
    # There is very little room in bank 0, so we set this up as a single trampoline for multiple possible usages.
    # the A register is preserved and can directly be used as a jumptable in page 3E.
    # Trampoline at rst 8
    # the A register is preserved and can directly be used as a jumptable in page 3E.
    rom.patch(0,
              0x0008,
              "0000000000000000000000000000",
              ASM("""
        ld   h, a
        ld   a, [$DBAF]
        push af
        ld   a, $3E
        call $080C ; switch bank
        ld   a, h
        jp $4000
    """),
              fill_nop=True)

    # Special trampoline to jump to the damage-entity code, we use this from bowwow to damage instead of eat.
    rom.patch(
        0x00, 0x0018, "000000000000000000000000000000",
        ASM("""
        ld   a, $03
        ld   [$2100], a
        call $71C0
        ld   a, [$DBAF]
        ld   [$2100], a
        ret
    """))

    my_path = os.path.dirname(__file__)
    rom.patch(
        0x3E,
        0x0000,
        0x3000,
        ASM(
            """
        call MainJumpTable
        pop af
        jp $080C ; switch bank and return to normal code.

MainJumpTable:
        rst  0 ; JUMP TABLE
        dw   MainLoop                     ; 0
        dw   RenderChestItem              ; 1
        dw   GiveItemFromChest            ; 2
        dw   ItemMessage                  ; 3
        dw   RenderDroppedKey             ; 4
        dw   RenderHeartPiece             ; 5
        dw   GiveItemFromChestMultiworld  ; 6
        dw   CheckIfLoadBowWow            ; 7
        dw   BowwowEat                    ; 8
        dw   HandleOwlStatue              ; 9
        dw   ItemMessageMultiworld        ; A
        dw   GiveItemAndMessageForRoom    ; B
        dw   RenderItemForRoom            ; C
        dw   StartGameMarinMessage        ; D

StartGameMarinMessage:
        ; Injection to reset our frame counter
        call $27D0 ; Enable SRAM
        ld   hl, $B000
        xor  a
        ldi  [hl], a ;subsecond counter
        ld   a, $08  ;(We set the counter to 8 seconds, as it takes 8 seconds before link wakes up and marin talks to him)
        ldi  [hl], a ;second counter
        xor  a
        ldi  [hl], a ;minute counter
        ldi  [hl], a ;hour counter

        ld   hl, $B010
        ldi  [hl], a ;check counter low
        ldi  [hl], a ;check counter high

        ; Show the normal message
        ld   a, $01
        jp $2385

    """ + open(os.path.join(my_path, "bank3e.asm/multiworld.asm"),
               "rt").read() +
            open(os.path.join(my_path, "bank3e.asm/link.asm"), "rt").read() +
            open(os.path.join(my_path, "bank3e.asm/chest.asm"), "rt").read() +
            open(os.path.join(my_path, "bank3e.asm/bowwow.asm"), "rt").read() +
            open(os.path.join(my_path, "bank3e.asm/message.asm"), "rt").read()
            + open(os.path.join(my_path, "bank3e.asm/owl.asm"), "rt").read(),
            0x4000),
        fill_nop=True)
    # 3E:3300-3616: Multiworld flags per room (for both chests and dropped keys)
    # 3E:3800-3B16: DroppedKey item types
    # 3E:3B16-3E2C: Owl statue items

    # Put 20 rupees in all owls by default.
    rom.patch(0x3E, 0x3B16, "00" * 0x316, "1C" * 0x316)

    rom.patch(0x3E, 0x2F00, "00" * len(seed), binascii.hexlify(seed))

    # Prevent the photo album from crashing due to serial interrupts
    rom.patch(0x28, 0x00D2, ASM("ld a, $09"), ASM("ld a, $01"))
示例#21
0
文件: bank3e.py 项目: dragonc0/LADXR
def addBank3E(rom, seed):
    # No default text for getting the bow, so use an unused slot.
    rom.texts[0x89] = formatText(b"Found the bow!")
    rom.texts[0xD9] = formatText(
        b"Found the boomerang!")  # owl text slot reuse
    rom.texts[0xBE] = rom.texts[
        0x111]  # owl text slot reuse to get the master skull message in the first dialog group
    for idx in range(8):
        rom.texts[0xBF + idx] = b""
    rom.texts[0xC7] = b""
    rom.texts[0xC8] = formatText(
        b"Found BowWow! Which monster put him in a chest? He is a good boi, and waits for you at the Swamp."
    )
    rom.texts[0xC9] = 0xC0A0  # Custom message slot
    rom.texts[0xCA] = formatText(b"Found 10 arrows!")
    rom.texts[0xCB] = formatText(b"Found a single arrow... joy?")

    # Create a trampoline to bank 0x3E in bank 0x00.
    # There is very little room in bank 0, so we set this up as a single trampoline for multiple possible usages.
    # the A register is preserved and can directly be used as a jumptable in page 3E.
    # Trampoline at rst 8
    # the A register is preserved and can directly be used as a jumptable in page 3E.
    rom.patch(0,
              0x0008,
              "0000000000000000000000000000",
              ASM("""
        ld   h, a
        ld   a, [$DBAF]
        push af
        ld   a, $3E
        call $080C ; switch bank
        ld   a, h
        jp $4000
    """),
              fill_nop=True)

    # Special trampoline to jump to the damage-entity code, we use this from bowwow to damage instead of eat.
    rom.patch(
        0x00, 0x0018, "000000000000000000000000000000",
        ASM("""
        ld   a, $03
        ld   [$2100], a
        call $71C0
        ld   a, [$DBAF]
        ld   [$2100], a
        ret
    """))

    my_path = os.path.dirname(__file__)
    rom.patch(
        0x3E,
        0x0000,
        0x3000,
        ASM(
            """
        call MainJumpTable
        pop af
        jp $080C ; switch bank and return to normal code.

MainJumpTable:
        rst  0 ; JUMP TABLE
        dw   MainLoop                     ; 0
        dw   RenderChestItem              ; 1
        dw   GiveItemFromChest            ; 2
        dw   ItemMessage                  ; 3
        dw   RenderDroppedKey             ; 4
        dw   RenderHeartPiece             ; 5
        dw   GiveItemFromChestMultiworld  ; 6
        dw   CheckIfLoadBowWow            ; 7
        dw   BowwowEat                    ; 8
        dw   HandleOwlStatue              ; 9
        dw   ItemMessageMultiworld        ; A
        dw   GiveItemAndMessageForRoom    ; B
        dw   RenderItemForRoom            ; C

    """ + open(os.path.join(my_path, "bank3e.asm/link.asm"), "rt").read() +
            open(os.path.join(my_path, "bank3e.asm/chest.asm"), "rt").read() +
            open(os.path.join(my_path, "bank3e.asm/bowwow.asm"), "rt").read() +
            open(os.path.join(my_path, "bank3e.asm/message.asm"), "rt").read()
            + open(os.path.join(my_path, "bank3e.asm/owl.asm"), "rt").read(),
            0x4000),
        fill_nop=True)
    # 3E:3300-3616: Multiworld flags per room (for both chests and dropped keys)
    # 3E:3800-3B16: DroppedKey item types
    # 3E:3B16-3E2C: Owl statue items

    # Put 20 rupees in all owls by default.
    rom.patch(0x3E, 0x3B16, "00" * 0x316, "1C" * 0x316)

    rom.patch(0x3E, 0x2F00, "00" * len(seed), binascii.hexlify(seed))
示例#22
0
def setSeashellGoal(rom, count):
    rom.texts[0x1A3] = formatText(b"You need %d seashells" % (count))

    # Remove the seashell mansion handler (as it will take your seashells) but put a heartpiece instead
    re = RoomEditor(rom, 0x2E9)
    re.entities = [(4, 4, 0x35)]
    re.store(rom)

    rom.patch(0x19,
              0x0ACB,
              0x0C21,
              ASM(
                  """
        ldh  a, [$F8] ; room status
        and  $10
        ret  nz
        ldh  a, [$F0] ; active entity state
        rst  0
        dw   state0, state1, state2, state3, state4

state0:
        ld   a, [$C124] ; room transition state
        and  a
        ret  nz
        ldh  a, [$99]  ; link position Y
        cp   $70
        ret  nc
        jp   $3B12  ; increase entity state

state1:
        call $0C05 ; get entity transition countdown
        jr   nz, renderShells
        ld   [hl], $10
        call renderShells

        ld   hl, $C2B0 ; private state 1 table
        add  hl, bc
        ld   a, [wSeashellsCount]
        cp   [hl]
        jp   z, $3B12  ; increase entity state
        ld   a, [hl]   ; increase the amount of compared shells
        inc  a
        daa
        ld   [hl], a
        ld   hl, $C2C0 ; private state 2 table
        add  hl, bc
        inc  [hl] ; increase amount of displayed shells
        ld   a, $2B
        ldh  [$F4], a ; SFX
        ret

state2:
        ld   a, [wSeashellsCount]
        cp   $%02d
        jr   c, renderShells
        ; got enough shells
        call $3B12 ; increase entity state
        call $0C05 ; get entity transition countdown
        ld   [hl], $40
        jp   renderShells

state3:
        ld   a, $23
        ldh  [$F2], a ; SFX: Dungeon opened
        ld   hl, $D806 ; egg room status
        set  4, [hl]
        ld   a, [hl]
        ldh  [$F8], a ; current room status
        call $3B12 ; increase entity state

        ld   a, $00
        jp   $4C2E

state4:
        ret

renderShells:
        ld   hl, $C2C0 ; private state 2 table
        add  hl, bc
        ld   a, [hl]
        cp   $14
        jr   c, .noMax
        ld   a, $14
.noMax:
        and  a
        ret  z
        ld   c, a
        ld   hl, spriteRect
        call $3CE6 ; RenderActiveEntitySpritesRect
        ret

spriteRect:
        db $10, $1E, $1E, $0C
        db $10, $2A, $1E, $0C
        db $10, $36, $1E, $0C
        db $10, $42, $1E, $0C
        db $10, $4E, $1E, $0C

        db $10, $5A, $1E, $0C
        db $10, $66, $1E, $0C
        db $10, $72, $1E, $0C
        db $10, $7E, $1E, $0C
        db $10, $8A, $1E, $0C

        db $24, $1E, $1E, $0C
        db $24, $2A, $1E, $0C
        db $24, $36, $1E, $0C
        db $24, $42, $1E, $0C
        db $24, $4E, $1E, $0C

        db $24, $5A, $1E, $0C
        db $24, $66, $1E, $0C
        db $24, $72, $1E, $0C
        db $24, $7E, $1E, $0C
        db $24, $8A, $1E, $0C
    """ % (count), 0x4ACB),
              fill_nop=True)
示例#23
0
    def patch(self, rom, option, *, multiworld=None):
        assert multiworld is None

        # Always have the boomerang trade guy enabled (normally you need the magnifier)
        rom.patch(0x19,
                  0x05EC,
                  ASM("ld a, [wTradeSequenceItem]\ncp $0E"),
                  ASM("ld a, $0E\ncp $0E"),
                  fill_nop=True)  # show the guy
        rom.patch(0x00,
                  0x3199,
                  ASM("ld a, [wTradeSequenceItem]\ncp $0E"),
                  ASM("ld a, $0E\ncp $0E"),
                  fill_nop=True)  # load the proper room layout

        if self.setting == 'trade':
            inv = INVENTORY_MAP[option]
            # Patch the check if you traded back the boomerang (so traded twice)
            rom.patch(0x19, 0x063F, ASM("cp $0D"), ASM("cp $%s" % (inv)))
            # Item to give by "default" (aka, boomerang)
            rom.patch(0x19, 0x06C1, ASM("ld a, $0D"), ASM("ld a, $%s" % (inv)))
            # Check if inventory slot is boomerang to give back item in this slot
            rom.patch(0x19, 0x06FC, ASM("cp $0D"), ASM("cp $%s" % (inv)))
            # Put the boomerang ID in the inventory of the boomerang guy (aka, traded back)
            rom.patch(0x19, 0x0710, ASM("ld a, $0D"), ASM("ld a, $%s" % (inv)))

            rom.texts[0x222] = formatText("Okay, let's do it!")
            rom.texts[0x224] = formatText(
                "You got the {%s} in exchange for the item you had." %
                (option))
            rom.texts[0x225] = formatText(
                "Give me back my {%s}, I beg you! I'll return the item you gave me"
                % (option),
                ask="Okay Not Now")
            rom.texts[0x226] = formatText(
                "The item came back to you. You returned the other item.")
        else:
            # Patch the inventory trade to give an specific item instead
            rom.texts[0x221] = formatText(
                "I found a good item washed up on the beach... Want to have it?",
                ask="Okay No")
            rom.patch(0x19,
                      0x069C,
                      0x06C6,
                      ASM("""
                ; Mark trade as done
                ld a, $06
                ld [$DB7D], a

                ld a, [$472B]
                ldh [$F1], a
                ld a, $02
                rst 8
                
                ld a, $0D
            """),
                      fill_nop=True)
            # Show the right item above link
            rom.patch(0x19,
                      0x0786,
                      0x0793,
                      ASM("""
                ld a, [$472B]
                ldh [$F1], a
                ld a, $01
                rst 8
            """),
                      fill_nop=True)
            # Give the proper message for this item
            rom.patch(0x19,
                      0x075A,
                      0x076A,
                      ASM("""
                ld a, [$472B]
                ldh [$F1], a
                ld a, $03
                rst 8
            """),
                      fill_nop=True)
            rom.patch(0x19, 0x072B, "00", "%02X" % (CHEST_ITEMS[option]))

            # Ignore the trade back.
            rom.texts[0x225] = formatText("It's a secret to everybody.")
            rom.patch(0x19,
                      0x0668,
                      ASM("ld a, [$DB7D]"),
                      ASM("ret"),
                      fill_nop=True)
示例#24
0
def setRaftGoal(rom):
    rom.texts[0x1A3] = formatText(b"Just sail away.")

    # Remove the egg and egg event handler.
    re = RoomEditor(rom, 0x006)
    for x in range(4, 7):
        for y in range(0, 4):
            re.removeObject(x, y)
    re.objects.append(ObjectHorizontal(4, 1, 0x4d, 3))
    re.objects.append(ObjectHorizontal(4, 2, 0x03, 3))
    re.objects.append(ObjectHorizontal(4, 3, 0x03, 3))
    re.entities = []
    re.updateOverlay()
    re.store(rom)

    re = RoomEditor(rom, 0x08D)
    re.objects[6].count = 4
    re.objects[7].x += 2
    re.objects[7].type_id = 0x2B
    re.objects[8].x += 2
    re.objects[8].count = 2
    re.objects[9].x += 1
    re.objects[11] = ObjectVertical(7, 5, 0x37, 2)
    re.objects[12].x -= 1
    re.objects[13].x -= 1
    re.objects[14].x -= 1
    re.objects[14].type_id = 0x34
    re.objects[17].x += 3
    re.objects[17].count -= 3
    re.updateOverlay()
    re.overlay[7 + 60] = 0x33
    re.store(rom)

    re = RoomEditor(rom, 0x0E9)
    re.objects[30].count = 1
    re.objects[30].x += 2
    re.overlay[7 + 70] = 0x0E
    re.overlay[8 + 70] = 0x0E
    re.store(rom)
    re = RoomEditor(rom, 0x0F9)
    re.objects = [
        ObjectHorizontal(4, 0, 0x0E, 6),
        ObjectVertical(9, 0, 0xCA, 8),
        ObjectVertical(8, 0, 0x0E, 8),
        Object(3, 0, 0x38),
        Object(3, 1, 0x32),
        ObjectHorizontal(4, 1, 0x2C, 3),
        Object(7, 1, 0x2D),
        ObjectVertical(7, 2, 0x38, 5),
        Object(7, 7, 0x34),
        ObjectHorizontal(0, 7, 0x2F, 7),
        ObjectVertical(2, 3, 0xE8, 4),
        ObjectVertical(3, 2, 0xE8, 5),
        ObjectVertical(4, 2, 0xE8, 2),
        ObjectVertical(4, 4, 0x5C, 3),
        ObjectVertical(5, 2, 0x5C, 5),
        ObjectVertical(6, 2, 0x5C, 5),
        Object(6, 4, 0xC6),
        ObjectWarp(1, 0x1F, 0xF6, 136, 112)
    ]
    re.updateOverlay(True)
    re.entities.append((0, 0, 0x41))
    re.store(rom)
    re = RoomEditor(rom, 0x1F6)
    re.objects[-1].target_x -= 16
    re.store(rom)

    # Fix the raft graphics (this overrides some unused graphic tiles)
    rom.banks[0x31][0x21C0:0x2200] = rom.banks[0x2E][0x07C0:0x0800]

    # Patch the owl entity to run our custom end handling.
    rom.patch(0x06,
              0x27F5,
              0x2A77,
              ASM("""
        ld  a, [$DB95]
        cp  $0B
        ret nz
        ; If map is not fully loaded, return
        ld  a, [$C124]
        and a
        ret nz
        ; Check if we are moving off the bottom of the map
        ldh a, [$99]
        cp  $7D
        ret c
        ; Move link back so it does not move off the map
        ld  a, $7D
        ldh [$99], a
        
        xor a
        ld  e, a
        ld  d, a

raftSearchLoop:
        ld  hl, $C280
        add hl, de
        ld  a, [hl]
        and a
        jr  z, .skipEntity
        
        ld  hl, $C3A0
        add hl, de
        ld  a, [hl]
        cp  $6A
        jr  nz, .skipEntity

        ; Raft found, check if near the bottom of the screen.
        ld  hl, $C210
        add hl, de
        ld  a, [hl]
        cp  $70
        jr  nc, raftOffWorld

.skipEntity:
        inc e
        ld  a, e
        cp  $10
        jr  nz, raftSearchLoop
        ret

raftOffWorld:
        ; Switch to the end credits
        ld  a, $01
        ld  [$DB95], a
        ld  a, $00
        ld  [$DB96], a
        ret
    """),
              fill_nop=True)

    # We need to run quickly trough part of the credits, or else it bugs out
    # Skip the whole windfish part.
    rom.patch(0x17, 0x0D39, None, ASM("ld a, $18\nld [$D00E], a\nret"))
    # And skip the zoomed out laying on the log
    rom.patch(0x17, 0x20ED, None, ASM("ld a, $00"))
    # Finally skip some waking up on the log.
    rom.patch(0x17, 0x23BC, None, ASM("jp $4CD9"))
    rom.patch(0x17, 0x2476, None, ASM("jp $4CD9"))
示例#25
0
def setRequiredInstrumentCount(rom, count):
    if count >= 8:
        return
    if count < 0:
        rom.patch(0x00,
                  0x31f5,
                  ASM("ld a, [$D806]\nand $10\njr z, $25"),
                  ASM(""),
                  fill_nop=True)
        rom.patch(0x20,
                  0x2dea,
                  ASM("ld a, [$D806]\nand $10\njr z, $29"),
                  ASM(""),
                  fill_nop=True)
        count = 0

    # TODO: Music bugs out at the end, unless you have all instruments.
    rom.texts[0x1A3] = formatText(b"You need %d instruments" % (count))
    rom.patch(
        0x19, 0x0B79, None, "0000"
    )  # always spawn all instruments, we need the last one as that handles opening the egg.
    rom.patch(0x19, 0x0BF4, ASM("jp $3BC0"), ASM("jp $7FE0")
              )  # instead of rendering the instrument, jump to the code below.
    rom.patch(0x19,
              0x0BFE,
              ASM("""
        ; Normal check fo all instruments
        ld   e, $08
        ld   hl, $DB65
    loop:
        ldi  a, [hl]
        and  $02
        jr   z, $12
        dec  e
        jr   nz, loop
    """),
              ASM("""
        jp   $7F2B ; jump to the end of the bank, where there is some space for code.
    """),
              fill_nop=True)
    # Add some code at the end of the bank, as we do not have enough space to do this "in place"
    rom.patch(0x19,
              0x3F2B,
              "0000000000000000000000000000000000000000000000000000",
              ASM("""
        ld   d, $00
        ld   e, $08
        ld   hl, $DB65 ; start of has instrument memory
loop:
        ld   a, [hl]
        and  $02
        jr   z, noinc
        inc  d
noinc:
        inc  hl
        dec  e
        jr   nz, loop
        ld   a, d
        cp   $%02x    ; check if we have a minimal of this amount of instruments.
        jp   c, $4C1A ; not enough instruments
        jp   $4C0B    ; enough instruments
    """ % (count)),
              fill_nop=True)
    rom.patch(0x19,
              0x3FE0,
              "0000000000000000000000000000000000000000000000000000",
              ASM("""
    ; Entry point of render code
        ld   hl, $DB65  ; table of having instruments
        push bc
        ldh  a, [$F1]
        ld   c, a
        add  hl, bc
        pop  bc
        ld   a, [hl]
        and  $02        ; check if we have this instrument
        ret  z
        jp   $3BC0 ; jump to render code
    """),
              fill_nop=True)
示例#26
0
def fixChests(rom):
    # Patch the chest code, so it can give a lvl1 sword.
    # Normally, there is some code related to the owl event when getting the tail key,
    # as we patched out the owl. We use it to jump to our custom code in bank $3E to handle getting the item
    rom.patch(0x03,
              0x109C,
              ASM("""
        cp $11 ; if not tail key, skip
        jr nz, end
        push af
        ld   a, [$C501]
        ld   e, a
        ld   hl, $C2F0
        add  hl, de
        ld   [hl], $38
        pop af
    end:
        ld   e, a
        cp   $21 ; if is message chest or higher number, next instruction is to skip giving things.
    """),
              ASM("""
        ld   a, $06 ; GiveItemMultiworld
        rst  8

        and  a   ; clear the carry flag to always skip giving stuff.
    """),
              fill_nop=True)

    # Instead of the normal logic to on which sprite data to show, we jump to our custom code in bank 3E.
    rom.patch(0x07,
              0x3C36,
              None,
              ASM("""
        ld   a, $01
        rst  8
        jp $7C5E
    """),
              fill_nop=True)

    # Instead of the normal logic of showing the proper dialog, we jump to our custom code in bank 3E.
    rom.patch(
        0x07, 0x3C9C, None,
        ASM("""
        ld   a, $0A ; showItemMessageMultiworld
        rst  8
        jp $7CE9
    """))

    # Sound to play is normally loaded from a table, which is no longer big enough. So always use the same sound.
    rom.patch(0x07,
              0x3C81,
              ASM("""
        add  hl, de
        ld   a, [hl]
    """),
              ASM("ld a, $01"),
              fill_nop=True)

    # Always spawn seashells even if you have the L2 sword
    rom.patch(0x14, 0x192F, ASM("ld a, $1C"), ASM("ld a, $20"))

    rom.texts[0x9A] = formatText("You found 10 {BOMB}!")
示例#27
0
    def setupUi(self, Dialog, data, databaseFile, course, userName, chapter = None):
        threading.stack_size(1228800) #multiple of 4kB
        super().setupUi(Dialog)
        #self.fullScreenSize = QtWidgets.QDesktopWidget().availableGeometry().size()
        if (userName == "chloé"):
            self.displayAnswer.selectAll()
            self.displayAnswer.setFontPointSize(14)
            self.displayQuestion.selectAll()
            self.displayQuestion.setFontPointSize(14)
            #self.sliderButtonLabel.setVisible(False)
            #self.sliderTextLabel.setVisible(False)
            #self.textPoliceSlider.setVisible(False)
            #self.buttonPoliceSlider.setVisible(False)

        self.dialog = Dialog
        self.__action = ""
        self.__data = data
        self.__databaseFile = databaseFile
        self.__course = course
        self.__chapter = chapter
        self.__userName = userName
        self.__currentChapter = ""
        self.__question = ""
        self.__answer = ""
        self.__index = 0
        self.__indexChapter = 0
        self.__formatQ = []
        self.__formatA = []
        if self.__chapter is not None : 
            self.__indexChapter = self.getIndexOfChapter()
        self.__numberOfQInChapter = 0
        self.validateChangeButton.setVisible(False)

        self.deleteButton.pressed.connect(lambda:utils.buttonPressed(self.deleteButton))
        self.deleteButton.released.connect(lambda:utils.buttonReleased(self.deleteButton))
        self.deleteButton.clicked.connect(self.delete)

        self.editButton.pressed.connect(lambda:utils.buttonPressed(self.editButton))
        self.editButton.released.connect(lambda:utils.buttonReleased(self.editButton))
        self.editButton.clicked.connect(self.edit)

        self.stopButton.pressed.connect(lambda:utils.buttonPressed(self.stopButton))
        self.stopButton.released.connect(lambda:utils.buttonReleased(self.stopButton))
        self.stopButton.clicked.connect(self.stop)

        self.nextButton.pressed.connect(lambda:utils.buttonPressed(self.nextButton))
        self.nextButton.released.connect(lambda:utils.buttonReleased(self.nextButton))
        self.nextButton.clicked.connect(self.next)

        self.previousButton.pressed.connect(lambda:utils.buttonPressed(self.previousButton))
        self.previousButton.released.connect(lambda:utils.buttonReleased(self.previousButton))
        self.previousButton.clicked.connect(self.previous)

        self.insertButton.pressed.connect(lambda:utils.buttonPressed(self.insertButton))
        self.insertButton.released.connect(lambda:utils.buttonReleased(self.insertButton))
        self.insertButton.clicked.connect(self.insert)
        #self.displayAnswer.setAutoFormatting(QtWidgets.QTextEdit.AutoBulletList)
        #self.displayQuestion.setAutoFormatting(QtWidgets.QTextEdit.AutoBulletList)

        self.displayChapter.setText(self.getchapterFromIndex())
        #self.textPoliceSlider.setValue(50)
        #self.textPoliceSlider.valueChanged.connect(self.changeTextPolice)
        #self.buttonPoliceSlider.setValue(50)
        #self.buttonPoliceSlider.valueChanged.connect(self.changeButtonPolice)

        self.readyToValidate = False
        self.validateChangeButton.clicked.connect(self.validateChange)
        self.displayChapter.repaint()
        self.validateChangeButton.repaint()
        self.display()
        
        self.formatMenuQ.setVisible(False)
        self.formatMenuQ.currentIndexChanged.connect(lambda:utils.formatText(self.formatMenuQ, self.displayQuestion))
        self.formatMenuA.setVisible(False)
        self.formatMenuA.currentIndexChanged.connect(lambda:utils.formatText(self.formatMenuA, self.displayAnswer))
示例#28
0
def reduceMessageLengths(rom, rnd):
    # Into text from Marin. Got to go fast, so less text. (This intro text is very long)
    rom.texts[0x01] = formatText(
        rnd.choice([
            "Let's a go!",
            "Remember, sword goes on A!",
            "Avoid the heart piece of shame!",
            "Marin? No, this is Zelda. Welcome to Hyrule",
            "Why are you in my bed?",
            "This is not a Mario game!",
            "MuffinJets was here...",
            "Remember, there are no bugs in LADX",
            "#####, #####, you got to wake up!\nDinner is ready.",
            "Go find the stepladder",
            "Pizza power!",
            "Eastmost penninsula is the secret",
            "There is no cow level",
            "You cannot lift rocks with your bear hands",
        ]))

    # Reduce length of a bunch of common texts
    rom.texts[0xEA] = formatText("You've got a Guardian Acorn!")
    rom.texts[0xEB] = rom.texts[0xEA]
    rom.texts[0xEC] = rom.texts[0xEA]
    rom.texts[0x08] = formatText("You got a Piece of Power!")
    rom.texts[0xEF] = formatText("You found a {SEASHELL}!")
    rom.texts[0xA7] = formatText("You've got the {COMPASS}!")

    rom.texts[0x07] = formatText("You need the {NIGHTMARE_KEY}!")
    rom.texts[0x8C] = formatText("You need a {KEY}!")  # keyhole block

    rom.texts[0x09] = formatText(
        "Ahhh... It has  the Sleepy {TOADSTOOL}, it does! We'll mix it up something in a jiffy, we will!"
    )
    rom.texts[0x0A] = formatText(
        "The last thing I kin remember was bitin' into a big juicy {TOADSTOOL}... Then, I had the darndest dream... I was a raccoon! Yeah, sounds strange, but it sure was fun!"
    )
    rom.texts[0x0F] = formatText(
        "You pick the {TOADSTOOL}... As you hold it over your head, a mellow aroma flows into your nostrils."
    )
    rom.texts[0x13] = formatText(
        "You've learned the ^{SONG1}!^ This song will always remain in your heart!"
    )
    rom.texts[0x18] = formatText("Will you give me 28 {RUPEES} for my secret?",
                                 ask="Give Don't")
    rom.texts[0x19] = formatText(
        "How about it? 42 {RUPEES} for my little secret...", ask="Give Don't")
    rom.texts[0x1e] = formatText(
        "...You're so cute! I'll give you a 7 {RUPEE} discount!")
    rom.texts[0x2d] = formatText("{ARROWS_10}\n10 {RUPEES}!", ask="Buy  Don't")
    rom.texts[0x32] = formatText("{SHIELD}\n20 {RUPEES}!", ask="Buy  Don't")
    rom.texts[0x33] = formatText("Ten {BOMB}\n10 {RUPEES}", ask="Buy  Don't")
    rom.texts[0x3d] = formatText(
        "It's a {SHIELD}! There is space for your name!")
    rom.texts[0x42] = formatText(
        "It's 30 {RUPEES}! You can play the game three more times with this!")
    rom.texts[0x45] = formatText(
        "How about some fishing, little buddy? I'll only charge you 10 {RUPEES}...",
        ask="Fish Not Now")
    rom.texts[0x4b] = formatText(
        "Wow! Nice Fish! It's a lunker!! I'll give you a 20 {RUPEE} prize! Try again?",
        ask="Cast Not Now")
    rom.texts[0x4e] = formatText(
        "You're short of {RUPEES}? Don't worry about it. You just come back when you have more money, little buddy."
    )
    rom.texts[0x4f] = formatText(
        "You've got a {HEART_PIECE}! Press SELECT on the Subscreen to see.")
    rom.texts[0x8e] = formatText(
        "Well, it's an {OCARINA}, but you don't know how  to play it...")
    rom.texts[0x90] = formatText(
        "You found the {POWER_BRACELET}! At last, you can pick up pots and stones!"
    )
    rom.texts[0x91] = formatText(
        "You got your {SHIELD} back! Press the button and repel enemies with it!"
    )
    rom.texts[0x93] = formatText(
        "You've got the {HOOKSHOT}! Its chain stretches long when you use it!")
    rom.texts[0x94] = formatText(
        "You've got the {MAGIC_ROD}! Now you can burn things! Burn it! Burn, baby burn!"
    )
    rom.texts[0x95] = formatText(
        "You've got the {PEGASUS_BOOTS}! If you hold down the Button, you can dash!"
    )
    rom.texts[0x96] = formatText(
        "You've got the {OCARINA}! You should learn to play many songs!")
    rom.texts[0x97] = formatText(
        "You've got the {FEATHER}! It feels like your body is a  lot lighter!")
    rom.texts[0x98] = formatText(
        "You've got a {SHOVEL}! Now you can feel the joy of digging!")
    rom.texts[0x99] = formatText(
        "You've got some {MAGIC_POWDER}! Try sprinkling it on a variety of things!"
    )
    rom.texts[0x9b] = formatText(
        "You found your {SWORD}!  It must be yours because it has your name engraved on it!"
    )
    rom.texts[0x9c] = formatText(
        "You've got the {FLIPPERS}! If you press the B Button while you swim, you can dive underwater!"
    )
    rom.texts[0x9e] = formatText(
        "You've got a new {SWORD}! You should put your name on it right away!")
    rom.texts[0x9f] = formatText(
        "You've got a new {SWORD}! You should put your name on it right away!")
    rom.texts[0xa0] = formatText(
        "You found the {MEDICINE}! You should apply this and see what happens!"
    )
    rom.texts[0xa1] = formatText(
        "You've got the {TAIL_KEY}! Now you can open the Tail Cave gate!")
    rom.texts[0xa2] = formatText(
        "You've got the {SLIME_KEY}! Now you can open the gate in Ukuku Prairie!"
    )
    rom.texts[0xa3] = formatText("You've got the {ANGLER_KEY}!")
    rom.texts[0xa4] = formatText("You've got the {FACE_KEY}!")
    rom.texts[0xa5] = formatText("You've got the {BIRD_KEY}!")
    rom.texts[0xa6] = formatText(
        "At last, you got a {MAP}! Press the START Button to look at it!")
    rom.texts[0xa8] = formatText(
        "You found a {STONE_BEAK}! Let's find the owl statue that belongs to it."
    )
    rom.texts[0xa9] = formatText(
        "You've got the {NIGHTMARE_KEY}! Now you can open the door to the Nightmare's Lair!"
    )
    rom.texts[0xaa] = formatText(
        "You got a {KEY}! You can open a locked door.")
    rom.texts[0xab] = formatText("You got 20 {RUPEES}! JOY!", center=True)
    rom.texts[0xac] = formatText("You got 50 {RUPEES}! Very Nice!",
                                 center=True)
    rom.texts[0xad] = formatText("You got 100 {RUPEES}! You're Happy!",
                                 center=True)
    rom.texts[0xae] = formatText("You got 200 {RUPEES}! You're Ecstatic!",
                                 center=True)
    rom.texts[0xdc] = formatText(
        "Ribbit! Ribbit! I'm Mamu, on vocals! But I don't need to tell you that, do I? Everybody knows me! Want to hang out and listen to us jam? For 300 Rupees, we'll let you listen to a previously unreleased cut! What do you do?",
        ask="Pay Leave")
    rom.texts[0xe8] = formatText(
        "You've found a {GOLD_LEAF}! Press START to see how many you've collected!"
    )
    rom.texts[0xed] = formatText(
        "You've got the Mirror Shield! You can now turnback the beams you couldn't block before!"
    )
    rom.texts[0xee] = formatText(
        "You've got a more Powerful {POWER_BRACELET}! Now you can almost lift a whale!"
    )
    rom.texts[0xf0] = formatText(
        "Want to go on a raft ride for a hundred {RUPEES}?", ask="Yes No Way")
示例#29
0
    def patch(self, rom, option, *, multiworld=None):
        assert multiworld is None

        if self.give_bowwow:
            option = BOWWOW
            rom.texts[0xC8] = formatText(b"Got BowWow!")
            rom.patch(0x05,
                      0x0CD0,
                      0x0CDA,
                      ASM("""
                ld   a, $01
                ld   [$DB56], a
            """),
                      fill_nop=True)
            rom.patch(0x05, 0x0CF3, ASM("ld de, $4CC6\ncall $3C77"),
                      ASM("ld de, $401C\ncall $3BC0"))
            rom.patch(
                5, 0x0CDA, ASM("ld a, $22"), ASM("ld a, $00")
            )  # do not change links sprite into the one with a shield
        else:
            # Change which item you get at the start.
            rom.patch(5, 0x0CD1, "04", INVENTORY_MAP[option])
            rom.patch(5, 0x0CC6, "8617", INVENTORY_ICON[option]
                      )  # patch shield that icon that is shown.
            if option != SHIELD:
                rom.patch(
                    5, 0x0CDA, ASM("ld a, $22"), ASM("ld a, $00")
                )  # do not change links sprite into the one with a shield
                #   Do not set the shield level to 1, but potentially set another item level if needed.
                if option == SWORD:
                    # TOFIX: This directly hides marin and tarin
                    rom.patch(5,
                              0x0CD7,
                              ASM("ld [$DB44], a"),
                              ASM("ld [$DB4E], a"),
                              fill_nop=True)
                elif option == POWER_BRACELET:
                    rom.patch(5,
                              0x0CD7,
                              ASM("ld [$DB44], a"),
                              ASM("ld [$DB43], a"),
                              fill_nop=True)
                else:
                    rom.patch(5,
                              0x0CD7,
                              ASM("ld [$DB44], a"),
                              "",
                              fill_nop=True)

        # Patch the text that Tarin uses to give your shield back.
        rom.texts[0x54] = formatText(
            b"#####, it is dangerous to go alone!\nTake this!")
        rom.patch(5, 0x0CDE, ASM("ld a, $91"),
                  ASM("ld a, $%02x" % (self.MESSAGE[option])))

        rom.patch(0x05,
                  0x0CAB,
                  0x0CB0,
                  ASM("""
            ; Set the room status to finished.
            ld a, $20
            call $36C4
        """),
                  fill_nop=True)

        # Instead of checking for the shield level to put you in the bed, check the room flag.
        rom.patch(0x05, 0x1202, ASM("ld a, [$DB44]\nand a"),
                  ASM("ldh a, [$F8]\nand $20"))
        rom.patch(0x05, 0x0C6D, ASM("ld a, [$DB44]\nand a"),
                  ASM("ldh a, [$F8]\nand $20"))

        # If the starting item is picked up, load the right palette when entering the room
        rom.patch(0x21,
                  0x0176,
                  ASM("ld a, [$DB48]\ncp $01"),
                  ASM("ld a, [$DAA3]\ncp $A1"),
                  fill_nop=True)
        rom.patch(0x05, 0x0C94, "FF473152C5280000", "FD2ED911CE100000")
        rom.patch(0x05, 0x0CB0, ASM("ld hl, $DC88"), ASM("ld hl, $DC80"))
示例#30
0
def removeOwlEvents(rom):
    # Remove all the owl events from the entity tables.
    for room in range(0x100):
        re = RoomEditor(rom, room)
        if re.hasEntity(0x41):
            re.removeEntities(0x41)
            re.store(rom)
    # Clear texts used by the owl. Potentially reused somewhere o else.
    rom.texts[0x0D9] = b'\xff'  # used by boomerang
    # 1 Used by empty chest (master stalfos message)
    # 8 unused (0x0C0-0x0C7)
    # 1 used by bowwow in chest
    # 1 used by item for other player message
    # 2 used by arrow chest messages
    # 2 used by tunics
    for idx in range(0x0BE, 0x0CE):
        rom.texts[idx] = b'\xff'


    # Patch the owl entity into a ghost to allow refill of powder/bombs/arrows
    rom.texts[0xC0] = formatText("Everybody hates me, so I give away free things in the hope people will love me. Want something?", ask="Okay No")
    rom.texts[0xC1] = formatText("Good for you.")
    rom.patch(0x06, 0x27F5, 0x2A77, ASM("""
    ; Check if we have powder or bombs.
    ld   e, INV_SIZE
    ld   hl, $DB00
loop:
    ldi  a, [hl]
    cp   $02 ; bombs
    jr   z, hasProperItem
    cp   $0C ; powder
    jr   z, hasProperItem
    cp   $05 ; bow
    jr   z, hasProperItem
    dec  e
    jr   nz, loop
    ret
hasProperItem:
    
    ; Render ghost
    ld de, sprite
    call $3BC0

    call $64C6 ; check if game is busy (pops this stack frame if busy)

    ldh a, [$E7] ; frame counter
    swap a
    and  $01
    call $3B0C ; set entity sprite variant
    call $641A ; check collision
    ldh  a, [$F0] ;entity state
    rst 0
    dw  waitForTalk
    dw  talking

waitForTalk:
    call $645D ; check if talked to
    ret  nc
    ld   a, $C0
    call $2385 ; open dialog
    call $3B12 ; increase entity state
    ret

talking:
    ; Check if we are still talking
    ld   a, [$C19F]
    and  a
    ret  nz
    call $3B12 ; increase entity state
    ld   [hl], $00 ; set to state 0
    ld   a, [$C177] ; get which option we selected
    and  a
    ret  nz

    ; Give powder
    ld   a, [$DB4C]
    cp   $10
    jr   nc, doNotGivePowder
    ld   a, $10
    ld   [$DB4C], a
doNotGivePowder:

    ld   a, [$DB4D]
    cp   $10
    jr   nc, doNotGiveBombs
    ld   a, $10
    ld   [$DB4D], a
doNotGiveBombs:

    ld   a, [$DB45]
    cp   $10
    jr   nc, doNotGiveArrows
    ld   a, $10
    ld   [$DB45], a
doNotGiveArrows:

    ld   a, $C1
    call $2385 ; open dialog
    ret

sprite:
    db   $76, $09, $78, $09, $7A, $09, $7C, $09
""", 0x67F5), fill_nop=True)
    rom.patch(0x20, 0x0322 + 0x41 * 2, "734A", "564B")  # Remove the owl init handler

    re = RoomEditor(rom, 0x2A3)
    re.entities.append((7, 6, 0x41))
    re.store(rom)