Compare commits
No commits in common. "master" and "v2.0" have entirely different histories.
32
.github/workflows/daily.yml
vendored
|
|
@ -1,32 +0,0 @@
|
|||
name: "MALCO's Daily Challenge"
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '53 15 * * *' # 9:53 AM, UTC-6
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
Build:
|
||||
runs-on: '${{ matrix.os }}'
|
||||
strategy:
|
||||
matrix:
|
||||
os:
|
||||
- ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: 'stable'
|
||||
- name: Install dependencies (Ubuntu)
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo add-apt-repository -y ppa:bartbes/love-stable
|
||||
sudo apt-get -q update
|
||||
sudo apt-get install -y xvfb love
|
||||
- name: Generate Daily
|
||||
env:
|
||||
WEBHOOK: ${{ secrets.WEBHOOK }}
|
||||
run: |
|
||||
cd $GITHUB_WORKSPACE
|
||||
sudo xvfb-run -a --server-args="-screen 0 1024x768x24" love src --daily
|
||||
cat daily.txt
|
||||
curl -H "Content-Type: application/json" -X POST -d @daily.txt "$WEBHOOK"
|
||||
137
.github/workflows/python.yml
vendored
|
|
@ -1,137 +0,0 @@
|
|||
name: Python Package
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- '*'
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
mypy-required:
|
||||
runs-on: 'ubuntu-latest'
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Workaround for worktree config
|
||||
run: git config --unset-all extensions.worktreeConfig || true
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.10"
|
||||
cache: "pip"
|
||||
|
||||
- name: Install Python packages
|
||||
run: |
|
||||
python -m pip install -e .
|
||||
python -m pip install mypy
|
||||
|
||||
- name: Mypy on required files
|
||||
uses: tsuyoshicho/action-mypy@v5
|
||||
with:
|
||||
github_token: ${{ secrets.github_token }}
|
||||
# Change reviewdog reporter if you need [github-pr-check,github-check,github-pr-review].
|
||||
reporter: github-check
|
||||
setup_method: nothing
|
||||
target: --config-file=pyproject.toml
|
||||
fail_on_error: true
|
||||
install_types: false
|
||||
|
||||
mypy-modified:
|
||||
runs-on: 'ubuntu-latest'
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Workaround for worktree config
|
||||
run: git config --unset-all extensions.worktreeConfig || true
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.10"
|
||||
cache: "pip"
|
||||
|
||||
- name: Install Python packages
|
||||
run: |
|
||||
python -m pip install -e .
|
||||
python -m pip install mypy
|
||||
|
||||
- name: Mypy on modified files
|
||||
uses: tsuyoshicho/action-mypy@v5
|
||||
with:
|
||||
github_token: ${{ secrets.github_token }}
|
||||
# Change reviewdog reporter if you need [github-pr-check,github-check,github-pr-review].
|
||||
reporter: github-check
|
||||
setup_method: nothing
|
||||
level: warning
|
||||
fail_on_error: false
|
||||
install_types: false
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
name: Wheel
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: 'recursive'
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "3.10"
|
||||
|
||||
- name: Install Python packages
|
||||
run: python -m pip install --upgrade build pip
|
||||
|
||||
- name: build wheel
|
||||
run: python -m build --wheel
|
||||
|
||||
- name: build sdist
|
||||
run: python -m build --sdist
|
||||
|
||||
- name: Store the packages
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: python-package-distributions
|
||||
path: dist
|
||||
|
||||
pypi:
|
||||
runs-on: 'ubuntu-latest'
|
||||
needs:
|
||||
- mypy-required
|
||||
- build
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
|
||||
steps:
|
||||
- name: Download all the dists
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: python-package-distributions
|
||||
path: dist/
|
||||
|
||||
- name: Publish 📦 to TestPyPI
|
||||
if: ${{ github.ref == 'refs/heads/patcher' }}
|
||||
uses: pypa/gh-action-pypi-publish@master
|
||||
with:
|
||||
password: ${{ secrets.testpypi_password }}
|
||||
repository_url: https://test.pypi.org/legacy/
|
||||
|
||||
- name: Publish 📦 to PyPI
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
uses: pypa/gh-action-pypi-publish@master
|
||||
with:
|
||||
password: ${{ secrets.pypi_password }}
|
||||
33
.github/workflows/workflow-validate.yml
vendored
|
|
@ -1,33 +0,0 @@
|
|||
name: Check Workflow Files
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
merge_group:
|
||||
pull_request:
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
actions:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Install action-validator with asdf
|
||||
uses: asdf-vm/actions/install@v3
|
||||
with:
|
||||
tool_versions: |
|
||||
action-validator 0.5.1
|
||||
|
||||
- name: Lint Actions
|
||||
run: |
|
||||
find .github/workflows -type f \( -iname \*.yaml -o -iname \*.yml \) \
|
||||
| xargs -I {} action-validator --verbose {}
|
||||
25
.gitignore
vendored
|
|
@ -1,22 +1,11 @@
|
|||
data/*
|
||||
notes/*
|
||||
|
||||
pre-edited-cs/Doukutsu\.exe\.blbkp
|
||||
|
||||
pre-edited-cs/Profile\.dat
|
||||
|
||||
pre-edited-cs/window\.rect
|
||||
|
||||
pre-edited-cs/Profile\.dat\.bkp
|
||||
*Copy/
|
||||
|
||||
venv/
|
||||
|
||||
build/
|
||||
|
||||
dist/
|
||||
|
||||
cave_story_randomizer.egg-info/
|
||||
|
||||
**/__pycache__
|
||||
|
||||
pre_edited_cs/**/Doukutsu\.exe\.blbkp
|
||||
pre_edited_cs/**/Profile*
|
||||
pre_edited_cs/**/window\.rect
|
||||
|
||||
pre_edited_cs/data/version.txt
|
||||
|
||||
pre_edited_cs/freeware/Doukutsu_backup.exe
|
||||
|
|
|
|||
23
.gitlab-ci.yml
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# image: shru/arch-love-release:heavy
|
||||
image: asmfreak/love-release:latest
|
||||
|
||||
variables:
|
||||
ITCHIO_USER: shru
|
||||
ITCHIO_GAME: cave-story-randomizer
|
||||
CHANNEL: $CI_COMMIT_REF_NAME
|
||||
|
||||
stages:
|
||||
- build-release
|
||||
|
||||
build-and-release:
|
||||
stage: build-release
|
||||
when: manual
|
||||
script:
|
||||
# I - Build
|
||||
- cd src
|
||||
- love-release -W
|
||||
# II - Release to itch.io
|
||||
- cd releases
|
||||
- FILE=$(ls *-win32.zip) ;
|
||||
zip -d "$FILE" "*/lovec.exe" "*/changes.txt" "*/readme.txt" "*.ico" ;
|
||||
butler push "$FILE" "$ITCHIO_USER/$ITCHIO_GAME:win32-$CHANNEL"
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
# See https://pre-commit.com for more information
|
||||
# See https://pre-commit.com/hooks.html for more hooks
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: v0.8.3
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: [ --fix, --exit-non-zero-on-fix ]
|
||||
- id: ruff-format
|
||||
|
||||
- repo: https://github.com/henriquegemignani/jsonschema-to-typeddict
|
||||
rev: v1.1.1
|
||||
hooks:
|
||||
- id: jsonschema-to-typeddict
|
||||
files: caver/schema/schema.json
|
||||
args: [ --output-path, caver/schema/types.py, --root-name, CaverData ]
|
||||
48
.travis.yml
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
language: python
|
||||
os: linux
|
||||
dist: xenial
|
||||
addons:
|
||||
apt:
|
||||
update: true
|
||||
packages:
|
||||
- libzip-dev
|
||||
- xvfb
|
||||
services:
|
||||
- xvfb
|
||||
before_install:
|
||||
- |
|
||||
pip install hererocks
|
||||
hererocks env --luarocks 3.0 --lua latest
|
||||
export 'PATH='"$TRAVIS_BUILD_DIR"'/env/bin'":$PATH"
|
||||
install:
|
||||
- |
|
||||
sudo add-apt-repository -y ppa:bartbes/love-stable
|
||||
sudo apt-get -q update
|
||||
sudo apt-get -y install love
|
||||
luarocks install --server="http://luarocks.org/dev" lua-zip
|
||||
luarocks install love-release
|
||||
script:
|
||||
- bash daily.sh
|
||||
env:
|
||||
global:
|
||||
- secure: DU2Mq4FPbOidv0Go4b+2r5Vy7v0bbQo40ZZPkiwm/6nAJYkwySwVn2DyZGwh/kV4o6ZG0IgtLxPvHiF8lVZptbtkHJTt/GeokwwvsfpHJntPC9jyvXklFkkln9h2AgWrhTmFf+EYE4Mlm7FAjsr/9ZZHCuGn7wDCOBk3g4Zy7eAyKGqpYMN3296eUiZPXWtOAexmbavFI07pmu4ZyJ8K6HMmjd8YSAQpui3zJn/hMTupQm+o5s/ehZ72QnUyjRWdKvLlJCzORrajJxgYXQqLdjXVMcq4kuR4pDRnLdW9XBlAWiHOvj7wlVOUyBq2ZyhkTTNEYiQp+9UsIua1gG0hdLiOGH2ODtrb6NvQIRUfs5jE6xHmw3hQCfIe9itT+SbVQmuuTovM/MQTS/vH7k+AHtnJCGykMjAD6evNi1EkOG5oxrL7xEGPz7lzyVISoz0O4YmMWGF0qIzb68R11+Eo1URFrEUDxZc7F2kMoeAbnTxfiGABrMXrgIN7ReJhfD1z4ik6KwKBFw9AwJfldyb5w0QgqFAkkihqKGp5VbTMR6LeSN0Tq/Ic3QRvLHYt43+eoRXS4d2lvSo/0Nf7FftQPurbLI6c/r9nckwOZmjFicwYJ0Ulrbd46og74FUQZFSMcrVsiXo1PG2yTwu9bUvTBUHWdWh0o2xPpfAHbA05++c=
|
||||
before_deploy:
|
||||
- |
|
||||
cd src; love-release -M; cd -
|
||||
mv pre-edited-cs "src/releases/Cave Story"
|
||||
cd src/releases
|
||||
zip -9 -qur CaveStoryRandomizer-macos.zip "Cave Story"
|
||||
zip -9 -qr CaveStoryRandomizer-linux.zip "Cave Story" CaveStoryRandomizer.love
|
||||
cd -
|
||||
# don't forget to create the windows releases!
|
||||
deploy:
|
||||
provider: releases
|
||||
token:
|
||||
secure: bMinTly2BOZCNQw625Fz744hvVQlnwZiC6pQZZx1f5evs0gi4TXbqqft5UN3orGgRiNnVnbf2qYC7PnS1LzynHUimdVk8iqfRKz4ADuWXyf9/i1gojzzSAI87lxbGaHxzqjZLtzf1zRonPlY1oj9X3a1eAle6EEAn/Utnm/jqZPhTYm8cMowLWqcVTcDOw1lhBpgsVYdej1wCaq7r2KBDvrqWZCdt8pJ2lcaShJEqmBONDvu9KO+gbNXwmhBAz4bG0DTVFhO459ZNjfNz749eiU7KhbxvFgz7O+j8HEdhlXznYgmzveUmVmhOSe3z037YwCNv+2ar0FITGkmTpgog0z2XuxDMb28Eakoc0uzaowwB68JRfEeRpBGidhSGraZ5DnHOS3QdDaEQ4jImv97DagiVoqcKm3JDGhGuvbI4dfPsXHKMncJC8cqf86NwSg63boabcoUTwzVLZdd4tbiOBqYPBgEtEz4uFgKvkrrzE0DoP1Efi1aZqcnOW6xckHbC261rxB5QG8WGcb1tDnmQgbhbEEguPHuzKBWP6ktpjpFdeS3Wbqb0UMaXQXMCcaMpJfCLNsLxQ6iHOh+XQhJREDPTuXm4F1m0BzSjBvQpWQ4tpO+kF1KiJ4wiwzn9jTfJxhgMgxEoY75dtH+E0K2jXLRezychR22V+7R9ifNLns=
|
||||
file:
|
||||
- src/releases/*.zip
|
||||
file_glob: true
|
||||
draft: true
|
||||
skip_cleanup: true
|
||||
on:
|
||||
tags: true
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"setup": {
|
||||
"looseChecking": {
|
||||
"events": true,
|
||||
"arguments": true
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
CaveStoryRandomizer.ico
Normal file
|
After Width: | Height: | Size: 182 KiB |
51
README.md
|
|
@ -1,3 +1,52 @@
|
|||
# Cave Story Randomizer [Open Mode]
|
||||
|
||||
A patcher for randomizing Cave Story. If you want to play, check out [Randovania](https://github.com/randovania/randovania)!
|
||||
The Cave Story Randomizer shuffles the location of every item in Cave Story, creating a new experience each time you play! The randomizer has logic in place to ensure that you can always reach every item and finish the game. Get started by heading to the [releases page](https://github.com/cave-story-randomizer/cave-story-randomizer/releases) and downloading the most recent version! If you find yourself stuck, wanting to talk about the hilarious location you found the panties in, or just plain enjoying the game please consider joining our [official Discord server](https://discord.gg/7zUdPEn) and hanging out!
|
||||
|
||||
## Main differences
|
||||
Note that there are a few key differences from the vanilla game in order to improve the playing experience:
|
||||
|
||||
- All 5 teleporter locations in Arthur's House are active from the beginning of the game
|
||||
- All other teleporters from the vanilla game are active and linked to one another at all times
|
||||
- A teleporter between Sand Zone (near the Storehouse) and Labyrinth I has been placed and can be activated in one of two ways:
|
||||
1. Defeating Toroko+
|
||||
2. Using the teleporter from the Labyrinth I side
|
||||
- Most cutscenes have been abridged or skipped entirely
|
||||
- Jellyfish Juice can be used an infinite number of times
|
||||
- You can carry as many as 5 puppies at once: Jenka will only accept them once you've collected all 5
|
||||
- By the way, all 5 puppies will be located somewhere in the Sand Zone
|
||||
- Certain items that are received from NPCs have been placed in chests:
|
||||
- Labyrinth B (Fallen Booster)
|
||||
- Labyrinth Shop
|
||||
- One requiring the Machine Gun to open
|
||||
- One requiring the Fireball to open
|
||||
- One requiring the Spur to open
|
||||
- Jail no. 1
|
||||
- Storage? (Ma Pignon)
|
||||
- This chest requires saving Curly in the Waterway to open
|
||||
- If you don't have Curly's Air Tank after defeating the Core, the water will not rise and you may leave without dying
|
||||
- Curly cannot be left behind permanently in the Core; the shutter will never close once the boss has been defeated
|
||||
- The jump in the Waterway to save Curly has been made much easier
|
||||
- Ironhead will always give you his item on defeat (but there's still a special surprise if you defeat him without taking damage!)
|
||||
- Kazuma will only open the door between Egg no. 0 and the Outer Wall if you save him in Grasstown
|
||||
- Kazuma's door can be blown down from both the outside and the inside
|
||||
- Entering the Throne Room to complete the game requires doing three things:
|
||||
1. Saving Sue in the Egg Corridor
|
||||
2. Obtaining the Booster 2.0
|
||||
3. Obtaining the Iron Bond
|
||||
|
||||
## Help me!
|
||||
If you find yourself stuck, here are a few common pitfalls:
|
||||
- Remember that the Jellyfish Juice can quench more than one fireplace
|
||||
- The Graveyard can only be accessed if you obtain the Silver Locket and see Toroko get kidnapped
|
||||
- The Hermit Gunsmith will wake up and give you an item if you defeat the Core and show him his gun
|
||||
- The western side of the Labyrinth can be accessed without flight if you defeat Toroko+
|
||||
- The Plantation can be accessed without the Teleporter Room Key if you save Kazuma and teleport in or climb the Outer Wall
|
||||
- The Waterway can be accessed without the Cure-All by using the teleporter in the Labyrinth Shop
|
||||
- There may be a required item in the Last Cave (Hidden) as a reward for defeating the Red Demon
|
||||
|
||||
If you're still stuck, join our [official Discord server](https://discord.gg/7zUdPEn) and ask for help in there!
|
||||
|
||||
## Credits
|
||||
- Original Cave Story Randomizer by shru: https://shru.itch.io/cave-story-randomizer
|
||||
- Font: https://datagoblin.itch.io/monogram
|
||||
- Icon: Bubbler (@Ethan#6397)
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
import os
|
||||
|
||||
|
||||
# Functions
|
||||
# =========
|
||||
#
|
||||
# .. _get_hook_dirs:
|
||||
#
|
||||
# get_hook_dirs
|
||||
# -------------
|
||||
#
|
||||
# Tell PyInstaller where to find hooks provided by this distribution;
|
||||
# this is referenced by the :ref:`hook registration <hook_registration>`.
|
||||
# This function returns a list containing only the path to this
|
||||
# directory, which is the location of these hooks.
|
||||
|
||||
def get_hook_dirs():
|
||||
return [os.path.dirname(__file__)]
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
from PyInstaller.utils.hooks import collect_data_files
|
||||
|
||||
# https://pyinstaller.readthedocs.io/en/stable/hooks.html#provide-hooks-with-package
|
||||
|
||||
datas = collect_data_files('caver', excludes=['__pyinstaller'])
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
from PyInstaller.utils.hooks import collect_data_files
|
||||
|
||||
# https://pyinstaller.readthedocs.io/en/stable/hooks.html#provide-hooks-with-package
|
||||
|
||||
datas = collect_data_files('pre_edited_cs', excludes=['__pyinstaller'])
|
||||
218
caver/patcher.py
|
|
@ -1,218 +0,0 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import logging
|
||||
import platform as pl
|
||||
import shutil
|
||||
import sys
|
||||
import textwrap
|
||||
import typing
|
||||
from enum import Enum
|
||||
from pathlib import Path
|
||||
from uuid import UUID
|
||||
|
||||
import pre_edited_cs
|
||||
from randovania_lupa import LuaRuntime # type: ignore
|
||||
|
||||
from caver.schema.validator_with_default import DefaultValidatingDraft7Validator
|
||||
|
||||
LuaFile = typing.Any
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from collections.abc import Callable
|
||||
|
||||
from caver.schema import (
|
||||
CaverData,
|
||||
CaverdataMaps,
|
||||
CaverdataOtherTsc,
|
||||
EventNumber,
|
||||
MapName,
|
||||
)
|
||||
|
||||
|
||||
class CaverException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class CSPlatform(Enum):
|
||||
FREEWARE = "freeware"
|
||||
TWEAKED = "tweaked"
|
||||
|
||||
|
||||
def get_path() -> Path:
|
||||
if getattr(sys, "frozen", False):
|
||||
file_dir = Path(getattr(sys, "_MEIPASS"))
|
||||
else:
|
||||
file_dir = Path(__file__).parent.parent
|
||||
return file_dir.joinpath("caver")
|
||||
|
||||
|
||||
def validate(patch_data: dict) -> None:
|
||||
with Path(__file__).parent.joinpath("schema/schema.json").open() as f:
|
||||
schema = json.load(f)
|
||||
DefaultValidatingDraft7Validator(schema).validate(patch_data)
|
||||
|
||||
|
||||
def patch_files(
|
||||
patch_data: CaverData, output_dir: Path, platform: CSPlatform, progress_update: Callable[[str, float], None]
|
||||
) -> None:
|
||||
progress_update("Validating schema...", -1)
|
||||
validate(typing.cast(dict, patch_data))
|
||||
|
||||
progress_update("Copying base files...", -1)
|
||||
ensure_base_files_exist(platform, output_dir)
|
||||
|
||||
total = len(patch_data["maps"].keys()) + len(patch_data["other_tsc"].keys()) + 3
|
||||
|
||||
lua_file = get_path().joinpath("tsc_file.lua").read_text()
|
||||
TscFile = typing.cast(LuaFile, LuaRuntime().execute(lua_file))
|
||||
|
||||
for i, (mapname, mapdata) in enumerate(patch_data["maps"].items()):
|
||||
progress_update(f"Patching {mapname}...", i / total)
|
||||
patch_map(mapname, mapdata, TscFile, output_dir)
|
||||
|
||||
for filename, scripts in patch_data["other_tsc"].items():
|
||||
i += 1
|
||||
progress_update(f"Patching {filename}.tsc...", i / total)
|
||||
patch_other(filename, scripts, TscFile, output_dir)
|
||||
|
||||
i += 1
|
||||
progress_update("Copying MyChar...", i / total)
|
||||
patch_mychar(patch_data["mychar"], output_dir, platform is CSPlatform.TWEAKED)
|
||||
|
||||
i += 1
|
||||
progress_update("Copying hash...", i / total)
|
||||
patch_hash(patch_data["hash"], output_dir)
|
||||
|
||||
i += 1
|
||||
progress_update("Copying UUID...", i / total)
|
||||
patch_uuid(patch_data["uuid"], output_dir)
|
||||
|
||||
if platform == CSPlatform.TWEAKED:
|
||||
if pl.system() == "Linux":
|
||||
output_dir.joinpath("CSTweaked.exe").unlink()
|
||||
else:
|
||||
output_dir.joinpath("CSTweaked").unlink()
|
||||
|
||||
|
||||
def ensure_base_files_exist(platform: CSPlatform, output_dir: Path) -> None:
|
||||
internal_copy = pre_edited_cs.get_path()
|
||||
|
||||
with internal_copy.joinpath("data", "version.txt").open() as version_file:
|
||||
latest_version = version_file.readline()
|
||||
|
||||
version = output_dir.joinpath("data", "version.txt")
|
||||
current_version = "v0.0.0.0"
|
||||
if version.exists():
|
||||
with version.open() as version_file:
|
||||
current_version = version_file.readline()
|
||||
|
||||
keep_existing_files = current_version >= latest_version
|
||||
|
||||
def should_ignore(path: str, names: list[str]) -> list[str]:
|
||||
base = ["__init__.py", "__pycache__", "ScriptSource", "__pyinstaller"]
|
||||
if keep_existing_files:
|
||||
p = Path(path)
|
||||
base.extend(
|
||||
[str(p.joinpath(name)) for name in names if p.joinpath(name).exists() and p.joinpath(name).is_file()]
|
||||
)
|
||||
return base
|
||||
|
||||
try:
|
||||
shutil.copytree(internal_copy.joinpath(platform.value), output_dir, ignore=should_ignore, dirs_exist_ok=True)
|
||||
shutil.copytree(
|
||||
internal_copy.joinpath("data"), output_dir.joinpath("data"), ignore=should_ignore, dirs_exist_ok=True
|
||||
)
|
||||
except shutil.Error:
|
||||
raise CaverException(
|
||||
"Error copying base files. Ensure the directory is not read-only, and that Doukutsu.exe is closed"
|
||||
)
|
||||
output_dir.joinpath("data", "Plaintext").mkdir(exist_ok=True)
|
||||
|
||||
|
||||
def patch_map(mapname: MapName, mapdata: CaverdataMaps, TscFile: LuaFile, output_dir: Path) -> None:
|
||||
mappath = output_dir.joinpath("data", "Stage", f"{mapname}.tsc")
|
||||
tsc_file = TscFile.new(TscFile, mappath.read_bytes(), logging.getLogger("caver"))
|
||||
|
||||
for event, script in mapdata["pickups"].items():
|
||||
TscFile.placeScriptAtEvent(tsc_file, script, event, mapname)
|
||||
|
||||
for event, song in mapdata["music"].items():
|
||||
TscFile.placeSongAtCue(tsc_file, song["song_id"], event, song["original_id"], mapname)
|
||||
|
||||
for event, script in mapdata["entrances"].items():
|
||||
needle = "<EVE...." # TODO: create a proper pattern
|
||||
TscFile.placeScriptAtEvent(tsc_file, script, event, mapname, needle)
|
||||
|
||||
for event, hint in mapdata["hints"].items():
|
||||
script = create_hint_script(hint["text"], hint.get("facepic", "0000") != "0000", hint.get("ending", "<END"))
|
||||
TscFile.placeScriptAtEvent(tsc_file, script, event, mapname)
|
||||
|
||||
chars = TscFile.getText(tsc_file).values()
|
||||
mappath.write_bytes(bytes(chars))
|
||||
output_dir.joinpath("data", "Plaintext", f"{mapname}.txt").write_text(TscFile.getPlaintext(tsc_file))
|
||||
|
||||
|
||||
def patch_other(
|
||||
filename: MapName, scripts: dict[EventNumber, CaverdataOtherTsc], TscFile: LuaFile, output_dir: Path
|
||||
) -> None:
|
||||
filepath = output_dir.joinpath("data", f"{filename}.tsc")
|
||||
tsc_file = TscFile.new(TscFile, filepath.read_bytes(), logging.getLogger("caver"))
|
||||
|
||||
for event, script in scripts.items():
|
||||
TscFile.placeScriptAtEvent(tsc_file, script["script"], event, filename, script.get("needle", "<EVE...."))
|
||||
|
||||
chars = TscFile.getText(tsc_file).values()
|
||||
filepath.write_bytes(bytes(chars))
|
||||
output_dir.joinpath("data", "Plaintext", f"{filename}.txt").write_text(TscFile.getPlaintext(tsc_file))
|
||||
|
||||
|
||||
def patch_mychar(mychar: str | None, output_dir: Path, add_upscale: bool) -> None:
|
||||
if mychar is None:
|
||||
return
|
||||
mychar_img = Path(mychar).read_bytes()
|
||||
output_dir.joinpath("data", "MyChar.bmp").write_bytes(mychar_img)
|
||||
|
||||
if add_upscale:
|
||||
mychar_name = Path(mychar).name
|
||||
mychar_up_img = Path(mychar).parent.joinpath("2x", mychar_name).read_bytes()
|
||||
output_dir.joinpath("data", "sprites_up", "MyChar.bmp").write_bytes(mychar_up_img)
|
||||
|
||||
|
||||
def patch_hash(hash: list[int], output_dir: Path) -> None:
|
||||
hash_strings = [f"{num:04d}" for num in hash]
|
||||
hash_string = ",".join(hash_strings)
|
||||
output_dir.joinpath("data", "hash.txt").write_text(hash_string)
|
||||
|
||||
|
||||
def patch_uuid(uuid: str, output_dir: Path) -> None:
|
||||
uuid = f"{{{UUID(uuid)}}}"
|
||||
output_dir.joinpath("data", "uuid.txt").write_text(uuid)
|
||||
|
||||
|
||||
def wrap_msg_text(text: str, facepic: bool, *, ending: str = "<NOD", max_text_boxes: int | None = 1) -> str:
|
||||
hard_limit = 35
|
||||
msgbox_limit = 26 if facepic else hard_limit
|
||||
|
||||
max_lines = max_text_boxes * 3 if max_text_boxes is not None else None
|
||||
lines = textwrap.wrap(text, width=msgbox_limit, max_lines=max_lines)
|
||||
|
||||
text = ""
|
||||
for i, line in enumerate(lines):
|
||||
text += line
|
||||
if i < len(lines) - 1:
|
||||
if i % 3 == 2:
|
||||
text += "<NOD"
|
||||
if len(line) != hard_limit:
|
||||
text += "\r\n"
|
||||
text += ending
|
||||
|
||||
return text
|
||||
|
||||
|
||||
def create_hint_script(text: str, facepic: bool, ending: str) -> str:
|
||||
"""
|
||||
A desperate attempt to generate valid <MSG text.
|
||||
Fills one text box (up to three lines). Attempts to wrap words elegantly.
|
||||
"""
|
||||
return f"<PRI<MSG<TUR{wrap_msg_text(text, facepic, ending=ending)}"
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
from caver.schema.types import (
|
||||
CaverData,
|
||||
CaverdataMaps,
|
||||
CaverdataMapsHints,
|
||||
CaverdataMapsMusic,
|
||||
CaverdataOtherTsc,
|
||||
EventNumber,
|
||||
MapName,
|
||||
TscScript,
|
||||
TscValue,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"CaverData",
|
||||
"TscValue",
|
||||
"EventNumber",
|
||||
"MapName",
|
||||
"TscScript",
|
||||
"CaverdataMapsHints",
|
||||
"CaverdataMapsMusic",
|
||||
"CaverdataMaps",
|
||||
"CaverdataOtherTsc",
|
||||
]
|
||||
|
|
@ -1,195 +0,0 @@
|
|||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"$schema": {
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
},
|
||||
"maps": {
|
||||
"type": "object",
|
||||
"propertyNames": {
|
||||
"$ref": "#/$defs/map_name"
|
||||
},
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pickups": {
|
||||
"type": "object",
|
||||
"propertyNames": {
|
||||
"$ref": "#/$defs/event_number"
|
||||
},
|
||||
"additionalProperties": {
|
||||
"$ref": "#/$defs/tsc_script"
|
||||
},
|
||||
"default": {}
|
||||
},
|
||||
"hints": {
|
||||
"type": "object",
|
||||
"propertyNames": {
|
||||
"$ref": "#/$defs/event_number"
|
||||
},
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"text": {
|
||||
"type": "string"
|
||||
},
|
||||
"facepic": {
|
||||
"$ref": "#/$defs/tsc_value",
|
||||
"default": "0000"
|
||||
},
|
||||
"ending": {
|
||||
"$ref": "#/$defs/tsc_script",
|
||||
"default": "<END"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"text",
|
||||
"facepic",
|
||||
"ending"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"default": {}
|
||||
},
|
||||
"music": {
|
||||
"type": "object",
|
||||
"propertyNames": {
|
||||
"$ref": "#/$defs/event_number"
|
||||
},
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"original_id": {
|
||||
"$ref": "#/$defs/tsc_value"
|
||||
},
|
||||
"song_id": {
|
||||
"$ref": "#/$defs/tsc_value"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"original_id",
|
||||
"song_id"
|
||||
],
|
||||
"additionalProperties": false
|
||||
},
|
||||
"default": {}
|
||||
},
|
||||
"entrances": {
|
||||
"type": "object",
|
||||
"propertyNames": {
|
||||
"$ref": "#/$defs/event_number"
|
||||
},
|
||||
"additionalProperties": {
|
||||
"$ref": "#/$defs/tsc_script"
|
||||
},
|
||||
"default": {}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"pickups",
|
||||
"hints",
|
||||
"music",
|
||||
"entrances"
|
||||
]
|
||||
},
|
||||
"default": {}
|
||||
},
|
||||
"other_tsc": {
|
||||
"type": "object",
|
||||
"propertyNames": {
|
||||
"$ref": "#/$defs/map_name"
|
||||
},
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"propertyNames": {
|
||||
"$ref": "#/$defs/event_number"
|
||||
},
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"needle": {
|
||||
"type": "string",
|
||||
"description": "Lua pattern to search for and replace within the event"
|
||||
},
|
||||
"script": {
|
||||
"$ref": "#/$defs/tsc_script"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"needle",
|
||||
"script"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"default": {}
|
||||
},
|
||||
"mychar": {
|
||||
"description": "A path to the mychar.bmp file to use (Optional)",
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "null"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^.*\\.bmp$"
|
||||
}
|
||||
],
|
||||
"default": null
|
||||
},
|
||||
"hash": {
|
||||
"description": "An array of five item IDs to display on the title screen, within [1, 39]",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"maximum": 39
|
||||
},
|
||||
"minItems": 5,
|
||||
"maxItems": 5,
|
||||
"default": [1,1,1,1,1]
|
||||
},
|
||||
"uuid": {
|
||||
"description": "The UUID for the world in a multiworld session, or the empty UUID if single player.",
|
||||
"type": "string",
|
||||
"pattern": "^\\{[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}\\}$",
|
||||
"default": "{00000000-0000-0000-0000-000000000000}"
|
||||
},
|
||||
"platform": {
|
||||
"description": "Which supported platform to export to.",
|
||||
"$comment": "Not actually used by the patcher.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"freeware",
|
||||
"tweaked"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"maps",
|
||||
"other_tsc",
|
||||
"mychar",
|
||||
"hash",
|
||||
"uuid"
|
||||
],
|
||||
"additionalProperties": false,
|
||||
"$defs": {
|
||||
"tsc_value": {
|
||||
"type": "string",
|
||||
"pattern": "^[ -~]{4}$"
|
||||
},
|
||||
"event_number": {
|
||||
"$ref": "#/$defs/tsc_value",
|
||||
"$comment": "Semantic alias for tsc_value"
|
||||
},
|
||||
"map_name": {
|
||||
"type": "string"
|
||||
},
|
||||
"tsc_script": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
# This file is generated. Manual changes will be lost
|
||||
# fmt: off
|
||||
# ruff: noqa
|
||||
from __future__ import annotations
|
||||
|
||||
import typing_extensions as typ
|
||||
|
||||
|
||||
# Definitions
|
||||
TscValue: typ.TypeAlias = str
|
||||
EventNumber: typ.TypeAlias = TscValue
|
||||
MapName: typ.TypeAlias = str
|
||||
TscScript: typ.TypeAlias = str
|
||||
|
||||
|
||||
# Schema entries
|
||||
@typ.final
|
||||
class CaverdataMapsHints(typ.TypedDict):
|
||||
text: str
|
||||
facepic: TscValue
|
||||
ending: TscScript
|
||||
|
||||
|
||||
@typ.final
|
||||
class CaverdataMapsMusic(typ.TypedDict):
|
||||
original_id: TscValue
|
||||
song_id: TscValue
|
||||
|
||||
|
||||
@typ.final
|
||||
class CaverdataMaps(typ.TypedDict):
|
||||
pickups: dict[EventNumber, TscScript]
|
||||
hints: dict[EventNumber, CaverdataMapsHints]
|
||||
music: dict[EventNumber, CaverdataMapsMusic]
|
||||
entrances: dict[EventNumber, TscScript]
|
||||
|
||||
|
||||
@typ.final
|
||||
class CaverdataOtherTsc(typ.TypedDict):
|
||||
needle: str
|
||||
script: TscScript
|
||||
|
||||
|
||||
|
||||
@typ.final
|
||||
class Caverdata(typ.TypedDict):
|
||||
maps: dict[MapName, CaverdataMaps]
|
||||
other_tsc: dict[MapName, dict[EventNumber, CaverdataOtherTsc]]
|
||||
mychar: None | str
|
||||
hash: list[int]
|
||||
uuid: str
|
||||
platform: typ.NotRequired[str]
|
||||
|
||||
CaverData: typ.TypeAlias = Caverdata
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
from jsonschema import Draft7Validator, validators
|
||||
|
||||
|
||||
def extend_with_default(validator_class):
|
||||
validate_properties = validator_class.VALIDATORS["properties"]
|
||||
|
||||
def set_defaults(validator, properties, instance, schema):
|
||||
for property, subschema in properties.items():
|
||||
if "default" in subschema:
|
||||
instance.setdefault(property, subschema["default"])
|
||||
|
||||
yield from validate_properties(
|
||||
validator,
|
||||
properties,
|
||||
instance,
|
||||
schema,
|
||||
)
|
||||
|
||||
return validators.extend(
|
||||
validator_class,
|
||||
{"properties": set_defaults},
|
||||
)
|
||||
|
||||
|
||||
DefaultValidatingDraft7Validator = extend_with_default(Draft7Validator)
|
||||
|
|
@ -1,281 +0,0 @@
|
|||
offset 414bf0
|
||||
|
||||
#define
|
||||
rectMax=0D
|
||||
rectMaxx10=0D0
|
||||
|
||||
rcLeft.left=EBP-0D0
|
||||
rcLeft.top=EBP-0CC
|
||||
rcLeft.right=EBP-0C8
|
||||
rcLeft.bottom=EBP-0C4
|
||||
|
||||
rcRight.left=EBP-1A0
|
||||
rcRight.top=EBP-19C
|
||||
rcRight.right=EBP-198
|
||||
rcRight.bottom=EBP-194
|
||||
|
||||
gMC.rect.left=49E69C
|
||||
gMC.rect.top=49E6A0
|
||||
gMC.rect.right=49E6A4
|
||||
gMC.rect.bottom=49E6A8
|
||||
|
||||
gMC.cond=49E638
|
||||
gMC.flag=49E63C
|
||||
gMC.ani_no=49E678
|
||||
gMC.ani_wait=49E674
|
||||
gMC.up=49E644
|
||||
gMC.down=49E648
|
||||
gMC.ym=49E670
|
||||
gMC.direct=49E640
|
||||
gMC.air=49E6DC
|
||||
|
||||
gKey_addr=49E210
|
||||
gKeyUp=493634
|
||||
gKeyLeft=493630
|
||||
gKeyRight=493638
|
||||
bKey=EBP+8
|
||||
|
||||
PlaySoundObject=00420640
|
||||
#enddefine
|
||||
|
||||
PUSH EBP
|
||||
MOV EBP,ESP
|
||||
SUB ESP,1A0 ; or whatever
|
||||
|
||||
PUSH ESI
|
||||
PUSH EDI
|
||||
XOR ESI,ESI
|
||||
|
||||
; FRAMERECTS
|
||||
|
||||
; Push left framerects onto stack for ease of looping
|
||||
PUSH 0D0 ; DROWNING SPRITES
|
||||
|
||||
PUSH 70
|
||||
PUSH 60
|
||||
PUSH 30
|
||||
PUSH 50
|
||||
PUSH 30
|
||||
PUSH 40
|
||||
PUSH 30
|
||||
PUSH 0
|
||||
PUSH 20
|
||||
PUSH 0
|
||||
PUSH 10
|
||||
PUSH 0
|
||||
|
||||
MOV EAX, 0
|
||||
MOV ECX, 10
|
||||
MOV EDX, 20
|
||||
JMP :loopbody
|
||||
|
||||
:looptop
|
||||
ADD ESI, 10
|
||||
CMP ESI, rectMaxx10
|
||||
JGE :loopend
|
||||
|
||||
:loopbody
|
||||
; Left top = 0, Right top = 0x10
|
||||
MOV [rcLeft.top+ESI], EAX | MOV [rcRight.top+ESI], ECX
|
||||
; Left bottom = 0x10, Right bottom = 0x20
|
||||
MOV [rcLeft.bottom+ESI], ECX | MOV [rcRight.bottom+ESI], EDX
|
||||
|
||||
POP EDI
|
||||
; Left/Right left = value from stack
|
||||
MOV [rcLeft.left+ESI], EDI | MOV [rcRight.left+ESI], EDI
|
||||
ADD EDI, 10
|
||||
; Left/Right right = value from stack + 0x10
|
||||
MOV [rcLeft.right+ESI], EDI | MOV [rcRight.right+ESI], EDI
|
||||
|
||||
JMP :looptop
|
||||
|
||||
:loopend
|
||||
|
||||
; if (gMC.air <= 0)
|
||||
MOV EDX, [gMC.air]
|
||||
CMP EDX, 0
|
||||
JG :checkCond
|
||||
MOV [gMC.ani_no], 0C
|
||||
JMP :checkDir
|
||||
|
||||
; if (gMC.cond & 2)
|
||||
:checkCond
|
||||
MOVZX EAX, BYTE [gMC.cond]
|
||||
TEST EAX, 00000002
|
||||
JNE :return
|
||||
|
||||
; if (gMC.flag & 8)
|
||||
:checkFlag
|
||||
MOV ECX, [gMC.flag]
|
||||
TEST ECX, 00000008
|
||||
JE :checkUp
|
||||
|
||||
; if (gMC.cond & 1)
|
||||
TEST EAX, 00000001
|
||||
JE :keycheckWalk
|
||||
MOV [gMC.ani_no], 0B
|
||||
JMP :checkDir
|
||||
|
||||
; else if (gKey & (gKeyLeft | gKeyRight) && bKey)
|
||||
:keycheckWalk
|
||||
MOV ECX, [gKey_addr]
|
||||
MOV EDX, [gKeyLeft]
|
||||
OR EDX, [gKeyRight]
|
||||
TEST ECX, EDX ; gKey & (gKeyLeft | gKeyRight)
|
||||
JE :keycheckStop
|
||||
|
||||
CMP [bKey], 0 ; bKey
|
||||
JE :keycheckStop
|
||||
|
||||
; if (gKey & gKeyUp)
|
||||
TEST ECX, [gKeyUp]
|
||||
JE :WalkFrames
|
||||
|
||||
:UpWalkFrames
|
||||
PUSH 6
|
||||
PUSH 9
|
||||
PUSH 9
|
||||
PUSH 7
|
||||
JMP :WalkAni
|
||||
:WalkFrames
|
||||
PUSH 1
|
||||
PUSH 4
|
||||
PUSH 4
|
||||
PUSH 2
|
||||
|
||||
:WalkAni
|
||||
OR EAX, 00000004
|
||||
MOV BYTE [gMC.cond], AL ;gMC.cond |= 4
|
||||
|
||||
POP EAX ; 7 if looking up, else 2
|
||||
POP ECX ; 9 if looking up, else 4
|
||||
|
||||
MOV ESI, [gMC.ani_wait]
|
||||
INC ESI ; ++gMC.ani_wait
|
||||
|
||||
MOV EDI, [gMC.ani_no]
|
||||
|
||||
; if (++gMC.ani_wait > 4)
|
||||
CMP ESI, 4
|
||||
JLE :checkWalkAni
|
||||
|
||||
XOR ESI,ESI ; gMC.ani_wait = 0
|
||||
|
||||
INC EDI ; ++gMC.ani_no
|
||||
|
||||
CMP EDI, EAX
|
||||
JE :playSound
|
||||
CMP EDI, ECX
|
||||
JNE :checkWalkAni
|
||||
|
||||
:playSound
|
||||
PUSH 1
|
||||
PUSH 18
|
||||
CALL PlaySoundObject
|
||||
ADD ESP,8
|
||||
|
||||
; UP: if (gMC.ani_no > 9 || gMC.ani_no < 6)
|
||||
; ELSE: if (gMC.ani_no > 4 || gMC.ani_no < 1)
|
||||
:checkWalkAni
|
||||
MOV [gMC.ani_wait], ESI
|
||||
|
||||
POP EAX ; 9 if looking up, else 4
|
||||
POP ECX ; 6 if looking up, else 1
|
||||
|
||||
CMP EDI, EAX
|
||||
JG :resetWalkAni
|
||||
CMP EDI, ECX
|
||||
JGE :setAniNo
|
||||
|
||||
:resetWalkAni
|
||||
MOV EDI, ECX
|
||||
|
||||
:setAniNo
|
||||
MOV [gMC.ani_no], EDI
|
||||
JMP :checkDir
|
||||
|
||||
:keyChecKStop
|
||||
TEST ECX, [gKeyUp]
|
||||
JE :StopFrame
|
||||
CMP [bKey], 0
|
||||
JE :StopFrame
|
||||
|
||||
:UpStopFrame
|
||||
PUSH 5
|
||||
JMP :StopAni
|
||||
:StopFrame
|
||||
PUSH 0
|
||||
|
||||
:StopAni
|
||||
TEST EAX, 00000004
|
||||
JE :SetStopAni
|
||||
PUSH 1
|
||||
PUSH 18
|
||||
CALL PlaySoundObject
|
||||
ADD ESP,8
|
||||
|
||||
:SetStopAni
|
||||
MOVZX EAX, BYTE [gMC.cond]
|
||||
AND EAX, FFFFFFFB
|
||||
MOV BYTE [gMC.cond], AL
|
||||
|
||||
POP ECX
|
||||
MOV [gMC.ani_no], ECX
|
||||
JMP :checkDir
|
||||
|
||||
:checkUp
|
||||
LEA EAX, [gMC.ani_no]
|
||||
|
||||
CMP [gMC.up], 0
|
||||
JE :checkDown
|
||||
MOV [EAX], 6
|
||||
JMP :checkDir
|
||||
|
||||
:checkDown
|
||||
CMP [gMC.down], 0
|
||||
JE :checkYm
|
||||
MOV [EAX], 0A
|
||||
JMP :checkDir
|
||||
|
||||
:checkYm
|
||||
CMP [gMC.ym], 0
|
||||
JLE :ymLess
|
||||
|
||||
:ymMore
|
||||
MOV [EAX], 1
|
||||
JMP :checkDir
|
||||
|
||||
:ymLess
|
||||
MOV [EAX], 3
|
||||
|
||||
:checkDir
|
||||
MOV EAX, [gMC.ani_no]
|
||||
SHL EAX, 4
|
||||
|
||||
CMP [gMC.direct], 0
|
||||
JNE :rectRight
|
||||
|
||||
:rectLeft
|
||||
LEA EAX, [EAX+rcLeft.left]
|
||||
JMP :setrect
|
||||
:rectRight
|
||||
LEA EAX, [EAX+rcRight.left]
|
||||
|
||||
:setrect
|
||||
MOV ECX, [EAX]
|
||||
MOV [gMC.rect.left], ECX
|
||||
MOV ECX, [EAX+4]
|
||||
MOV [gMC.rect.top], ECX
|
||||
MOV ECX, [EAX+8]
|
||||
MOV [gMC.rect.right], ECX
|
||||
MOV ECX, [EAX+0C]
|
||||
MOV [gMC.rect.bottom], ECX
|
||||
|
||||
:return
|
||||
POP EDI
|
||||
POP ESI
|
||||
|
||||
MOV ESP,EBP
|
||||
POP EBP
|
||||
RETN
|
||||
INT3
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
offset 414b50
|
||||
|
||||
PUSH EBP
|
||||
MOV EBP, ESP
|
||||
|
||||
PUSH 0B4
|
||||
PUSH 0
|
||||
PUSH 0049E638
|
||||
CALL 00480D30
|
||||
ADD ESP,0C ; memset(&gMC, 0, sizeof(MYCHAR))
|
||||
|
||||
MOV BYTE [49E638],80 ; gMC.cond = 0x80
|
||||
MOV [49E640],2 ; gMC.direct = 2
|
||||
|
||||
MOV EAX,1000
|
||||
MOV [49E694],EAX ; gMC.view.back = 8 * 0x200
|
||||
MOV [49E690],EAX ; gMC.view.top = 8 * 0x200
|
||||
MOV [49E68C],EAX ; gMC.view.front = 8 * 0x200
|
||||
MOV [49E698],EAX ; gMC.view.bottom = 8 * 0x200
|
||||
|
||||
MOV ECX,0A00
|
||||
MOV [49E684],ECX ; gMC.hit.back = 5 * 0x200
|
||||
MOV [49E680],EAX ; gMC.hit.top = 8 * 0x200
|
||||
MOV [49E67C],ECX ; gMC.hit.front = 5 * 0x200
|
||||
MOV [49e688],EAX ; gMC.hit.bottom = 8 * 0x200
|
||||
|
||||
MOV WORD [49E6CC],3 ; gMC.life = 3
|
||||
MOV WORD [49E6D0],3 ; gMC.max_life = 3
|
||||
MOV [49E64C],0 ; gMC.unit = 0
|
||||
|
||||
MOV [49E6DC],3E8 ; gMC.air = 1000
|
||||
|
||||
POP EBP
|
||||
RETN
|
||||
INT3
|
||||
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
offset 4169EB
|
||||
|
||||
#define
|
||||
GetNPCFlag=40E930
|
||||
StartTextScript=421990
|
||||
|
||||
setDeathCond=416A52
|
||||
computeAirGet=416A65
|
||||
|
||||
gMC.air=49E6DC
|
||||
#enddefine
|
||||
|
||||
PUSH 0FA0 ; 4000
|
||||
CALL GetNPCFlag
|
||||
POP ECX
|
||||
|
||||
TEST EAX,EAX ; if (GetNPCFlag(4000))
|
||||
JE :drown
|
||||
|
||||
:core
|
||||
PUSH 44C ; 1100
|
||||
CALL StartTextScript
|
||||
POP ECX
|
||||
|
||||
MOV [gMC.air], 3E8 ; gMC.air = 1000
|
||||
|
||||
JMP computeAirGet
|
||||
|
||||
:drown
|
||||
PUSH 29 ; 41
|
||||
CALL StartTextScript
|
||||
POP ECX
|
||||
|
||||
JMP setDeathCond
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
offset 415256
|
||||
|
||||
#define
|
||||
gMC.air=49E6DC
|
||||
gMC.cond=49E638
|
||||
#enddefine
|
||||
|
||||
CMP [gMC.air], 0
|
||||
JLE 00415495
|
||||
MOV AL, BYTE [gMC.cond]
|
||||
TEST AL, 00000080
|
||||
JE 00415270
|
||||
TEST AL, 00000002
|
||||
JE 00415275
|
||||
|
||||
//data 90 90 90 90 ; 4 bytes were saved
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
offset 40cf90
|
||||
|
||||
#define
|
||||
count=EBP-4
|
||||
Strip_addr=0049D628
|
||||
Credit.mode=49D620
|
||||
MAX_STRIP=40
|
||||
size=50
|
||||
|
||||
Strip.flag=EAX
|
||||
Strip.x=EAX+4
|
||||
Strip.y=EAX+8
|
||||
Strip.cast=EAX+0C
|
||||
Strip.str=EAX+10
|
||||
#enddefine
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
push ecx
|
||||
|
||||
mov eax, [Strip_addr]
|
||||
mov edx, MAX_STRIP
|
||||
|
||||
:$LL4@ActionStri
|
||||
test BYTE [Strip.flag], 80
|
||||
je :$LN5@ActionStri
|
||||
cmp [Credit.mode], 0
|
||||
je :$LN5@ActionStri
|
||||
|
||||
sub [Strip.y], 100
|
||||
|
||||
:$LN5@ActionStri
|
||||
cmp [Strip.y], -2000
|
||||
jg :$LN2@ActionStri
|
||||
|
||||
and [Strip.flag], 0
|
||||
|
||||
:$LN2@ActionStri
|
||||
add eax, size
|
||||
sub edx, 1
|
||||
jne :$LL4@ActionStri
|
||||
|
||||
leave
|
||||
retn
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
offset 40d3e0
|
||||
|
||||
#define
|
||||
size=50
|
||||
MAX_STRIP=40
|
||||
Strip_addr=0049d628
|
||||
#enddefine
|
||||
|
||||
PUSH EBP
|
||||
MOV EBP,ESP
|
||||
|
||||
PUSH 18
|
||||
PUSH 0
|
||||
PUSH 0049D610
|
||||
CALL 00480D30
|
||||
ADD ESP,0C
|
||||
|
||||
/*
|
||||
PUSH 500
|
||||
PUSH 0
|
||||
PUSH 0049D628
|
||||
CALL 00480D30
|
||||
ADD ESP,0C
|
||||
|
||||
PUSH size
|
||||
PUSH MAX_STRIP
|
||||
CALL 00487701
|
||||
ADD ESP,8
|
||||
MOV [Strip_addr],EAX
|
||||
*/
|
||||
XOR EAX,EAX
|
||||
MOV [Strip_addr],EAX
|
||||
|
||||
POP EBP
|
||||
RETN
|
||||
INT3
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
offset 4115e6
|
||||
PUSH 3F0 ; (MAX_STRIP - 1) * 0x10
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
ActionStripper.txt
|
||||
InitCreditScript.txt
|
||||
LoadGenericDataMAX_STRIP.txt
|
||||
PutStripper.txt
|
||||
RestoreStripper.txt
|
||||
SetStripper.txt
|
||||
StartCreditScript.txt
|
||||
ReleaseCreditScript.txt
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
offset 40D010
|
||||
|
||||
#define
|
||||
; Constants
|
||||
MAX_STRIP=40
|
||||
MAX_STRIPx10=400
|
||||
size=50
|
||||
|
||||
; Locals
|
||||
ArrayPad=EBP-4
|
||||
rc_addr=EBP-14
|
||||
rc.left=EBP-14
|
||||
rc.right=EBP-0C
|
||||
rc.top=EBP-10
|
||||
rc.bottom=EBP-8
|
||||
|
||||
; References
|
||||
Strip_addr=0049D628
|
||||
Strip.flag=ecx
|
||||
Strip.x=ecx+4
|
||||
Strip.y=ecx+8
|
||||
Strip.cast=ecx+0c
|
||||
Strip.str=ecx+10
|
||||
grcFull=0048f92c
|
||||
|
||||
; Functions
|
||||
PutBitmap3=0040c3c0
|
||||
|
||||
; Builtins
|
||||
___security_cookie=498b20
|
||||
__security_check_cookie=00480dc1
|
||||
#enddefine
|
||||
|
||||
push ebp
|
||||
mov ebp,esp
|
||||
sub esp, 14 ; 00000018H
|
||||
|
||||
push ebx
|
||||
push esi
|
||||
push edi
|
||||
; Line 92
|
||||
xor esi, esi
|
||||
xor edi, edi
|
||||
|
||||
:$LL4@PutStrippe
|
||||
; Line 94
|
||||
mov ecx, [Strip_addr]
|
||||
test BYTE [esi+Strip.flag], 80 ; 00000080H
|
||||
je :$LN2@PutStrippe
|
||||
; Line 97
|
||||
and [rc.left], 0
|
||||
mov [rc.right], 140 ; 00000140H
|
||||
mov [rc.top], edi
|
||||
lea eax, [edi+10]
|
||||
mov [rc.bottom], eax
|
||||
|
||||
; Line 102
|
||||
push 23 ; 00000023H
|
||||
|
||||
lea eax, [rc_addr]
|
||||
push eax
|
||||
|
||||
mov ebx, 1ff ; 000001ffH
|
||||
mov eax, [esi+Strip.y]
|
||||
cdq
|
||||
and edx, ebx
|
||||
add eax, edx
|
||||
sar eax, 9
|
||||
push eax
|
||||
|
||||
mov eax, [esi+Strip.x]
|
||||
cdq
|
||||
and edx, ebx
|
||||
add eax, edx
|
||||
sar eax, 9
|
||||
push eax
|
||||
|
||||
push grcFull
|
||||
|
||||
call PutBitmap3
|
||||
|
||||
; Line 110
|
||||
push 25 ; 00000025H
|
||||
|
||||
mov ecx, [Strip_addr]
|
||||
mov eax, [esi+Strip.cast]
|
||||
cdq
|
||||
mov ebx, 0d
|
||||
idiv ebx
|
||||
imul edx, edx, 18
|
||||
imul eax, eax, 18
|
||||
mov [rc.left], edx
|
||||
add edx, 18 ; 00000018H
|
||||
mov [rc.right], edx
|
||||
mov [rc.top], eax
|
||||
add eax, 18
|
||||
mov [rc.bottom], eax
|
||||
lea eax, [rc_addr]
|
||||
push eax
|
||||
|
||||
mov ebx, 1ff
|
||||
mov eax, [esi+Strip.y]
|
||||
cdq
|
||||
and edx, ebx
|
||||
add eax, edx
|
||||
sar eax, 9
|
||||
sub eax, 8
|
||||
push eax
|
||||
|
||||
mov eax, [esi+Strip.x]
|
||||
cdq
|
||||
and edx, ebx
|
||||
add eax, edx
|
||||
sar eax, 9
|
||||
sub eax, 18 ; 00000018H
|
||||
push eax
|
||||
|
||||
push grcFull
|
||||
|
||||
call PutBitmap3
|
||||
add esp, 28 ; 00000028H
|
||||
|
||||
:$LN2@PutStrippe
|
||||
; Line 92
|
||||
add edi, 10 ; 00000010H
|
||||
add esi, size ; 00000050H
|
||||
cmp edi, MAX_STRIPx10 ; 000007f0H
|
||||
jl :$LL4@PutStrippe
|
||||
|
||||
; Line 113
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebx
|
||||
leave
|
||||
retn
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
offset 40d410
|
||||
|
||||
#define
|
||||
Credit.pData=49d614
|
||||
Strip=49d628
|
||||
_free=0048128b
|
||||
#enddefine
|
||||
|
||||
push ebp
|
||||
mov ebp,esp
|
||||
|
||||
mov eax, [Credit.pData]
|
||||
test eax, eax
|
||||
je :$LN2@ReleaseCre
|
||||
|
||||
push eax
|
||||
call _free
|
||||
pop ecx
|
||||
|
||||
and [Credit.pData], 0
|
||||
|
||||
:$LN2@ReleaseCre
|
||||
mov eax, [Strip]
|
||||
test eax, eax
|
||||
je :$LN3@ReleaseCre
|
||||
|
||||
push eax
|
||||
call _free
|
||||
pop ecx
|
||||
|
||||
:$LN3@ReleaseCre
|
||||
mov esp, ebp
|
||||
pop ebp
|
||||
retn
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
offset 40d240
|
||||
|
||||
#define
|
||||
; Constants
|
||||
MAX_STRIPx10=400
|
||||
|
||||
; Locals
|
||||
ArrayPad = EBP-4
|
||||
rc_addr = EBP-14
|
||||
rc.left=EBP-14
|
||||
rc.right=EBP-0c
|
||||
rc.top=EBP-10
|
||||
rc.bottom=EBP-8
|
||||
|
||||
; References
|
||||
Credit=49D620
|
||||
Strip_addr=0049D628
|
||||
Strip.flag=0049D628
|
||||
Strip.x=0049D62C
|
||||
Strip.y=0049D630
|
||||
Strip.cast=0049D634
|
||||
Strip.str=0049D638
|
||||
|
||||
; Functions
|
||||
CortBox2=0040ca80
|
||||
PutText2=0040ceb0
|
||||
|
||||
; Builtins
|
||||
___security_cookie=498b20
|
||||
__security_check_cookie=00480dc1
|
||||
#enddefine
|
||||
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
sub esp, 14 ; 00000014H
|
||||
push esi
|
||||
push edi
|
||||
; Line 151
|
||||
xor edi, edi
|
||||
xor esi, esi
|
||||
:$LL4@RestoreStr
|
||||
; Line 153
|
||||
mov eax, [Strip_addr]
|
||||
test eax, eax
|
||||
je :return
|
||||
test [edi+eax], 128 ; 00000080H
|
||||
je :$LN2@RestoreStr
|
||||
; Line 155
|
||||
and [rc.left], 0
|
||||
; Line 156
|
||||
mov [rc.right], 140 ; 00000140H
|
||||
; Line 157
|
||||
mov [rc.top], esi
|
||||
; Line 158
|
||||
lea eax, [esi+16]
|
||||
mov [rc.bottom], eax
|
||||
; Line 160
|
||||
push 23 ; 00000023H
|
||||
push 0
|
||||
lea eax, [rc_addr]
|
||||
push eax
|
||||
|
||||
call CortBox2
|
||||
; Line 161
|
||||
push 23 ; 00000023H
|
||||
push 00feffff ; 00feffffH
|
||||
mov eax, [Strip_addr]
|
||||
add eax, 10 ; 00000010H
|
||||
add eax, edi
|
||||
push eax
|
||||
push [rc.top]
|
||||
push 0
|
||||
call PutText2
|
||||
add esp, 20 ; 00000020H
|
||||
:$LN2@RestoreStr
|
||||
; Line 151
|
||||
add esi, 10 ; 00000010H
|
||||
add edi, 50 ; 00000050H
|
||||
cmp esi, MAX_STRIPx10 ; 000007f0H
|
||||
jl :$LL4@RestoreStr
|
||||
; Line 164
|
||||
:return
|
||||
pop edi
|
||||
pop esi
|
||||
leave
|
||||
retn
|
||||
|
|
@ -1,116 +0,0 @@
|
|||
offset 40d150
|
||||
|
||||
#define
|
||||
; Constants
|
||||
MAX_STRIP=40
|
||||
size=50
|
||||
|
||||
; Locals
|
||||
ArrayPad=EBP-4
|
||||
rc_addr=EBP-14
|
||||
rc.left=EBP-14
|
||||
rc.right=EBP-0C
|
||||
rc.top=EBP-10
|
||||
rc.bottom=EBP-8
|
||||
|
||||
; Arguments
|
||||
argx=EBP+8
|
||||
argy=EBP+0C
|
||||
argtext=EBP+10
|
||||
argcast=EBP+14
|
||||
|
||||
; References
|
||||
Strip_addr=0049D628
|
||||
Strip.flag=edx
|
||||
Strip.x=edx+4
|
||||
Strip.y=edx+8
|
||||
Strip.cast=edx+0c
|
||||
Strip.str=edx+10
|
||||
|
||||
; Functions
|
||||
CortBox2=0040ca80
|
||||
PutText2=0040ceb0
|
||||
|
||||
; Builtins
|
||||
___security_cookie=498b20
|
||||
__security_check_cookie=00480dc1
|
||||
_strcpy=00481100
|
||||
#enddefine
|
||||
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
sub esp, 14 ; 00000014H
|
||||
mov eax, [___security_cookie]
|
||||
mov [ArrayPad], eax
|
||||
mov edx, [Strip_addr]
|
||||
mov eax, edx
|
||||
push esi
|
||||
push edi
|
||||
mov edi, [argtext]
|
||||
; Line 121
|
||||
xor esi, esi
|
||||
:$LL4@SetStrippe
|
||||
; Line 122
|
||||
test [eax], 80 ; 00000080H
|
||||
je :$LN13@SetStrippe
|
||||
; Line 121
|
||||
inc esi
|
||||
add eax, size ; 00000050H
|
||||
mov ecx, esi
|
||||
cmp esi, MAX_STRIP ; 0000007fH
|
||||
jl :$LL4@SetStrippe
|
||||
; Line 125
|
||||
cmp ecx, MAX_STRIP ; 0000007fH
|
||||
je :$LN1@SetStrippe
|
||||
:$LN13@SetStrippe
|
||||
; Line 129
|
||||
imul ecx, esi, size
|
||||
mov [ecx+Strip.flag], 80 ; 00000080H
|
||||
; Line 130
|
||||
mov eax, [argx]
|
||||
mov [ecx+Strip.x], eax
|
||||
; Line 131
|
||||
mov eax, [argy]
|
||||
mov [ecx+Strip.y], eax
|
||||
; Line 132
|
||||
mov eax, [argcast]
|
||||
mov [ecx+Strip.cast], eax
|
||||
; Line 133
|
||||
push edi
|
||||
lea eax, [Strip.str]
|
||||
add eax, ecx
|
||||
push eax
|
||||
call _strcpy
|
||||
; Line 136
|
||||
and [rc.left], 0
|
||||
; Line 137
|
||||
mov [rc.right], 140 ; 00000140H
|
||||
; Line 138
|
||||
shl esi, 4
|
||||
mov [rc.top], esi
|
||||
; Line 139
|
||||
lea eax, [esi+10]
|
||||
mov [rc.bottom], eax
|
||||
|
||||
; Line 141
|
||||
push 23 ; 00000023H
|
||||
push 0
|
||||
lea eax, [rc_addr]
|
||||
push eax
|
||||
call CortBox2
|
||||
; Line 142
|
||||
push 23 ; 00000023H
|
||||
push 00feffff ; 00feffffH
|
||||
push edi
|
||||
push [rc.top]
|
||||
push 0
|
||||
call PutText2
|
||||
add esp, 28 ; 00000028H
|
||||
:$LN1@SetStrippe
|
||||
; Line 143
|
||||
pop edi
|
||||
pop esi
|
||||
mov ecx, [ArrayPad]
|
||||
call __security_check_cookie
|
||||
leave
|
||||
retn
|
||||
|
|
@ -1,160 +0,0 @@
|
|||
offset 40d440
|
||||
|
||||
#define
|
||||
; Constants
|
||||
MAX_STRIP=40
|
||||
size=50
|
||||
|
||||
; Locals
|
||||
path=EBP-108
|
||||
ArrayPad=EBP-4
|
||||
|
||||
; References
|
||||
Strip_addr=0049D628
|
||||
Credit.pData=49D614
|
||||
Credit.size=49d610
|
||||
Credit.offset=49d618
|
||||
Credit.wait=49d61c
|
||||
Credit.mode=49d620
|
||||
Illust.x=49d60c
|
||||
Illust.act_no=49d608
|
||||
grcGame.left=48f91c
|
||||
gDataPath=0049E220
|
||||
|
||||
; Functions
|
||||
GetFileSizeLong=00410d80
|
||||
EncryptionBinaryData2=004215c0
|
||||
ReloadBitmapFile=0040BFD0
|
||||
|
||||
; Builtins
|
||||
___security_cookie=498b20
|
||||
__security_check_cookie=00480dc1
|
||||
_malloc=004813a3
|
||||
_calloc=00487701
|
||||
_free=0048128B
|
||||
_memset=00480d30
|
||||
_sprintf=00481010
|
||||
_fopen=00480FFD
|
||||
_fread=00480f55
|
||||
|
||||
; Strings
|
||||
credit_script=48f918
|
||||
format=0048C374
|
||||
str_rb=0048C37C
|
||||
str_casts=0048c380
|
||||
#enddefine
|
||||
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
sub esp, 108 ; 00000108H
|
||||
mov eax, [___security_cookie]
|
||||
mov [ArrayPad], eax
|
||||
; Line 241
|
||||
mov eax, [Credit.pData]
|
||||
push esi
|
||||
xor esi, esi
|
||||
push edi
|
||||
test eax, eax
|
||||
je :$LN2@StartCredi
|
||||
; Line 243
|
||||
push eax
|
||||
call _free
|
||||
pop ecx
|
||||
; Line 244
|
||||
mov [Credit.pData], esi
|
||||
|
||||
:$LN2@StartCredi
|
||||
; Line 248
|
||||
push [credit_script]
|
||||
lea eax, [path]
|
||||
push gDataPath
|
||||
push format
|
||||
push eax
|
||||
call _sprintf
|
||||
; Line 250
|
||||
lea eax, [path]
|
||||
push eax
|
||||
call GetFileSizeLong
|
||||
add esp, 14 ; 00000014H
|
||||
mov [Credit.size], eax
|
||||
; Line 251
|
||||
cmp eax, -1
|
||||
je :$LN8@StartCredi
|
||||
; Line 255
|
||||
push eax
|
||||
call _malloc
|
||||
mov [Credit.pData], eax
|
||||
pop ecx
|
||||
; Line 256
|
||||
test eax, eax
|
||||
je :$LN8@StartCredi
|
||||
; Line 259
|
||||
lea eax, [path]
|
||||
push str_rb
|
||||
push eax
|
||||
call _fopen
|
||||
pop ecx
|
||||
pop ecx
|
||||
; Line 260
|
||||
test eax, eax
|
||||
jne :$LN5@StartCredi
|
||||
; Line 262
|
||||
push [Credit.pData]
|
||||
call _free
|
||||
pop ecx
|
||||
:$LN8@StartCredi
|
||||
; Line 299
|
||||
xor eax, eax
|
||||
:$LN1@StartCredi
|
||||
pop edi
|
||||
pop esi
|
||||
mov ecx, [ArrayPad]
|
||||
call __security_check_cookie
|
||||
leave
|
||||
retn
|
||||
:$LN5@StartCredi
|
||||
; Line 267
|
||||
push eax
|
||||
push [Credit.size]
|
||||
xor edi, edi
|
||||
inc edi
|
||||
push edi
|
||||
push [Credit.pData]
|
||||
call _fread
|
||||
; Line 274
|
||||
push [Credit.size]
|
||||
push [Credit.pData]
|
||||
call EncryptionBinaryData2
|
||||
; Line 293
|
||||
push 25 ; 00000025H
|
||||
push str_casts
|
||||
mov [Credit.offset], esi
|
||||
mov [Credit.wait], esi
|
||||
mov [Credit.mode], edi
|
||||
mov [Illust.x], fffec000 ; fffec000H
|
||||
mov [Illust.act_no], esi
|
||||
mov [grcGame.left], 0a0 ; 000000a0H
|
||||
call ReloadBitmapFile
|
||||
add esp, 20 ; 00000020H
|
||||
test eax, eax
|
||||
je SHORT :$LN8@StartCredi
|
||||
; Line 297
|
||||
mov eax, [Strip_addr]
|
||||
test eax, eax
|
||||
je :blah
|
||||
|
||||
push eax
|
||||
call _free
|
||||
pop ecx
|
||||
|
||||
:blah
|
||||
push size
|
||||
push MAX_STRIP
|
||||
call _calloc
|
||||
add ESP,8
|
||||
mov [Strip_addr],EAX
|
||||
; Line 298
|
||||
mov eax, edi
|
||||
jmp :$LN1@StartCredi
|
||||
|
||||
data cc cc cc cc cc cc cc cc
|
||||
|
|
@ -1,107 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<hack name="SuperOrg" author="txin">
|
||||
<panel>
|
||||
<panel title="Info">
|
||||
</panel>
|
||||
<field type="info" col="0">
|
||||
Causes the game to load music and instruments from files instead of resources.
|
||||
This effectively allows for near unlimited music files in a mod.
|
||||
</field>
|
||||
<field type="info" col="0">
|
||||
<CMUabcd will now change the current music to "data\Orgs\abcd.org".
|
||||
"abcd" can be any ascii character, and letters are case sensitive.
|
||||
It will also load the instruments within "data\Orgs\abcd.dat" as a wave100 file.
|
||||
</field>
|
||||
<field type="info" col="0">
|
||||
If the "*.dat" file is not found, the game will simply skip loading it.
|
||||
However, if the "*.org" file is not found, the game may crash.
|
||||
The default/empty org is "0000.org", and the default wave100 is "0000.dat".
|
||||
</field>
|
||||
<panel title="Customize" col="0">
|
||||
</panel>
|
||||
<panel>
|
||||
<panel title="" col="0">
|
||||
<field type="label">New *.org size limit (bytes)</field>
|
||||
|
||||
<field type="text" size="4" offset="0x41BAED" col="1">1048576</field>
|
||||
</panel>
|
||||
</panel>
|
||||
<panel title="Data" col="0">
|
||||
</panel>
|
||||
<panel>
|
||||
<field type="data" offset="0x40FDF4" col="0">
|
||||
89 85 9C FE FF FF 85 C0 74 58 3D 28 23 00 00 7D
|
||||
0F 6A 04 8F 85 E4 FE FF FF 68 30 30 30 32 EB 47
|
||||
3D E0 2E 00 00 7D 0F 6A 03 8F 85 E4 FE FF FF 68
|
||||
30 30 34 31 EB 31 3D 98 3A 00 00 7D 0F 6A 02 8F
|
||||
85 E4 FE FF FF 68 30 30 34 30 EB 1B 3D 50 46 00
|
||||
00 7D 0F 6A 01 8F 85 E4 FE FF FF 68 30 30 33 36
|
||||
EB 05 68 30 30 32 34 E8 80 10 01 00 58 90 90 90
|
||||
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
|
||||
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
|
||||
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
|
||||
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
|
||||
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
|
||||
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
|
||||
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
|
||||
</field>
|
||||
<field type="data" offset="0x41B379" col="1">
|
||||
2E 64 61 74 00 CC CC 60 89 E5 8B 7D 24 6A 7F 59
|
||||
31 C0 89 CA F2 AE E3 47 29 CA 89 D1 8B 75 24 BF
|
||||
B9 4F 49 00 F3 A4 68 48 C7 48 00 68 B0 4F 49 00
|
||||
6A 05 59 E8 50 8F 00 00 F3 A4 E8 45 5C 06 00 85
|
||||
C0 74 1C 50 93 6A 01 68 00 64 00 00 68 00 E7 49
|
||||
00 E8 86 5B 06 00 53 E8 46 5A 06 00 31 C0 40 89
|
||||
45 1C 89 EC 61 C3 CC B8 F4 57 4A 00 89 08 C3 CC
|
||||
CC CC CC CC CC CC CC
|
||||
</field>
|
||||
<field type="data" offset="0x41BAD0" col="2">
|
||||
60 8B EC 81 EC 9C 00 00 00 A1 20 8B 49 00 89 45
|
||||
EC 56 89 8D 64 FF FF FF C6 45 F7 00 68 00 00 10
|
||||
00 E8 AD 58 06 00 89 45 FC FF 75 24 E8 7F F8 FF
|
||||
FF 6A 05 BE A3 C0 41 00 59 F3 A4 68 48 C7 48 00
|
||||
68 B0 4F 49 00 E8 E3 54 06 00 93 31 C0 40 E8 E8
|
||||
87 00 00
|
||||
</field>
|
||||
<field type="data" offset="0x41C09D" col="3">
|
||||
8B E5 61 C2 04 00 2E 6F 72 67 00 CC
|
||||
</field>
|
||||
<field type="data" offset="0x41C6B1" col="4">
|
||||
30 30 30 30 00 CC CC CC CC CC CC CC CC CC CC 55
|
||||
8B EC 8B 0D E8 57 4A 00 E3 21 68 B1 C6 41 00 E8
|
||||
AB EC FF FF 85 C0 75 04 33 C0 EB 0F B9 18 4E 4A
|
||||
00 E8 69 EF FF FF B8 01 00 00 00 C9 C3
|
||||
</field>
|
||||
<field type="data" offset="0x420EE0" col="0">
|
||||
55 8B EC 8B 4D 08 E3 0A 3B 0D F4 57 4A 00 75 02
|
||||
C9 C3 E8 79 B8 FF FF BA F4 57 4A 00 89 42 04 8B
|
||||
0A 89 4A 08 E8 E7 B8 FF FF 83 7D 08 00 75 07 C7
|
||||
45 08 30 30 30 30 E8 1F 34 00 00 9B E8 CF B7 FF
|
||||
FF 83 C4 04 6A 64 E8 95 B8 FF FF 83 C4 04 6A 00
|
||||
E8 FB B7 FF FF 83 C4 04 E8 53 B8 FF FF 8B 4D 08
|
||||
E8 9B A4 FF FF C9 C3 CC
|
||||
</field>
|
||||
<field type="data" offset="0x420F50" col="1">
|
||||
60 8B EC E8 18 B8 FF FF 97 E8 92 B8 FF FF BE F4
|
||||
57 4A 00 8B 1E 8B 46 08 B9 A8 4F 49 00 89 01 C6
|
||||
41 04 00 51 E8 77 B7 FF FF FF 76 04 E8 AF B7 FF
|
||||
FF 6A 64 E8 38 B8 FF FF E8 03 B8 FF FF 8B 46 08
|
||||
89 06 89 7E 08 89 EC 61 C3
|
||||
</field>
|
||||
<field type="data" offset="0x4242DA" col="2">
|
||||
B9 E0 5A 4A 00 8B 51 F8 03 11 81 3A 3C 43 4D 55
|
||||
75 60 FF 72 04 E8 EC CB FF FF 58 83 05 E0 5A 4A
|
||||
00 08 E9 CA E2 FF FF BE 79 B3 41 00 4F 89 7D 00
|
||||
C3 8B 75 FC 3C 01 75 0F 53 50 50 56 E8 3A CC 05
|
||||
00 46 83 C4 10 EB ED 8B 0D D4 4F 49 00 E3 07 51
|
||||
E8 5C CF 05 00 59 8B 55 FC 89 15 D4 4F 49 00 C3
|
||||
5A B9 A8 4F 49 00 8B 45 08 89 01 C6 41 04 00 51
|
||||
FF E2
|
||||
</field>
|
||||
<field type="data" offset="0x494FB0" col="3">
|
||||
64 61 74 61 5C 4F 72 67 5C 51 57 45 52 54 59 55
|
||||
49 4F 50 2E 64 61 74 00
|
||||
</field>
|
||||
</panel>
|
||||
</panel>
|
||||
</hack>
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<hack name="SpeedText" author="txin">
|
||||
<panel>
|
||||
<panel title="Description">
|
||||
</panel>
|
||||
<field type="info">
|
||||
Causes message box text to scroll instantly, displaying = signs as circles.
|
||||
</field>
|
||||
<panel title="Data">
|
||||
</panel>
|
||||
<panel>
|
||||
<field type="data" offset="0x421d01" col="0">
|
||||
FE 45 D4 C3
|
||||
</field>
|
||||
<field type="data" offset="0x422573" col="1">
|
||||
6A 01 5A B9 28 36 49 00 A1 10 E2 49 00 F6 C4 02
|
||||
71 24 85 01 74 03 C1 F2 02 85 41 04 74 03 C1 F2
|
||||
02 B9 FC 5A 4A 00 01 11 83 39 04 0F 8C 98 31 00
|
||||
00 83 21 00 EB 1B 42 EB DD 90 90 90 90 90 90 90
|
||||
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
|
||||
90 C7 45 D4 00 00 00 00 83 7D D4 00 0F 85 9C 2F
|
||||
00 00 8B 0D D8 5A 4A 00 03 0D E0 5A 4A 00 0F BE
|
||||
11 83 FA 3C 0F 85 BF 2C 00 00 81 39 3C 45 4E 44
|
||||
75 71 C6 05 DC 5A 4A 00 00 80 25 38 E6 49 00 FE
|
||||
80 0D E8 E1 49 00 03 83 25 0C 5B 4A 00 00 6A 01
|
||||
8F 45 D4 EB B3 90 90 90 90 90 90 90 90 B9 28 36
|
||||
49 00 A1 10 E2 49 00 F6 C4 02 71 09 85 01 74 12
|
||||
85 41 04 74 0D 6A 00 6A 00 E8 0F 00 00 00 89 45
|
||||
D4 C3 6A 01 58 EB F7 90 90 90 90 90 90 B9 B1 37
|
||||
49 00 8B 44 E4 08 80 09 01 9B C2 08 00 90 90 90
|
||||
90 90 90
|
||||
</field>
|
||||
<field type="data" offset="0x423654" col="2">
|
||||
00
|
||||
</field>
|
||||
<field type="data" offset="0x4236B4" col="2">
|
||||
00
|
||||
</field>
|
||||
<field type="data" offset="0x425565" col="0">
|
||||
E8 B6 D0 FF FF D9 D0 E9 5A D0 FF FF E9 C6 01 00 00
|
||||
</field>
|
||||
<field type="data" offset="0x425737" col="1">
|
||||
E9 00 00 00 00 80 3D DC 5A 4A 00 00 75 0E 83 25 E8 E1 49 00 FB
|
||||
65 66 0F 19 C4
|
||||
</field>
|
||||
</panel>
|
||||
</panel>
|
||||
</hack>
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
0x40CD91
|
||||
03
|
||||
0x40CDC8
|
||||
03
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
0x40149E
|
||||
8B 4D F8 49 79 01 41 B8 68 9C 49 00 31 D2 39 10
|
||||
7D 02 89 08 39 08 7E 14 89 10 90 90 90 90 90 90
|
||||
90 90 90 90 90 90 90 90 90 90 90 90
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
0x41DB17
|
||||
95 EA
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
this file isn't a real hex patch; it's a copy and paste of peri's discord message on 5 dec 2024:
|
||||
|
||||
---
|
||||
|
||||
There is an undocumented hex edit to increase the size of the Casts.bmp surface (0x411569: F0 00 -> E0 01, which I presume we just used BL's hacks/intro/surface_bitmap_sizes.xml here);
|
||||
|
||||
There is an undocumented hex edit to increase the TSC buffer size (0x421545: 00 50 00 -> 20 A1 07, again this was probably from the BL hack and we never wrote it down);
|
||||
|
||||
Randomly the byte at 0x414B24 was changed from 0x80 to 0x5F, which is the number of bytes to memset when initializing the map flag array. Not sure why this was changed, but the multiworld DLL overwrites this function anyways so it doesn't really make a difference (anymore).
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
0x41D9C6
|
||||
A1 09 DF 49 00 90
|
||||
|
||||
0x41DA1F
|
||||
C7 45 F8 00 00 00 00 C7 45 FC 00 00 00 00
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
Author: Enlight
|
||||
|
||||
DUNC NOTE: flag range changed from 4008 through 4015 to 2888 through 2919 in rando
|
||||
also: skip the second patch it's not needed and also bugged
|
||||
|
||||
Instructions:
|
||||
1. Backup your .exe, then patch your .exe with the patches in patches.txt.
|
||||
2. Learn how to use the hack and setup your teleporters with the demonstration mod and the information below.
|
||||
3. Make a similar system in your mod.
|
||||
|
||||
|
||||
Important Files:
|
||||
Patches.txt - The first patch allows you to edit where teleporter menus draw. The 2nd one just fixes a graphic bug with slots 6 and 7.
|
||||
|
||||
OOBFlagGen.jar - What helps you generate the flags for the top framerects. Input address 49DF09 and the value will be how many pixels down you want
|
||||
the mod to START drawing the teleporter icons IN HEXADECIMAL. The rows are IN DECIMAL 0, 16, 32, 48, 64... etc. In HEXADECIMAL it's 0, 10, 20, 30 etc.
|
||||
Keep it in bytes. You will then copy the flags it generates (should be just over flag 4000) to use in your level TSC (explained below)
|
||||
|
||||
StageSelect.tsc - Example of how you can setup having different location names for different teleporters.
|
||||
This is just normal TSC using flags. The game is hardcoded to run events 1001-1007 for the slots, but flagjumps can change what it says.
|
||||
|
||||
The TSC file for Arthur's House (Pens1.tsc) - Example of how to setup everything else for the teleporters (explained below)
|
||||
|
||||
|
||||
~~~~~
|
||||
|
||||
|
||||
|
||||
Please open the demonstration mod in a CS editor of you choice to see how the tsc all comes together.
|
||||
The most important events though are the ones for displaying the teleporter.
|
||||
One of these events is shown below with comments.
|
||||
|
||||
#0100
|
||||
<KEY
|
||||
<FL-4008<FL-4009<FL-4010<FL-4011<FL-4012<FL-4013<FL-4014<FL-4015
|
||||
// What you generate with OOBFlagGen, tells the game the top framerect of where to draw the teleporter images.
|
||||
|
||||
<FL+5001<FL-5002<FL-5003<FL-5004
|
||||
// These are used like normal flags, telling StageSelect.tsc what to call the teleporter options.
|
||||
|
||||
<PS+0001:0110<PS+0002:0111<PS+0003:0112<PS+0004:0113
|
||||
// These are overwriting the teleporter slots to run events 110-113, this is what's saved to profile.dat
|
||||
but you can (probably) ignore that and just overwrite it every time before you display the tele menu.
|
||||
|
||||
<SLP<END
|
||||
// Displays the teleporter menu.
|
||||
|
||||
|
||||
|
||||
~~~~~
|
||||
|
||||
|
||||
|
||||
|
||||
If you have any other questions you can just contact me (Enlight) because I'm not good at writing tutorials at 4:30 AM
|
||||
<Cave Story ~ Doukutsu Monogatari> (C) Studio Pixel 2004
|
||||
|
|
@ -1,108 +0,0 @@
|
|||
; ActionCredit_Read
|
||||
|
||||
offset 0040d684
|
||||
|
||||
#define
|
||||
var_a=ebp-30
|
||||
len=ebp-34
|
||||
var_text=ebp-2c
|
||||
|
||||
Credit.pData=49d614
|
||||
Credit.offset=49d618
|
||||
Credit.wait=49d61c
|
||||
Credit.start_x=49d624
|
||||
|
||||
_memcpy=4813c0
|
||||
GetScriptNumber=40db00
|
||||
SetStripper=40d150
|
||||
IsShiftJIS=410e90
|
||||
#enddefine
|
||||
|
||||
mov ecx,[Credit.offset]
|
||||
inc ecx
|
||||
mov [Credit.offset],ecx
|
||||
mov [var_a],ecx
|
||||
|
||||
:loop
|
||||
mov eax,[Credit.pData]
|
||||
add eax,[var_a]
|
||||
movsx ecx,BYTE [eax]
|
||||
cmp ecx,5d
|
||||
je :break
|
||||
push ecx
|
||||
call IsShiftJIS
|
||||
pop ecx
|
||||
mov ecx,[var_a]
|
||||
test eax,eax
|
||||
je :notShiftJIS
|
||||
inc ecx
|
||||
:notShiftJIS
|
||||
inc ecx
|
||||
mov [var_a],ecx
|
||||
jmp :loop
|
||||
|
||||
:break
|
||||
; len = a - Credit.offset
|
||||
mov edx,[var_a]
|
||||
sub edx,[Credit.offset]
|
||||
mov [len],edx
|
||||
|
||||
push edx ; Arg3 = len
|
||||
|
||||
mov ecx,[Credit.pData]
|
||||
add ecx,[Credit.offset]
|
||||
push ecx ; Arg2 = &Credit.pData[Credit.offset]
|
||||
|
||||
lea ecx,[var_text]
|
||||
push ecx ; Arg1 = text
|
||||
|
||||
call _memcpy
|
||||
add esp,0c
|
||||
|
||||
; text[len] = '\0'
|
||||
mov ecx,[len]
|
||||
mov [ecx+var_text],0
|
||||
|
||||
; Credit.offset = a+1
|
||||
mov eax,[var_a]
|
||||
inc eax
|
||||
mov [Credit.offset],eax
|
||||
|
||||
|
||||
add eax,[Credit.pData]
|
||||
push eax ; Arg1 = &Credit.pData[Credit.offset]
|
||||
call GetScriptNumber
|
||||
; len = GetScriptNumber
|
||||
mov [len],eax
|
||||
pop ecx
|
||||
|
||||
push eax ; Arg4 = len
|
||||
|
||||
lea eax,[var_text]
|
||||
push eax ; Arg3 = text
|
||||
|
||||
mov edx,1f000
|
||||
mov eax,[Credit.wait]
|
||||
cmp eax,0
|
||||
jge :more
|
||||
imul eax,eax,200
|
||||
add edx,eax
|
||||
:more
|
||||
push edx
|
||||
|
||||
mov eax,[Credit.start_x]
|
||||
push eax ; Arg1 = Credit.start_x
|
||||
|
||||
call SetStripper
|
||||
add esp,10
|
||||
|
||||
; Credit.wait = 0
|
||||
mov [Credit.wait],0
|
||||
|
||||
; Credit.offset += 0
|
||||
mov eax,[Credit.offset]
|
||||
add eax,4
|
||||
mov [Credit.offset],eax
|
||||
jmp 0040da6a
|
||||
|
||||
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<hack name="noLoseFocus" author="Clownacy / txin">
|
||||
<panel>
|
||||
<field type="info">
|
||||
Prevents the game stopping when in the background
|
||||
</field>
|
||||
<field type="data" offset="0x413593">
|
||||
71
|
||||
</field>
|
||||
<field type="data" offset="0x412BC0">
|
||||
C3
|
||||
</field>
|
||||
<field type="data" offset="0x412BF0">
|
||||
C3
|
||||
</field>
|
||||
</panel>
|
||||
</hack>
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
0x434101
|
||||
8B 75 08 8B 46 10 01 46 08 8B 46 14 01 46 0C 6A
|
||||
20 59 3E 83 A4 8D 7C FF FF FF 00 E2 F5 C6 45 C0
|
||||
20 C6 45 C4 20 C6 45 C8 30 C6 45 CC 30 C6 45 D0
|
||||
30 C6 45 D4 20 C6 45 D8 40 C6 45 DC 30 C6 45 E0
|
||||
40 C6 45 E4 20 C6 45 E8 50 C6 45 EC 30 C6 45 F0
|
||||
50 C6 45 F4 20 C6 45 F8 60 C6 45 FC 30 C6 45 80
|
||||
20 C6 45 84 30 C6 45 88 30 C6 45 8C 40 C6 45 90
|
||||
30 C6 45 94 30 C6 45 98 40 C6 45 9C 40 C6 45 A0
|
||||
40 C6 45 A4 30 C6 45 A8 50 C6 45 AC 40 C6 45 B0
|
||||
50 C6 45 B4 30 C6 45 B8 60 C6 45 BC 40 FF 46 64
|
||||
83 7E 64 01 7E 07 83 66 64 00 FF 46 68 83 7E 68
|
||||
02 7E 04 83 66 68 00 89 F7 83 C7 54 8B 46 68 C1
|
||||
E0 04 83 7E 4C 00 75 06 8D 74 05 C0 EB 04 8D 74
|
||||
05 80 6A 04 59 F3 A5 C9 C3 CC CC CC CC CC CC 64
|
||||
61 74 61 5C 68 61 73 68 2E 74 78 74 00 CC CC C8
|
||||
34 01 00 6A 02 6A 05 E8 04 35 05 00 83 C4 04 89
|
||||
45 DC 68 E0 41 43 00 68 28 E3 49 00 68 40 C7 48
|
||||
00 8D 85 CC FE FF FF 50 E8 F2 CD 04 00 83 C4 10
|
||||
68 8C C2 48 00 8D 85 CC FE FF FF 50 E8 CB CD 04
|
||||
00 83 C4 08 85 C0 75 05 8B 45 DC C9 C3 50 6A 01
|
||||
6A 20 8D 45 E0 50 E8 09 CD 04 00 83 C4 0C E8 C7
|
||||
CB 04 00 83 C4 04 31 C9 31 D2 31 DB 30 E4 8A 44
|
||||
29 E0 3C 30 72 0F 3C 39 77 0B 2C 30 6B DB 0A 66
|
||||
01 C3 41 EB E9 8B 45 DC 66 89 1C 50 41 42 83 FA
|
||||
05 7C D7 C9 C3 CC CC CC CC CC CC CC CC CC CC CC
|
||||
CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC
|
||||
CC CC CC CC CC CC CC CC CC
|
||||
|
||||
0x433CC7
|
||||
43
|
||||
0x433EFB
|
||||
8B 75 08 83 46 14 40 81 7E 14 FF 05 00 00 7E 07
|
||||
C7 46 14 FF 05 00 00 8B 46 10 01 46 08 8B 46 14
|
||||
01 46 0C 8B 45 08 89 F7 83 C7 54 8B 46 68 C1 E0
|
||||
04 83 7E 4C 00 75 06 8D 74 05 D0 EB 04 8D 74 05
|
||||
A0 6A 04 59 F3 A5 C9 C3 CB 3C 43 00 E7 3C 43 00
|
||||
59 3E 43 00 BC 3E 43 00 CC CC CC CC CC CC CC CC
|
||||
CC CC CC CC CC C8 10 00 00 6A 41 5B 6A 05 59 8B
|
||||
75 08 0F B7 06 6A 08 5F 31 D2 F7 F7 6B D2 20 6B
|
||||
C0 10 89 55 F0 89 45 F4 83 C2 20 83 C0 10 89 55
|
||||
F8 89 45 FC 51 6A 08 8D 45 F0 50 6A 08 53 68 1C
|
||||
F9 48 00 E8 1D 84 FD FF 5B 5B 83 C4 0C 59 83 C3
|
||||
28 83 C6 02 E2 BC C9 C3 CC CC
|
||||
|
||||
0x40F9B5
|
||||
F4
|
||||
0x40FD8A
|
||||
E8 61 44 02 00 89 85 0C FE FF FF 83 A5 64 FF FF
|
||||
FF 00 83 A5 E4 FE FF FF 00 83 A5 9C FE FF FF 00
|
||||
68 20 20 20 00 E8 FC CA FF FF 89 45 C0 58
|
||||
0x40FF0D
|
||||
55
|
||||
0x40FF52
|
||||
10
|
||||
0x40FF8F
|
||||
2A
|
||||
0x40FF99
|
||||
20
|
||||
0x410141
|
||||
CF
|
||||
0x4102FB
|
||||
FF 75 C4 8D 85 FC FE FF FF 50 FF B5 0C FF FF FF
|
||||
6A 74 68 1C F9 48 00 E8 A9 C0 FF FF 83 C4 14 6A
|
||||
00 6A 00 E8 9D A8 FF FF 83 C4 08 FF B5 0C FE FF
|
||||
FF E8 2F 3C 02 00 83 C4 04 83 BD 9C FE FF FF 00
|
||||
74 0C 6A 08 6A 10 E8 EA A0 00 00 83 C4 04 E8 22
|
||||
20 00 00 FF 35 58 E4 49 00 E8 E7 AF FF FF 83 C4
|
||||
04 85 C0 0F 85 A0 FB FF FF EB 57 6A 00 E8 73 0B
|
||||
01 00 83 C4 04 FF 15 24 C1 48 00 89 85 E8 FE FF
|
||||
FF FF 15 24 C1 48 00 8B 8D E8 FE FF FF 81 C1 E8
|
||||
03 00 00 39 C8 73 28 6A 00 68 1C F9 48 00 E8 42
|
||||
C6 FF FF 83 C4 08 E8 CA 1F 00 00 FF 35 58 E4 49
|
||||
00 E8 8F AF FF FF 83 C4 04 85 C0 75 C4 EB 03 6A
|
||||
03 58 50 FF B5 0C FE FF FF E8 C2 0E 07 00 83 C4
|
||||
04 58 C9 C3 45 01 41 00 98 01 41 00 EB 01 41 00
|
||||
3E 02 41 00 8E 02 41 00 CC CC CC CC CC CC CC CC
|
||||
CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC
|
||||
CC CC CC CC CC
|
||||
|
||||
----------Specifications:
|
||||
|
||||
The hack reads the first 5 item numbers listed in data\hash.txt, and displays them on the title screen in order.
|
||||
The item numbers in data\hash.txt can be separated by any non-numerical character.
|
||||
If data\hash.txt does not exist, the title screen will display item 0 in all 5 slots.
|
||||
|
||||
The hack optimises NPCs 64 and 65's velocity and frame code.
|
||||
|
||||
004341F0 - load items from hash.txt
|
||||
00433F60 - render title screen items
|
||||
|
||||
----------Limitations:
|
||||
|
||||
If you enter item numbers in hash.txt over 65535, it will not work properly.
|
||||
If hash.txt is more than 31 bytes large, a buffer will overflow, and the game will likely crash. That said, due to the previous limitation, this should never happen.
|
||||
|
||||
----------Info:
|
||||
|
||||
This is version 1.2 of the "Titlescreen Hash Display" hack, created by zxin and commissioned by duncathan_salt.
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
; Reads version number from data\version.txt
|
||||
; The file must start with the version string in the format shown at the bottom of this file
|
||||
; Made by periwinkle
|
||||
|
||||
#define
|
||||
gDataPath=49E220
|
||||
gVersionString=48C2BC
|
||||
sprintf=481010
|
||||
fopen=480FFD
|
||||
rb=48C28C
|
||||
fread=480F55
|
||||
fclose=480E1B
|
||||
sscanf=4817E8
|
||||
call VirtualProtect=data ff 15 84 c0 48 00
|
||||
filePath=[ebp-114]
|
||||
bufchk=[ebp-10]
|
||||
tmp=[ebp-c]
|
||||
oldProtect=[ebp-8]
|
||||
fp=[ebp-4]
|
||||
v1=[ebp+8]
|
||||
v2=[ebp+c]
|
||||
v3=[ebp+10]
|
||||
v4=[ebp+14]
|
||||
#enddefine
|
||||
|
||||
offset 410990 ; GetCompileVersion
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
sub esp, 114
|
||||
mov eax, [498B20]
|
||||
mov bufchk, eax
|
||||
|
||||
; Get path to data\version.txt file
|
||||
push gDataPath
|
||||
push :VersionPath ; "%s\version.txt"
|
||||
lea edx, filePath
|
||||
push edx
|
||||
call sprintf
|
||||
add esp, c
|
||||
|
||||
; Open file
|
||||
push rb ; "rb"
|
||||
lea ecx, filePath
|
||||
push ecx
|
||||
call fopen
|
||||
add esp, 8
|
||||
test eax, eax
|
||||
jz :ReadVersion
|
||||
mov fp, eax
|
||||
|
||||
; Mark gVersionString as read/write (it's normally in a read-only segment)
|
||||
lea eax, oldProtect
|
||||
push eax
|
||||
push 4 ; PAGE_READWRITE
|
||||
push 40 ; Max size of gVersionString (including null character)
|
||||
push gVersionString
|
||||
call VirtualProtect
|
||||
test eax, eax
|
||||
jz :CloseFile
|
||||
|
||||
; Read contents of file into gVersionString
|
||||
push fp
|
||||
|
||||
push 3F ; count (excluding null character)
|
||||
push 1 ; size
|
||||
push gVersionString
|
||||
call fread
|
||||
add esp, 10
|
||||
mov byte [eax+gVersionString], 0 ; Write null terminator
|
||||
|
||||
; Restore previous protection status
|
||||
lea eax, tmp
|
||||
push eax
|
||||
push oldProtect
|
||||
push 40
|
||||
push gVersionString
|
||||
call VirtualProtect
|
||||
|
||||
:CloseFile
|
||||
push fp
|
||||
call fclose
|
||||
pop ecx
|
||||
|
||||
:ReadVersion
|
||||
; Parse the version string
|
||||
push v4
|
||||
push v3
|
||||
push v2
|
||||
push v1
|
||||
push :VersionString
|
||||
push gVersionString
|
||||
call sscanf
|
||||
add esp, 18
|
||||
|
||||
mov ecx, bufchk
|
||||
call 480DC1
|
||||
leave
|
||||
retn
|
||||
|
||||
:VersionPath
|
||||
data 25 73 5C 76 65 72 73 69 6F 6E 2E 74 78 74 00 00 ; "%s\version.txt"
|
||||
:VersionString
|
||||
data 76 25 64 2E 25 64 2E 25 64 2E 25 64 00 ; "v%d.%d.%d.%d"
|
||||
9
daily.sh
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
set -ev
|
||||
|
||||
if [ "$TRAVIS_EVENT_TYPE" != "cron" ]; then exit 0; fi
|
||||
|
||||
cd src
|
||||
love-release
|
||||
sudo xvfb-run -a --server-args="-screen 0 1024x768x24" love "releases/CaveStoryRandomizer.love" --daily
|
||||
cat daily.txt
|
||||
curl -H "Content-Type: application/json" -X POST -d @daily.txt "$WEBHOOK"
|
||||
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
1
pre-edited-cs/data/ArmsItem.tsc
Normal file
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
2
pre-edited-cs/data/Credit.tsc
Normal file
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
1
pre-edited-cs/data/Head.tsc
Normal file
BIN
pre_edited_cs/tweaked/data/mods/boss_rush/ItemImage.pbm → pre-edited-cs/data/ItemImage.bmp
Executable file → Normal file
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 134 B After Width: | Height: | Size: 134 B |
BIN
pre_edited_cs/tweaked/data/mods/boss_rush/MyChar.pbm → pre-edited-cs/data/MyChar.bmp
Executable file → Normal file
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 638 B After Width: | Height: | Size: 638 B |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |