This commit is contained in:
larzie 2024-12-25 14:23:13 +00:00 committed by GitHub
commit 9efec00113
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 322 additions and 266 deletions

View File

@ -1,6 +1,9 @@
name: Analyze name: Analyze
on: [push, pull_request] on:
push:
pull_request:
workflow_dispatch:
jobs: jobs:
decomplint-isle: decomplint-isle:
@ -15,16 +18,18 @@ jobs:
- LEGO1 - LEGO1
steps: steps:
- uses: actions/checkout@v4 - name: Checkout repository
uses: actions/checkout@v4
- uses: actions/setup-python@v5 - name: Setup Python
with: uses: actions/setup-python@v5
python-version: '3.12' with:
python-version: '3.13'
- name: Install python libraries - name: Setup Python modules
run: | run: |
pip install -r tools/requirements.txt pip install -r tools/requirements.txt
- name: Run decomplint.py - name: Run decomplint.py
run: | run: |
reccmp-decomplint ${{ matrix.who }} --module ${{ matrix.who }} --warnfail reccmp-decomplint ${{ matrix.who }} --module ${{ matrix.who }} --warnfail

View File

@ -1,6 +1,9 @@
name: Build name: Build
on: [push, pull_request] on:
push:
pull_request:
workflow_dispatch:
jobs: jobs:
fetch-deps: fetch-deps:
@ -17,12 +20,15 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
toolchain: toolchain:
- { name: 'MSVC', shell: 'sh', setup-cmake: true, setup-ninja: true, setup-msvc: true } - { name: 'MSVC', shell: 'sh', setup-cmake: true, setup-ninja: true, setup-msvc: true }
- { name: 'msys2 mingw32', shell: 'msys2 {0}', msystem: mingw32, msys-env: mingw-w64-i686, clang-tidy: true, werror: true } - { name: 'msys2 mingw32', shell: 'msys2 {0}', msystem: mingw32, msys-env: mingw-w64-i686, clang-tidy: true, werror: true }
- { name: 'msys2 clang32', shell: 'msys2 {0}', msystem: clang32, msys-env: mingw-w64-clang-i686, clang-tidy: true, werror: true, no-dx5-libs: true } - { name: 'msys2 clang32', shell: 'msys2 {0}', msystem: clang32, msys-env: mingw-w64-clang-i686, clang-tidy: true, werror: true, no-dx5-libs: true }
steps: steps:
- name: Set up MSYS2 - name: Checkout repository
uses: actions/checkout@v4
- name: Setup MSYS2
if: ${{ !!matrix.toolchain.msystem }} if: ${{ !!matrix.toolchain.msystem }}
uses: msys2/setup-msys2@v2 uses: msys2/setup-msys2@v2
with: with:
@ -33,21 +39,19 @@ jobs:
${{ matrix.toolchain.msys-env }}-ninja ${{ matrix.toolchain.msys-env }}-ninja
${{ matrix.toolchain.msys-env }}-clang-tools-extra ${{ matrix.toolchain.msys-env }}-clang-tools-extra
- name: Setup cmake - name: Setup CMake
if: matrix.toolchain.setup-cmake if: matrix.toolchain.setup-cmake
uses: jwlawson/actions-setup-cmake@v2 uses: jwlawson/actions-setup-cmake@v2
- name: Setup ninja - name: Setup ninja
if: matrix.toolchain.setup-ninja if: matrix.toolchain.setup-ninja
uses: ashutoshvarma/setup-ninja@master uses: larziwau/gha-setup-ninja@master
- name: Setup vcvars - name: Setup vcvars
if: matrix.toolchain.setup-msvc if: matrix.toolchain.setup-msvc
uses: ilammy/msvc-dev-cmd@v1 uses: ilammy/msvc-dev-cmd@v1
with: with:
arch: amd64_x86 # Use the 64-bit x64-native cross tools to build 32-bit x86 code arch: amd64_x86
- uses: actions/checkout@v4
- name: Build - name: Build
run: | run: |
@ -60,126 +64,129 @@ jobs:
cmake --build build -- -k0 cmake --build build -- -k0
build: build:
name: 'MSVC 4.20' name: MSVC 4.20
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- uses: actions/checkout@v4 - name: Checkout repository
uses: actions/checkout@v4
- uses: actions/checkout@v4 - name: Checkout MSVC repository
with: uses: actions/checkout@v4
repository: itsmattkc/msvc420 with:
path: msvc420 repository: itsmattkc/MSVC420
path: msvc420
- name: Setup cmake - name: Setup CMake
uses: jwlawson/actions-setup-cmake@v2 uses: jwlawson/actions-setup-cmake@v2
with: with:
# Use minimum supported version cmake-version: '3.31.x'
cmake-version: '3.15.x'
- name: Patch MSVC 4.2 - name: Patch MSVC
run: | run: |
tools/patch_c2.py msvc420/bin/C2.EXE tools/patch_c2.py msvc420/bin/C2.EXE
- name: Build - name: Build
shell: cmd shell: cmd
run: | run: |
call .\msvc420\bin\VCVARS32.BAT x86 call .\msvc420\bin\VCVARS32.BAT x86
cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo -G "NMake Makefiles" cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo -G "NMake Makefiles"
cmake --build build cmake --build build
- name: Upload Artifact - name: Upload artifact
uses: actions/upload-artifact@main uses: actions/upload-artifact@v4
with: with:
name: Win32 name: Win32
path: | path: |
build/CONFIG.EXE build/CONFIG.EXE
build/CONFIG.PDB build/CONFIG.PDB
build/ISLE.EXE build/ISLE.EXE
build/ISLE.PDB build/ISLE.PDB
build/LEGO1.DLL build/LEGO1.DLL
build/LEGO1.PDB build/LEGO1.PDB
compare: compare:
name: Compare with master name: Compare with master
needs: [build, fetch-deps] needs: [build, fetch-deps]
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- uses: actions/checkout@main - name: Checkout repository
uses: actions/checkout@v4
- uses: actions/setup-python@v5 - name: Setup Python
with: uses: actions/setup-python@v5
python-version: '3.12' with:
python-version: '3.13'
- uses: actions/download-artifact@main - name: Download artifact
with: uses: actions/download-artifact@v4
name: Win32 with:
path: build name: Win32
path: build
- name: Restore cached original binaries - name: Restore cached original binaries
id: cache-original-binaries id: cache-original-binaries
uses: actions/cache/restore@v4 uses: actions/cache/restore@v4
with: with:
enableCrossOsArchive: true enableCrossOsArchive: true
path: legobin path: legobin
key: legobin key: legobin
- name: Install python packages - name: Setup Python modules
shell: bash shell: bash
run: | run: |
pip install -r tools/requirements.txt pip install -r tools/requirements.txt
- name: Detect binaries - name: Detect binaries
run: | run: |
reccmp-project detect --what original --search-path legobin reccmp-project detect --what original --search-path legobin
reccmp-project detect --what recompiled --search-path build reccmp-project detect --what recompiled --search-path build
- name: Summarize Accuracy - name: Summarize accuracy
shell: bash shell: bash
run: | run: |
reccmp-reccmp -S CONFIGPROGRESS.SVG --svg-icon assets/config.png --target CONFIG | tee CONFIGPROGRESS.TXT reccmp-reccmp -S CONFIGPROGRESS.SVG --svg-icon assets/config.png --target CONFIG | tee CONFIGPROGRESS.TXT
reccmp-reccmp -S ISLEPROGRESS.SVG --svg-icon assets/isle.png --target ISLE | tee ISLEPROGRESS.TXT reccmp-reccmp -S ISLEPROGRESS.SVG --svg-icon assets/isle.png --target ISLE | tee ISLEPROGRESS.TXT
reccmp-reccmp -S LEGO1PROGRESS.SVG --svg-icon assets/lego1.png --target LEGO1 | tee LEGO1PROGRESS.TXT reccmp-reccmp -S LEGO1PROGRESS.SVG --svg-icon assets/lego1.png --target LEGO1 | tee LEGO1PROGRESS.TXT
- name: Compare Accuracy With Current Master - name: Compare accuracy with current master
shell: bash shell: bash
run: | run: |
# Compare with current master curl -fLSs -o CONFIGPROGRESS-OLD.TXT https://github.com/isledecomp/isle/releases/download/continuous/CONFIGPROGRESS.TXT || echo "" >CONFIGPROGRESS-OLD.TXT
curl -fLSs -o CONFIGPROGRESS-OLD.TXT https://github.com/isledecomp/isle/releases/download/continuous/CONFIGPROGRESS.TXT || echo "" >CONFIGPROGRESS-OLD.TXT curl -fLSs -o ISLEPROGRESS-OLD.TXT https://github.com/isledecomp/isle/releases/download/continuous/ISLEPROGRESS.TXT || echo "" >ISLEPROGRESS-OLD.TXT
curl -fLSs -o ISLEPROGRESS-OLD.TXT https://github.com/isledecomp/isle/releases/download/continuous/ISLEPROGRESS.TXT || echo "" >ISLEPROGRESS-OLD.TXT curl -fLSs -o LEGO1PROGRESS-OLD.TXT https://github.com/isledecomp/isle/releases/download/continuous/LEGO1PROGRESS.TXT || echo "" >LEGO1PROGRESS-OLD.TXT
curl -fLSs -o LEGO1PROGRESS-OLD.TXT https://github.com/isledecomp/isle/releases/download/continuous/LEGO1PROGRESS.TXT || echo "" >LEGO1PROGRESS-OLD.TXT
diff -u0 CONFIGPROGRESS-OLD.TXT CONFIGPROGRESS.TXT || true diff -u0 CONFIGPROGRESS-OLD.TXT CONFIGPROGRESS.TXT || true
diff -u0 ISLEPROGRESS-OLD.TXT ISLEPROGRESS.TXT || true diff -u0 ISLEPROGRESS-OLD.TXT ISLEPROGRESS.TXT || true
diff -u0 LEGO1PROGRESS-OLD.TXT LEGO1PROGRESS.TXT || true diff -u0 LEGO1PROGRESS-OLD.TXT LEGO1PROGRESS.TXT || true
- name: Test Exports - name: Test exports
shell: bash shell: bash
run: | run: |
reccmp-verexp --target LEGO1 reccmp-verexp --target LEGO1
- name: Check Vtables - name: Check vtables
shell: bash shell: bash
run: | run: |
reccmp-vtable --target CONFIG reccmp-vtable --target CONFIG
reccmp-vtable --target ISLE reccmp-vtable --target ISLE
reccmp-vtable --target LEGO1 reccmp-vtable --target LEGO1
- name: Check Variables - name: Check variables
shell: bash shell: bash
run: | run: |
reccmp-datacmp --target CONFIG reccmp-datacmp --target CONFIG
reccmp-datacmp --target ISLE reccmp-datacmp --target ISLE
reccmp-datacmp --target LEGO1 reccmp-datacmp --target LEGO1
- name: Upload Artifact - name: Upload artifact
uses: actions/upload-artifact@main uses: actions/upload-artifact@v4
with: with:
name: Accuracy Report name: Accuracy Report
path: | path: |
CONFIGPROGRESS.* CONFIGPROGRESS.*
ISLEPROGRESS.* ISLEPROGRESS.*
LEGO1PROGRESS.* LEGO1PROGRESS.*
upload: upload:
name: Upload artifacts name: Upload artifacts
@ -187,32 +194,35 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'isledecomp/isle' }} if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'isledecomp/isle' }}
steps: steps:
- uses: actions/checkout@v4 - name: Checkout uploadtool repository
with: uses: actions/checkout@v4
repository: probonopd/uploadtool with:
repository: probonopd/uploadtool
- uses: actions/download-artifact@main - name: Download build artifact
with: uses: actions/download-artifact@v4
name: Win32 with:
path: build name: Win32
path: build
- uses: actions/download-artifact@main - name: Download accuracy report artifact
with: uses: actions/download-artifact@v4
name: Accuracy Report with:
name: Accuracy Report
- name: Upload Continuous Release - name: Upload continuous release
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
UPLOAD_KEY: ${{ secrets.UPLOAD_KEY }} UPLOAD_KEY: ${{ secrets.UPLOAD_KEY }}
run: | run: |
./upload.sh \ ./upload.sh \
build/CONFIG.EXE \ build/CONFIG.EXE \
build/ISLE.EXE \ build/ISLE.EXE \
build/LEGO1.DLL \ build/LEGO1.DLL \
CONFIGPROGRESS.* \ CONFIGPROGRESS.* \
ISLEPROGRESS.* \ ISLEPROGRESS.* \
LEGO1PROGRESS.* LEGO1PROGRESS.*
curl -X POST -F key=$UPLOAD_KEY -F 'file=@CONFIGPROGRESS.SVG' https://legoisland.org/progress/ curl -X POST -F key=$UPLOAD_KEY -F 'file=@CONFIGPROGRESS.SVG' https://legoisland.org/progress/
curl -X POST -F key=$UPLOAD_KEY -F 'file=@ISLEPROGRESS.SVG' https://legoisland.org/progress/ curl -X POST -F key=$UPLOAD_KEY -F 'file=@ISLEPROGRESS.SVG' https://legoisland.org/progress/
curl -X POST -F key=$UPLOAD_KEY -F 'file=@LEGO1PROGRESS.SVG' https://legoisland.org/progress/ curl -X POST -F key=$UPLOAD_KEY -F 'file=@LEGO1PROGRESS.SVG' https://legoisland.org/progress/

View File

@ -1,6 +1,9 @@
name: Format name: Format
on: [push, pull_request] on:
push:
pull_request:
workflow_dispatch:
jobs: jobs:
clang-format: clang-format:
@ -8,12 +11,13 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - name: Checkout repository
uses: actions/checkout@v4
- name: Run clang-format - name: Run clang-format
run: | run: |
find CONFIG LEGO1 ISLE -iname '*.h' -o -iname '*.cpp' | xargs \ find CONFIG LEGO1 ISLE -iname '*.h' -o -iname '*.cpp' | xargs \
pipx run "clang-format>=17,<18" \ pipx run "clang-format>=17,<18" \
--style=file \ --style=file \
-i -i
git diff --exit-code git diff --exit-code

View File

@ -2,31 +2,31 @@ name: Download legobin
on: on:
workflow_call: workflow_call:
workflow_dispatch:
jobs: jobs:
fetch: fetch:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Restore cached original binaries
id: cache-original-binaries
uses: actions/cache/restore@v4
with:
enableCrossOsArchive: true
path: legobin
key: legobin
- name: Restore cached original binaries - name: Download original Island binaries
id: cache-original-binaries if: ${{ !steps.cache-original-binaries.outputs.cache-hit }}
uses: actions/cache/restore@v4 run: |
with: wget https://legoisland.org/download/CONFIG.EXE --directory-prefix=legobin
enableCrossOsArchive: true wget https://legoisland.org/download/ISLE.EXE --directory-prefix=legobin
path: legobin wget https://legoisland.org/download/LEGO1.DLL --directory-prefix=legobin
key: legobin
- name: Download original island binaries - name: Cache original binaries
if: ${{ !steps.cache-original-binaries.outputs.cache-hit }} if: ${{ !steps.cache-original-binaries.outputs.cache-hit }}
run: | uses: actions/cache/save@v4
wget https://legoisland.org/download/CONFIG.EXE --directory-prefix=legobin with:
wget https://legoisland.org/download/ISLE.EXE --directory-prefix=legobin enableCrossOsArchive: true
wget https://legoisland.org/download/LEGO1.DLL --directory-prefix=legobin path: legobin
key: legobin
- name: Cache original binaries
if: ${{ !steps.cache-original-binaries.outputs.cache-hit }}
uses: actions/cache/save@v4
with:
enableCrossOsArchive: true
path: legobin
key: legobin

View File

@ -1,6 +1,9 @@
name: Naming name: Naming
on: [push, pull_request] on:
push:
pull_request:
workflow_dispatch:
jobs: jobs:
ncc: ncc:
@ -8,40 +11,42 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - name: Checkout repository
uses: actions/checkout@v4
- name: Install LLVM and Clang - name: Setup LLVM and Clang
uses: KyleMayes/install-llvm-action@v2 uses: KyleMayes/install-llvm-action@v2
with: with:
version: '16' version: '16'
- uses: actions/setup-python@v5 - name: Setup Python
with: uses: actions/setup-python@v5
python-version: '3.12' with:
python-version: '3.13'
- name: Install python libraries - name: Setup Python modules
run: | run: |
pip install -r tools/requirements.txt pip install -r tools/requirements.txt
- name: Run ncc - name: Run ncc
run: | run: |
action_headers=$(find LEGO1/lego/legoomni/include/actions \ action_headers=$(find LEGO1/lego/legoomni/include/actions \
-name '*.h' -print0 | xargs -0 echo) -name '*.h' -print0 | xargs -0 echo)
python3 tools/ncc/ncc.py \ python3 tools/ncc/ncc.py \
--clang-lib ${{ env.LLVM_PATH }}/lib/libclang.so \ --clang-lib ${{ env.LLVM_PATH }}/lib/libclang.so \
--recurse \ --recurse \
--style tools/ncc/ncc.style \ --style tools/ncc/ncc.style \
--skip tools/ncc/skip.yml \ --skip tools/ncc/skip.yml \
--definition WINAPI FAR BOOL CALLBACK HWND__=HWND \ --definition WINAPI FAR BOOL CALLBACK HWND__=HWND \
--include \ --include \
util \ util \
LEGO1 \ LEGO1 \
LEGO1/omni/include \ LEGO1/omni/include \
LEGO1/lego/legoomni/include \ LEGO1/lego/legoomni/include \
LEGO1/lego/sources \ LEGO1/lego/sources \
--exclude \ --exclude \
LEGO1/omni/include/flic.h \ LEGO1/omni/include/flic.h \
LEGO1/omni/src/video/flic.cpp \ LEGO1/omni/src/video/flic.cpp \
$action_headers \ $action_headers \
--path LEGO1/omni LEGO1/lego/legoomni --path LEGO1/omni LEGO1/lego/legoomni

View File

@ -2,62 +2,77 @@
## Important Note ## Important Note
While we're thrilled that there is so much interest in reverse engineering LEGO Island and are happy to accept contributions from anyone who would like to help progress us further to our goal of a complete codebase, proposed changes to this repository must adhere to a certain degree of engineering quality. While the established contributors here are more than happy to provide code reviews and constructive criticism, it is not their job to teach potential contributors C++ or decompilation fundamentals. As a project that is largely an artifact of the free time of its contributors, the more of that (often scarce) resource that can be dedicated to efficient work, the faster the decompilation will progress. Unfortunately, this results in well-intentioned but poorly constructed contributions actually hurting progress in the long-term. While we are greatly appreciative of the sentiment, if you aren't very confident in your decompilation abilities, it is generally in the project's best interest that you return when you have a better grasp over the process. We are thrilled about the interest in reverse engineering LEGO Island and welcome contributions from anyone eager to advance the project. However, proposed changes must meet a certain standard of engineering quality. While our established contributors are happy to provide code reviews and constructive feedback, they cannot teach contributors C++ or decompilation fundamentals.
Generally, decompilation is a fairly advanced skill. Depending on your current proficiency with C/C++ and x86 assembly, it could take you months or even years to learn the skills necessary to do it adequately. If you're still interested in learning, [part 1 of the decompilation vlog](https://www.youtube.com/watch?v=MToTEqoVv3I) covers the overall process and should give you a starting point that you can dive in from. Once again, please make yourself familiar with this process before attempting to contribute code to this project. This project depends on contributors' free time, a resource often in short supply. Poorly constructed contributions, though well-intentioned, can hinder progress in the long term. If you're not confident in your decompilation abilities, we recommend returning once you have a stronger grasp of the process.
Decompilation is an advanced skill. Depending on your proficiency in C/C++ and x86 assembly, it might take months or even years to develop the necessary skills. For beginners, [Part 1 of the decompilation vlog](https://youtu.be/MToTEqoVv3I) provides an excellent introduction. Please familiarize yourself with this process before contributing code.
## Ghidra Server ## Ghidra Server
For documenting the original binaries and generating pseudocode that we decompile with, we primarily use [Ghidra](https://ghidra-sre.org/) (it's free and open source). To help with collaboration, we have a shared Ghidra repository with all of our current work. You are free to check it out and mess around with it locally, however to prevent sabotage, you will need to request permission before you can push your changes back to the server (ask in the Matrix room). We use [Ghidra](https://ghidra-sre.org/) (free and open source) to document the original binaries and generate pseudocode for decompilation. Collaboration is facilitated through a shared Ghidra repository. You are welcome to explore it locally, but push access requires permission to prevent sabotage. Contact us in the Matrix room to request access.
To access the Ghidra repository, use the following details: Repository details:
- **Address:** `server.mattkc.com`
- **Port:** `13100`
- Address: `server.mattkc.com` > **Note:** Much of the information on the Ghidra server is outdated. The source code in this repository is the most accurate "source of truth" and should be referenced whenever possible.
- Port: `13100`
**Please note that at the time of writing, much of the information found on the Ghidra server is severely outdated**. Generally, the source code found in this repository represents the latest "source of truth" and should be referenced whenever possible.
## General Guidelines ## General Guidelines
If you feel fit to contribute, feel free to create a pull request! Someone will review and merge it (or provide feedback) as soon as possible. If you're ready to contribute, feel free to create a pull request (PR). We will review and merge it—or provide feedback—as soon as possible.
Please keep your pull requests small and understandable; you may be able to shoot ahead and make a lot of progress in a short amount of time, but this is a collaborative project, so you must allow others to catch up and follow along. Large pull requests become significantly more unwieldy to review, and as such make it exponentially more likely for a mistake or error to go undetected. They also make it harder to merge other pull requests because the more files you modify, the more likely it is for a merge conflict to occur. A general guideline is to keep submissions limited to one class at a time. Sometimes two or more classes may be too interlinked for this to be feasible, so this is not a hard rule, however if your PR is starting to modify more than 10 or so files, it's probably getting too big. ### Pull Request Tips:
- Keep PRs small and understandable to facilitate collaboration and reduce errors.
- Large PRs (modifying more than ~10 files) increase the likelihood of merge conflicts and errors.
- Aim to focus on one class per PR. Interlinked classes may require exceptions but proceed cautiously.
This repository currently has only one goal: accuracy to the original executables. We are byte/instruction matching as much as possible, which means the priority is making the original compiler (MSVC 4.20) produce code that matches the original game. As such, modernizations and bug fixes will probably be rejected for the time being. ### Project Goals:
This repository's sole objective is **accuracy to the original executables**.
- We prioritize byte/instruction matching the original compiler (MSVC 4.20).
- Modernizations or bug fixes will likely be rejected for now.
## Overview ## Overview
* [`3rdparty`](/3rdparty): Contains code obtained from third parties, not including Mindscape. Generally, these are libraries that have been placed in the public domain or are freely available on the web. As these are unaltered files, our style guide (see below) does not apply. - **[`3rdparty`](/3rdparty):** Libraries from third parties (excluding Mindscape). These are public domain or freely available files. Our style guide does not apply here.
* [`CONFIG`](/CONFIG): Decompilation of `CONFIG.EXE`. It depends on some code in `LEGO1`. - **[`CONFIG`](/CONFIG):** Decompilation of `CONFIG.EXE`, dependent on `LEGO1` code.
* [`ISLE`](/ISLE): Decompilation of `ISLE.EXE`. It depends on some code in `LEGO1`. - **[`ISLE`](/ISLE):** Decompilation of `ISLE.EXE`, dependent on `LEGO1` code.
* [`LEGO1`](/LEGO1): Decompilation of `LEGO1.DLL`. This folder contains code from Mindscape's custom in-house engine called **Omni** (file pattern: `mx*`), the LEGO Island-specific extensions for Omni and the game's code (file pattern: `lego*`) as well as several utility libraries developed by Mindscape. - **[`LEGO1`](/LEGO1):** Decompilation of `LEGO1.DLL`, containing:
* [`tools`](/tools): A set of tools aiding in the decompilation effort. - **Omni:** Mindscape's custom in-house engine (`mx*` files).
* [`util`](/util): Utility headers aiding in the decompilation effort. - **LEGO-specific code:** Extensions and game-specific libraries (`lego*` files).
- **Utility libraries** developed by Mindscape.
- **[`tools`](/tools):** Aiding tools for decompilation.
- **[`util`](/util):** Utility headers supporting the effort.
## Tooling ## Tooling
Please make yourself familiar with the [available tooling and annotations](/tools/README.md). These are generally required to contribute to the project. Refer to the [tooling and annotations guide](/tools/README.md). Familiarity with these tools is essential for contributing.
## Notes on MSVC 4.20 ## Notes on MSVC 4.20
As outlined in the [`README`](/README.md), Microsoft Visual C++ 4.20 is the compiler we use to build the game. As outlined in the [`README`](/README.md), we use Microsoft Visual C++ 4.20 to compile the game.
One important aspect to know about this compiler in the context of the decompilation project is that the assembly code generation is somewhat erratic. We call this peculiarity "compiler randomness" or entropy. In essence, what it comes down to is that changes to the code base, for instance in a header, can pseudo-randomly affect the code generation of functions in compilation units that include this header, even if the changes are completely unrelated to those functions. For example, by adding an extra (unused) inline function or an enum declaration in a header, the code in some functions may unexpectedly wind up looking different and our main tool, [`reccmp`](/tools/README.md), will report either a (significantly) reduced or increased accuracy for those functions. This issue roughly affects around ~5% of all decompiled functions. ### Compiler Randomness
- The compiler's code generation can behave erratically, introducing "compiler randomness" or entropy.
- Changes in headers, even unrelated ones (e.g., adding an unused inline function), may alter unrelated function outputs.
- This issue affects ~5% of decompiled functions, complicating efforts to achieve 100% matching binaries.
We are currently unaware of the exact nature of this phenomenon. Unfortunately it represents a significant obstacle in our effort to achieve 100% matching binaries. If you or anyone you know has knowledge about the compiler internals that lead to the described observations, please contact us. If you have insights into this phenomenon, please contact us.
## Code Style ## Code Style
In general, we're not exhaustively strict about coding style, but there are some preferable guidelines to follow that have been adopted from what we know about the original codebase:
### Formatting ### Formatting
We use:
- [clang-format](https://clang.llvm.org/docs/ClangFormat.html) and [clang-tidy](https://clang.llvm.org/extra/clang-tidy/) with configuration files replicating the original formatting.
- Required `clang` version: `18.x`.
We are currently using [clang-format](https://clang.llvm.org/docs/ClangFormat.html) and [clang-tidy](https://clang.llvm.org/extra/clang-tidy/) with configuration files that aim to replicate the code formatting employed by the original developers. There are [integrations](https://clang.llvm.org/docs/ClangFormat.html#vim-integration) available for most editors and IDEs. The required `clang` toolchain version is `18.x`. ### Naming Conventions
We use a customized version of [ncc](https://github.com/nithinn/ncc) to replicate original naming conventions.
### Naming conventions - Required `clang` version: `16.x`.
- Refer to the [ncc tool guide](/tools/ncc) and [GitHub action](/.github/workflows/naming.yml) for details.
We are currently using a customized version of [ncc](https://github.com/nithinn/ncc) with a configuration file that aims to replicate the naming conventions employed by the original developers. `ncc` requires Clang `16.x`; please refer to the [tool](/tools/ncc) and the [GitHub action](/.github/workflows/naming.yml) for guidance.
## Questions? ## Questions?
For any further questions, feel free to ask in either the [Matrix chatroom](https://matrix.to/#/#isledecomp:matrix.org) or on the [forum](https://forum.mattkc.com/viewforum.php?f=1). For further questions, reach out via:
- [Matrix chatroom](https://matrix.to/#/#isledecomp:matrix.org)
- [Forum](https://forum.mattkc.com/viewforum.php?f=1)

View File

@ -2,66 +2,83 @@
[Development Vlog](https://www.youtube.com/playlist?list=PLbpl-gZkNl2COf_bB6cfgTapD5WduAfPz) | [Contributing](/CONTRIBUTING.md) | [Matrix](https://matrix.to/#/#isledecomp:matrix.org) | [Forums](https://forum.mattkc.com/viewforum.php?f=1) | [Patreon](https://www.patreon.com/mattkc) [Development Vlog](https://www.youtube.com/playlist?list=PLbpl-gZkNl2COf_bB6cfgTapD5WduAfPz) | [Contributing](/CONTRIBUTING.md) | [Matrix](https://matrix.to/#/#isledecomp:matrix.org) | [Forums](https://forum.mattkc.com/viewforum.php?f=1) | [Patreon](https://www.patreon.com/mattkc)
This is a functionally complete decompilation of LEGO Island (Version 1.1, English). It aims to be as accurate as possible, matching the recompiled instructions to the original machine code as much as possible. The goal is to provide a workable codebase that can be modified, improved, and ported to other platforms later on. This is a functionally complete decompilation of **LEGO Island** (Version 1.1, English). The aim is to match the recompiled instructions closely to the original machine code. The goal is to provide a workable codebase that can be modified, improved, and ported to other platforms in the future.
## Status ## Status
<img src="https://legoisland.org/progress/ISLEPROGRESS.SVG" width="50%"><img src="https://legoisland.org/progress/LEGO1PROGRESS.SVG" width="50%"> <img src="https://legoisland.org/progress/ISLEPROGRESS.SVG" width="50%"><img src="https://legoisland.org/progress/LEGO1PROGRESS.SVG" width="50%">
Both `ISLE.EXE` and `LEGO1.DLL` are completely decompiled and, to the best of our knowledge, are functionally identical to the originals. However, work is still ongoing to improve the accuracy, naming, documentation, and structure of the source code. While there may still be unresolved bugs that are not present in retail, the game should be fully playable with the binaries derived from this source code. Both `ISLE.EXE` and `LEGO1.DLL` are fully decompiled and are functionally identical to the original executables, as far as we know. However, there is ongoing work to improve the accuracy, naming, documentation, and structure of the source code. The game should be fully playable with the binaries derived from this source code, though some unresolved bugs may still exist.
Due to various complexities with regard to the compiler, these binaries are not a byte-for-byte match of the original executables. We remain hopeful that this can be resolved at some point. Due to complications with the compiler, the binaries are not a byte-for-byte match of the original executables, but we are hopeful that this will be resolved in the future.
## Building ## Building
This project uses the [CMake](https://cmake.org/) build system, which allows for a high degree of versatility regarding compilers and development environments. For the most accurate results, Microsoft Visual C++ 4.20 (the same compiler used to build the original game) is recommended. Since we're trying to match the output of this code to the original executables as closely as possible, all contributions will be graded with the output of this compiler. This project uses the [CMake](https://cmake.org/) build system, allowing compatibility with various compilers and development environments. For the most accurate results, **Microsoft Visual C++ 4.20** (the compiler used to build the original game) is recommended. All contributions will be evaluated based on the output from this compiler to maintain accuracy.
These instructions describe how to compile the repository using Visual C++ 4.2 to generate highly-accurate binaries that match the original retail functions. While other compilers may be used, doing so is at your own risk, and is not covered in this guide.
These instructions will outline how to compile this repository using Visual C++ 4.2 into highly-accurate binaries where the majority of functions are instruction-matching with retail. If you wish, you can try using other compilers, but this is at your own risk and won't be covered in this guide. ### Prerequisites
#### Prerequisites
You will need the following software installed: You will need the following software installed:
- Microsoft Visual C++ 4.2. This can be found on many abandonware sites, but the installer can be a little iffy on modern versions of Windows. For convenience, a [portable version](https://github.com/itsmattkc/msvc420) is available that can be downloaded and used quickly instead. - **Microsoft Visual C++ 4.2**: Available from many abandonware sites. A [portable version](https://github.com/itsmattkc/msvc420) is also available for easier setup.
- [CMake](https://cmake.org/). A copy is often included with the "Desktop development with C++" workload in newer versions of Visual Studio; however, it can also be installed as a standalone app. - **[CMake](https://cmake.org/)**: CMake is typically bundled with the "Desktop development with C++" workload in newer versions of Visual Studio but can also be installed separately.
#### Compiling ### Compiling
1. Open a Command Prompt (`cmd`). 1. Open a **Command Prompt** (`cmd`).
1. From Visual C++ 4.2, run `BIN/VCVARS32.BAT x86` to populate the path and other environment variables for compiling with MSVC. 2. From Visual C++ 4.2, run `BIN/VCVARS32.BAT x86` to set up the environment variables needed for compiling with MSVC.
1. Make a folder for compiled objects to go, such as a `build` folder inside the source repository (the folder you cloned/downloaded to). 3. Create a folder for the compiled objects, e.g., a `build` folder inside the source repository (the folder you cloned/downloaded).
1. In your Command Prompt, `cd` to the build folder. 4. In the Command Prompt, `cd` into the build folder.
1. Configure the project with CMake by running: 5. Configure the project with CMake by running:
```
cmake <path-to-source> -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo
```
- **Visual C++ 4.2 has issues with paths containing spaces**. If you get configure or build errors, make sure neither CMake, the repository, nor Visual C++ 4.2 is in a path that contains spaces.
- Replace `<path-to-source>` with the source repository. This can be `..` if your build folder is inside the source repository.
- `RelWithDebInfo` is recommended because it will produce debug symbols useful for further decompilation work. However, you can change this to `Release` if you don't need them. `Debug` builds are not recommended because they are unlikely to be compatible with the retail `LEGO1.DLL`, which is currently the only way to use this decompilation for gameplay.
- `NMake Makefiles` is most recommended because it will be immediately compatible with Visual C++ 4.2. For faster builds, you can use `Ninja` (if you have it installed), however due to limitations in Visual C++ 4.2, you can only build `Release` builds this way (debug symbols cannot be generated with `Ninja`).
1. Build the project by running `nmake` or `cmake --build <build-folder>`
1. When this is done, there should be a recompiled `ISLE.EXE` and `LEGO1.DLL` in the build folder.
1. Note that `nmake` must be run twice under certain conditions, so it is advisable to always (re-)compile using `nmake && nmake`.
If you have a CMake-compatible IDE, it should be pretty straightforward to use this repository, as long as you can use `VCVARS32.BAT` and set the generator to `NMake Makefiles`. ```bash
cmake <path-to-source> -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo
```
- **Note**: Visual C++ 4.2 has issues with paths containing spaces. If you experience configure or build errors, ensure that CMake, the repository, and Visual C++ 4.2 are not located in a directory with spaces.
- Replace `<path-to-source>` with the path to your source repository (you can use `..` if the build folder is inside the source repository).
- `RelWithDebInfo` is recommended as it includes debug symbols useful for further decompilation. You can switch to `Release` if you do not need debug symbols. Avoid using `Debug` builds as they may not be compatible with the retail `LEGO1.DLL`.
- `NMake Makefiles` is preferred for compatibility with Visual C++ 4.2. You can use `Ninja` for faster builds, but it limits you to only `Release` builds and will not generate debug symbols.
6. Build the project by running either `nmake` or `cmake --build <build-folder>`.
7. After the build process completes, `ISLE.EXE` and `LEGO1.DLL` will be available in the build folder.
8. **Important**: Run `nmake && nmake` twice under certain conditions to ensure proper recompilation.
If you have a CMake-compatible IDE, using it should be straightforward as long as you can execute `VCVARS32.BAT` and set the generator to `NMake Makefiles`.
## Usage ## Usage
Simply place the compiled `ISLE.EXE` and `LEGO1.DLL` into LEGO Island's install folder (usually `C:\Program Files\LEGO Island` or `C:\Program Files (x86)\LEGO Island`). Alternatively, LEGO Island can run from any directory as long as `ISLE.EXE` and `LEGO1.DLL` are in the same directory, and the registry keys (usually `HKEY_LOCAL_MACHINE\Software\Mindscape\LEGO Island` or `HKEY_LOCAL_MACHINE\Software\Wow6432Node\Mindscape\LEGO Island`) point to the correct location for the asset files. To use the compiled executables:
1. Place the compiled `ISLE.EXE` and `LEGO1.DLL` into LEGO Island's installation folder (typically found at `C:\Program Files\LEGO Island` or `C:\Program Files (x86)\LEGO Island`).
2. Alternatively, LEGO Island can run from any directory, provided both `ISLE.EXE` and `LEGO1.DLL` are in the same directory, and the registry keys (usually located at `HKEY_LOCAL_MACHINE\Software\Mindscape\LEGO Island` or `HKEY_LOCAL_MACHINE\Software\Wow6432Node\Mindscape\LEGO Island`) point to the correct asset file location.
## Contributing ## Contributing
If you're interested in helping or contributing to this project, check out the [CONTRIBUTING](/CONTRIBUTING.md) page. If you're interested in contributing to this project, please refer to the [CONTRIBUTING](/CONTRIBUTING.md) page.
## Additional Information ## Additional Information
### Which version of LEGO Island do I have? ### Which version of LEGO Island do I have?
Right click on `LEGO1.DLL`, select `Properties`, and switch to the `Details` tab. Under `Version` you should either see `1.0.0.0` (1.0) or `1.1.0.0` (1.1). Additionally, you can look at the game disc files; 1.0's files will all say August 8, 1997, and 1.1's files will all say September 8, 1997. Version 1.1 is by far the most common, especially if you're not using the English or Japanese versions, so that's most likely the version you have. To check your version of LEGO Island:
Please note that some localized versions of LEGO Island were recompiled with small changes despite maintaining a version number parallel with other versions; this decompilation specifically targets the English release of version 1.1 of LEGO Island. You can verify you have the correct version using the checksums below: 1. Right-click on `LEGO1.DLL`, select **Properties**, and go to the **Details** tab. You should see either:
- `1.0.0.0` (for version 1.0), or
- `1.1.0.0` (for version 1.1).
* ISLE.EXE `md5: f6da12249e03eed1c74810cd23beb9f5` 2. You can also check the game disc files:
* LEGO1.DLL `md5: 4e2f6d969ea2ef8655ba3fc221a0c8fe` - Version 1.0 files will be dated **August 8, 1997**.
* CONFIG.EXE `md5: 92d958a64a273662c591c88b09100f4a` - Version 1.1 files will be dated **September 8, 1997**.
Version 1.1 is the most common, especially if you're not using the English or Japanese versions.
Please note, some localized versions of LEGO Island were recompiled with small changes, even though they share the same version number. This decompilation targets the **English release of version 1.1** of LEGO Island.
You can verify that you have the correct version by checking the following checksums:
- **ISLE.EXE**: `md5: f6da12249e03eed1c74810cd23beb9f5`
- **LEGO1.DLL**: `md5: 4e2f6d969ea2ef8655ba3fc221a0c8fe`
- **CONFIG.EXE**: `md5: 92d958a64a273662c591c88b09100f4a`