示例#1
0
def setRomInfo(rom, seed, options):
    try:
        version = subprocess.run(['git', 'describe', '--tags', '--dirty=-D'],
                                 stdout=subprocess.PIPE).stdout.strip().decode(
                                     "ascii", "replace")
    except:
        version = ""

    if options.race:
        seed = "Race"
        if isinstance(options.race, str):
            seed += " " + options.race
        rom.patch(0x00, 0x07, "00", "01")
    else:
        rom.patch(0x00, 0x07, "00", "52")

    line_1_hex = _encode(seed[:16])
    line_2_hex = _encode(seed[16:])
    try:
        seednr = int(seed, 16)
    except:
        import hashlib
        seednr = int(
            hashlib.md5(seed.encode('ascii', 'replace')).hexdigest(), 16)

    for n in (3, 4):
        be = BackgroundEditor(rom, n)
        ba = BackgroundEditor(rom, n, attributes=True)
        for n, v in enumerate(_encode(version)):
            be.tiles[0x98a0 + 0x13 - len(version) + n] = v
            ba.tiles[0x98a0 + 0x13 - len(version) + n] = 0x00
        for n, v in enumerate(line_1_hex):
            be.tiles[0x9a01 + n] = v
            ba.tiles[0x9a01 + n] = 0x00
        for n, v in enumerate(line_2_hex):
            be.tiles[0x9a21 + n] = v
            ba.tiles[0x9a21 + n] = 0x00
        for n in range(0x09, 0x14):
            be.tiles[0x9820 + n] = 0x7F
            be.tiles[0x9840 + n] = 0xA0 + (n % 2)
            be.tiles[0x9860 + n] = 0xA2
        sn = seednr
        for n in range(0x0A, 0x14):
            tilenr = sn % 30
            sn //= 30
            if tilenr > 12:
                tilenr += 2
            if tilenr > 16:
                tilenr += 1
            if tilenr > 19:
                tilenr += 3
            if tilenr > 27:
                tilenr += 1
            if tilenr > 29:
                tilenr += 2
            if tilenr > 35:
                tilenr += 1
            be.tiles[0x9800 + n] = tilenr * 2
            be.tiles[0x9820 + n] = tilenr * 2 + 1
            pal = sn % 8
            sn //= 8
            ba.tiles[0x9800 + n] = 0x08 | pal
            ba.tiles[0x9820 + n] = 0x08 | pal
        be.store(rom)
        ba.store(rom)
示例#2
0
def singleSaveSlot(rom):
    # Do not validate/erase slots 2 and 3 at rom start
    rom.patch(0x01, 0x06B3, ASM("call $4794"), "", fill_nop=True)
    rom.patch(0x01, 0x06B9, ASM("call $4794"), "", fill_nop=True)

    # Patch the code that checks if files have proper filenames to skip file 2/3
    rom.patch(0x01, 0x1DD9, ASM("ld b, $02"), ASM("ret"), fill_nop=True)

    # Remove the part that writes death counters for save2/3 on the file select screen
    rom.patch(0x01, 0x0821, 0x084B, "", fill_nop=True)
    # Remove the call that updates the hearts for save2
    rom.patch(0x01, 0x0800, ASM("call $4DBE"), "", fill_nop=True)
    # Remove the call that updates the hearts for save3
    rom.patch(0x01, 0x0806, ASM("call $4DD6"), "", fill_nop=True)

    # Remove the call that updates the names for save2 and save3
    rom.patch(0x01, 0x0D70, ASM("call $4D94\ncall $4D9D"), "", fill_nop=True)

    # Remove the 2/3 slots from the screen and remove the copy text
    be = BackgroundEditor(rom, 0x03)
    del be.tiles[0x9924]
    del be.tiles[0x9984]
    be.store(rom)
    be = BackgroundEditor(rom, 0x04)
    del be.tiles[0x9924]
    del be.tiles[0x9984]
    for n in range(0x99ED, 0x99F1):
        del be.tiles[n]
    be.store(rom)

    # Do not do left/right for erase/copy selection.
    rom.patch(0x01, 0x092B, ASM("jr z, $0B"), ASM("jr $0B"))
    # Only switch between players
    rom.patch(0x01,
              0x08FA,
              0x091D,
              ASM("""
        ld  a, [$DBA7]
        and a
        ld  a, [$DBA6]
        jr  z, skip
        xor $03
skip:
    """),
              fill_nop=True)

    # On the erase screen, only switch between save 1 and return
    rom.patch(0x01,
              0x0E12,
              ASM("inc a\nand $03"),
              ASM("xor $03"),
              fill_nop=True)
    rom.patch(0x01,
              0x0E21,
              ASM("dec a\ncp $ff\njr nz, $02\nld a,$03"),
              ASM("xor $03"),
              fill_nop=True)

    be = BackgroundEditor(rom, 0x06)
    del be.tiles[0x9924]
    del be.tiles[0x9984]
    be.store(rom)
示例#3
0
def advancedInventorySubscreen(rom):
    # Instrument positions
    rom.patch(0x01, 0x2BCF, "0F51B1EFECAA4A0C", "090C0F12494C4F52")

    be = BackgroundEditor(rom, 2)
    be.tiles[0x9DA9] = 0x4A
    be.tiles[0x9DC9] = 0x4B
    for x in range(1, 10):
        be.tiles[0x9DE9 + x] = 0xB0 + (x % 9)
    be.tiles[0x9DE9] = 0xBA
    be.store(rom)
    be = BackgroundEditor(rom, 2, attributes=True)

    # Remove all attributes out of range.
    for y in range(0x9C00, 0x9E40, 0x20):
        for x in range(0x14, 0x20):
            del be.tiles[x + y]
    for n in range(0x9E40, 0xA020):
        del be.tiles[n]

    # Remove palette of instruments
    for y in range(0x9D00, 0x9E20, 0x20):
        for x in range(0x00, 0x14):
            be.tiles[x + y] = 0x01
    # And place it at the proper location
    for y in range(0x9D00, 0x9D80, 0x20):
        for x in range(0x09, 0x14):
            be.tiles[x + y] = 0x07

    # Key from 2nd vram bank
    be.tiles[0x9DA9] = 0x09
    be.tiles[0x9DC9] = 0x09
    # Nightmare heads from 2nd vram bank with proper palette
    for n in range(1, 10):
        be.tiles[0x9DA9 + n] = 0x0E

    be.store(rom)

    rom.patch(0x20, 0x19D3, ASM("ld bc, $5994\nld e, $33"),
              ASM("ld bc, $7E08\nld e, $%02x" % (0x33 + 24)))
    rom.banks[0x20][0x3E08:0x3E08 + 0x33] = rom.banks[0x20][0x1994:0x1994 +
                                                            0x33]
    rom.patch(0x20, 0x3E08 + 0x32, "00" * 25, "9DAA08464646464646464646"
              "9DCA08B0B0B0B0B0B0B0B0B0"
              "00")

    # instead of doing an GBC specific check, jump to our custom handling
    rom.patch(0x20,
              0x19DE,
              ASM("ldh a, [$FE]\nand a\njr z, $40"),
              ASM("call $7F00"),
              fill_nop=True)

    rom.patch(0x20,
              0x3F00,
              "00" * 0x100,
              ASM(
                  """
        ld   a, [$DBA5] ; isIndoor
        and  a
        jr   z, RenderKeysCounts
        ldh  a, [$F7]   ; mapNr
        cp   $FF
        jr   z, RenderDungeonFix
        cp   $06
        jr   z, D7RenderDungeonFix
        cp   $08
        jr   c, RenderDungeonFix 

RenderKeysCounts:
        ; Check if we have each nightmare key, and else null out the rendered tile
        ld   hl, $D636
        ld   de, $DB19
        ld   c, $08
NKeyLoop:
        ld   a, [de]
        and  a
        jr   nz, .hasNKey
        ld   a, $7F
        ld   [hl], a
.hasNKey:
        inc  hl
        inc  de
        inc  de
        inc  de
        inc  de
        inc  de
        dec  c
        jr   nz, NKeyLoop

        ld   a, [$DDDD]
        and  a
        jr   nz, .hasCNKey
        ld   a, $7F
        ld   [hl], a
.hasCNKey:

        ; Check the small key count for each dungeon and increase the tile to match the number
        ld   hl, $D642
        ld   de, $DB1A
        ld   c, $08
KeyLoop:
        ld   a, [de]
        add  a, $B0
        ld   [hl], a
        inc  hl
        inc  de
        inc  de
        inc  de
        inc  de
        inc  de
        dec  c
        jr   nz, KeyLoop

        ld   a, [$DDDE]
        add  a, $B0
        ld   [hl], a
        ret

D7RenderDungeonFix:
        ld   de, D7DungeonFix
        ld   c, $11
        jr   RenderDungeonFixGo   

RenderDungeonFix:
        ld   de, DungeonFix
        ld   c, $0D
RenderDungeonFixGo:
        ld   hl, $D633
.copyLoop:
        ld   a, [de]
        inc  de
        ldi  [hl], a
        dec  c
        jr   nz, .copyLoop
        ret
        
DungeonFix:
        db   $9D, $09, $C7, $7F
        db   $9D, $0A, $C7, $7F
        db   $9D, $13, $C3, $7F
        db   $00
D7DungeonFix:
        db   $9D, $09, $C7, $7F
        db   $9D, $0A, $C7, $7F
        db   $9D, $6B, $48, $7F
        db   $9D, $0F, $C7, $7F
        db   $00

    """, 0x7F00),
              fill_nop=True)
示例#4
0
文件: core.py 项目: daid/LADXR
def warpHome(rom):
    # Patch the S&Q menu to allow 3 options
    rom.patch(0x01,
              0x012A,
              0x0150,
              ASM("""
        ld   hl, $C13F
        call $6BA8 ; make sound on keypress
        ldh  a, [$CC] ; load joystick status
        and  $04      ; if up
        jr   z, noUp
        dec  [hl]
noUp:
        ldh  a, [$CC] ; load joystick status
        and  $08      ; if down
        jr   z, noDown
        inc  [hl]
noDown:

        ld   a, [hl]
        cp   $ff
        jr   nz, noWrapUp
        ld   a, $02
noWrapUp:
        cp   $03
        jr   nz, noWrapDown
        xor  a
noWrapDown:
        ld   [hl], a
        jp   $7E02
    """),
              fill_nop=True)
    rom.patch(0x01,
              0x3E02,
              0x3E20,
              ASM("""
        swap a
        add  a, $48
        ld   hl, $C018
        ldi  [hl], a
        ld   a, $24
        ldi  [hl], a
        ld   a, $BE
        ldi  [hl], a
        ld   [hl], $00
        ret
    """),
              fill_nop=True)

    rom.patch(0x01,
              0x00B7,
              ASM("""
        ld   a, [$C13F]
        cp   $01
        jr   z, $3B
    """),
              ASM("""
        ld   a, [$C13F]
        jp $7E20
    """),
              fill_nop=True)

    re = RoomEditor(rom, 0x2a3)
    warp = re.getWarps()[0]
    rom.patch(0x01,
              0x3E20,
              0x4000,
              ASM("""
        ; First, handle save & quit
        cp   $01
        jp   z, $40F9
        and  a
        jp   z, $40BE ; return to normal "return to game" handling

        ld   a, [$C509] ; Check if we have an item in the shop
        and  a
        jp   nz, $40BE ; return to normal "return to game" handling

        ld   a, $0B
        ld   [$DB95], a
        call $0C7D

        ; Replace warp0 tile data, and put link on that tile.
        xor  a
        ld   [$D401], a
        ld   [$D402], a
        ld   a, $%02x ; Room
        ld   [$D403], a
        ld   a, $%02x ; X
        ld   [$D404], a
        ld   a, $%02x ; Y
        ld   [$D405], a

        ldh  a, [$98]
        swap a
        and  $0F
        ld   e, a
        ldh  a, [$99]
        sub  $08
        and  $F0
        or   e
        ld   [$D416], a

        ld   a, $07
        ld   [$DB96], a
        ret
        jp   $40BE  ; return to normal "return to game" handling
    """ % (warp.room, warp.target_x, warp.target_y)),
              fill_nop=True)

    # Patch the S&Q screen to have 3 options.
    be = BackgroundEditor(rom, 0x0D)
    for n in range(2, 18):
        be.tiles[0x99C0 + n] = be.tiles[0x9980 + n]
        be.tiles[0x99A0 + n] = be.tiles[0x9960 + n]
        be.tiles[0x9980 + n] = be.tiles[0x9940 + n]
        be.tiles[0x9960 + n] = be.tiles[0x98e0 + n]
    be.tiles[0x9960 + 10] = 0xCE
    be.tiles[0x9960 + 11] = 0xCF
    be.tiles[0x9960 + 12] = 0xC4
    be.tiles[0x9960 + 13] = 0x7F
    be.tiles[0x9960 + 14] = 0x7F
    be.store(rom)

    sprite_data = [
        0b00000000,
        0b01000100,
        0b01000101,
        0b01000101,
        0b01111101,
        0b01000101,
        0b01000101,
        0b01000100,
        0b00000000,
        0b11100100,
        0b00010110,
        0b00010101,
        0b00010100,
        0b00010100,
        0b00010100,
        0b11100100,
    ]
    for n in range(32):
        rom.banks[0x0F][0x08E0 + n] = sprite_data[n // 2]