Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
CherryDT committed May 28, 2021
0 parents commit 0b14831
Show file tree
Hide file tree
Showing 76 changed files with 12,589 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*~

dyndemo/
htmlhelp/
docs/

36 changes: 36 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
Copyright (C) 2006-2021, David "Cherry" Trapp
All rights reserved.

1. Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the conditions laid out in the
following paragraphs are met.
2. Redistributions of source code (if available) must retain the above
copyright notice, this list of conditions and the following disclaimer.
3. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3.1. In case this software is redistributed in binary form inside of a
executable or library file belonging to Third Parties and/or
including modifications done by Third Parties (or done by the Author
in Third Parties' names), any license restrictions imposed by the
Third Parties which disallow modification and/or redistribution remain
valid and have to be adhered, overriding the rights described in
paragraph 1 of this license. This does not give the Third Parties
the right to claim ownership of those parts of the software which
were developed by the Author, nor does it affect the remaining
parts of this license.
4. All advertising materials by Third Parties mentioning features or use
of this software must display the following acknowledgement (unless
agreed otherwise through written notice):
This product includes software developed by David "Cherry" Trapp.

DISCLAIMER:
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
103 changes: 103 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# DynRPG - The RPG Maker 2003 Plugin SDK

**by David “Cherry” Trapp** - http://cherrytree.at/dynrpg - [email protected]

For an explanation of what this is and how to use it, or to **download a release**, check [its **website**](http://cherrytree.at/dynrpg).

This repository houses the full source code of DynRPG. If you are an end-user, get the release linked above instead.

## Directory structure

* `patch`: Contains the source code of the RPG_RT patch (written in assembly).
* `sdk`: Contains the header files and documentation of the DynRPG SDK (written in C++).
* `library`: Contains the source code of the DynRPG library (written in C++).
* `loader`: Contains the source code of the loader DLL (written in FreeBasic).
* `patcher`: Contains the source code of the patcher tool (written in FreeBasic).
* `dyndemo`: Will contain an RM2k3 project as test environment for the patch and loader, will contain the patched RPG_RT and the loader binary.
* `htmlhelp`: Will contain the HTML Help Compiler.
* `docs`: Will contain HTML docs.

## Build instructions

### Patch

#### Prerequisites

* Create an RPG Maker 2003 v1.08 project in a new folder `dyndemo`. You will test the patch and its functions here. The base version of the RPG_RT.exe can be found [here](https://cherryshare.at/f/maVT0s/RPG_RT.exe).
* Install [OllyDbg v1.10](http://ollydbg.de/odbg110.zip) and the [MUltimate Assembler](https://rammichael.com/multimate-assembler) plugin. Also check out [this answer](https://stackoverflow.com/a/13673957/1871033) in case you run into a problem with “Single-step event at ntdll” events. Add `0EEDFADE` to the allowed exceptions list to avoid breaking unnecessarily (for example when pressing F12).

#### Build

1. Load `dyndemo\RPG_RT.exe` into OllyDbg. You can specify command line arguments `TestPlay ShowTitle Window` for easier testing. If you have already loaded it and worked on it before, make sure to rewind it using Ctrl+F2 before saving changes (because further changes may have been made at runtime which you don’t want to include in the patch).
2. Press Ctrl+M to open MUltimate Assembler.
3. If you do this for the first time, right-click the tab bar and use the “Load from file…” option to load `patch\patch.asm`.
4. Click “Assemble” to apply the patch.
5. Make sure you are in the code segment - if not, press Ctrl+G and enter `401000`.
6. Right-click assembly code in the CPU window and select “Copy to executable” => “All modifications”.
7. Right-click the file window contents and select “Save file”.
8. Save to `RPG_RT2.exe`.

This will create a patched RPG_RT binary `dyndemo\RPG_RT2.exe`.

### Loader

#### Prerequisites

* Install [FreeBasic](https://www.freebasic.net/). Known working version is 1.03.0 but newer versions may work as well.
* Install [FBEdit](https://github.com/CherryDT/FbEditMOD/) to open the `.fbp` project files.
* Test project in `dyndemo` must exist (see patch building prerequisites above).

#### Build

1. Open `loader\dynloader.fbp` in FBEdit.
2. Select target `Windows dll` and hit F5 to compile.

This will create a loader DLL`dyndemo\dynloader.dll`.

### Library

#### Prerequisites

* Install MinGW with [GCC 5.3.0](https://sourceforge.net/projects/mingw/files/MinGW/Base/gcc/Version5/gcc-5.3.0-3/). Using a different version may require tweaks to compiler flags and/or modifications of `__asm` statements to work properly!
* Install [CodeBlocks](https://www.codeblocks.org/downloads/) (10.05 is known to work) and make sure it is configured to use the correct GCC version.

#### Build

1. Open `library\DynRPG.cbp` in CodeBlocks.
2. Select target `Release` and Ctrl+F9 to compile.

This will create a static library `sdk\lib\libDynRPG.a`.

**Note:** To build plugins using the DynRPG development environment, all you need to do is adding `(DynRPG repo path)\sdk\include` to your include search paths and `(DynRPG repo path)\sdk\lib` to your library search paths in the plugin project. If you then set the build output as `(DynRPG repo path)\dyndemo\DynPlugins\your_plugin.dll`, you can immediately test the plugin together with the dev version of DynRPG.

### Patcher

#### Prerequisites

* Install [FreeBasic](https://www.freebasic.net/). Known working version is 1.03.0 but newer versions may work as well.
* Install [FBEdit](https://github.com/CherryDT/FbEditMOD/) to open the `.fbp` project files.
* Unpatched file `dyndemo\RPG_RT.exe`, patched file `dyndemo\RPG_RT2.exe` and loader `dyndemo\dynloader.dll` must exist (see instructions to build the patch and the loader above).

#### Build

1. Open a command prompt and go to directory `patcher`.
2. Run `hpdpa dynrpg.txt` to create `dynrpg.hpd`.
3. Open `patcher\dynrpg_patcher.fbp` in FBEdit.
4. Select target `Windows GUI` and hit F5 to compile.

This will create a patcher binary `patcher\dynrpg_patcher.exe`.

### Documentation

#### Prerequisites

* Install [Doxygen](https://www.doxygen.nl/download.html), but get [version 1.7.6.1](https://sourceforge.net/projects/doxygen/files/rel-1.7.6.1/) - there is no guarantee newer versions are compatible.
* Install [HTML Help Compiler](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/htmlhelp/microsoft-html-help-downloads?redirectedfrom=MSDN) into a new directory `htmlhelp`.

#### Build

* Open a command prompt and go to directory `sdk\include\DynRPG`.
* Run `doxygen doxygen.cfg`.

This will create HTML docs in `docs\html` and a CHM file in `sdk\dynrpg.chm`.

8 changes: 8 additions & 0 deletions library/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
obj/
libDynRPG.a
*.dll.a
*.o

*.depends
*.layout

50 changes: 50 additions & 0 deletions library/Actor.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#define DYNRPG_STATIC
#include "DynRPG.h"

namespace RPG {
std::string Actor::getDegree() {
if(degree.s_str() == "\x01") return dbActors[id]->degree;
return degree;
}

std::string Actor::getCharsetFilename() {
if(charsetFilename.s_str() == "") return dbActors[id]->charsetFilename;
return charsetFilename;
}

int Actor::getCharsetId() {
if(charsetFilename.s_str() == "") return dbActors[id]->charsetId;
return charsetId;
}

int Actor::getCharsetTransparency() {
if(charsetFilename.s_str() == "") return dbActors[id]->charsetTransparent ? 3 : 0;
return charsetTransparency;
}

std::string Actor::getFacesetFilename() {
if(facesetFilename.s_str() == "") return dbActors[id]->facesetFilename;
return facesetFilename;
}

int Actor::getFacesetId() {
if(facesetFilename.s_str() == "") return dbActors[id]->facesetId;
return facesetId;
}

int Actor::getBattleGraphicId() {
if(battleGraphicId == 0) return dbActors[id]->battleGraphicId;
return battleGraphicId;
}

int Actor::getBattleCommand(int index) {
if(!customBattleCommands) return dbActors[id]->battleCommands[index];
return battleCommands[index];
}

Actor *Actor::partyMember(int index) {
Actor *ret = NULL;
asm volatile("call *%%esi" : "=a" (ret), "=d" (_edx) : "S" (0x4A6014), "a" (**(void ***)0x4CDB74), "d" (index) : "ecx", "cc", "memory"); // GetPartyMember
return ret;
}
}
84 changes: 84 additions & 0 deletions library/Battler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#define DYNRPG_STATIC
#include "DynRPG.h"

namespace RPG {
std::string Battler::getName() {
DStringPtr s;
asm volatile("call *%%esi" : "=a" (_eax), "=d" (_edx) : "S" (vTable[9]), "a" (this), "d" (&s) : "ecx", "cc", "memory"); // GetMaxHP
return s;
}

int Battler::getMaxHp() {
int ret;
asm volatile("call *%%esi" : "=a" (ret) : "S" (vTable[10]), "a" (this) : "edx", "ecx", "cc", "memory"); // GetMaxHP
return ret;
}

int Battler::getMaxMp() {
int ret;
asm volatile("call *%%esi" : "=a" (ret) : "S" (vTable[11]), "a" (this) : "edx", "ecx", "cc", "memory"); // GetMaxMP
return ret;
}

int Battler::getAttack() {
int ret;
asm volatile("call *%%esi" : "=a" (ret) : "S" (0x4BFB28), "a" (this) : "edx", "ecx", "cc", "memory"); // GetATK
return ret;
}

int Battler::getDefense() {
int ret;
asm volatile("call *%%esi" : "=a" (ret) : "S" (0x4BFBF4), "a" (this) : "edx", "ecx", "cc", "memory"); // GetDEF
return ret;
}

int Battler::getIntelligence() {
int ret;
asm volatile("call *%%esi" : "=a" (ret) : "S" (0x4BFCC0), "a" (this) : "edx", "ecx", "cc", "memory"); // GetINT
return ret;
}

int Battler::getAgility() {
int ret;
asm volatile("call *%%esi" : "=a" (ret) : "S" (0x4BFD5C), "a" (this) : "edx", "ecx", "cc", "memory"); // GetAGI
return ret;
}

void Battler::setRow(Row newRow) {
rowAlt = newRow;
row = newRow;
}

void Battler::damagePopup(int number, int color) {
damagePopupTimer = DPT_START;
asm volatile("call *%%esi" : "=a" (_eax), "=d" (_edx), "=c" (_ecx) : "S" (0x4BF5E4), "a" (this), "d" (number), "c" (color) : "cc", "memory"); // ShowDamage
}

void Battler::damagePopup(std::string text) {
damagePopupTimer = DPT_START;
DStringPtr s(text);
asm volatile("call *%%esi" : "=a" (_eax), "=d" (_edx) : "S" (0x4BF550), "a" (this), "d" (s.str) : "ecx", "cc", "memory");
}

bool Battler::isMonster() {
return vTable == reinterpret_cast<void **>(0x4BD35C);
}

void Battler::flash(int r, int g, int b, int intensity, int duration) {
flashR = r;
flashG = g;
flashB = b;
flashIntensity = (double)intensity;
flashTimer = duration;
}

bool Battler::executeAction(bool skipPluginHandlers) {
bool ret;
if(skipPluginHandlers) {
asm volatile("call *%%esi" : "=a" (ret), "=d" (_edx) : "S" (0x49A04C), "a" (**sceneObjects[SCENE_BATTLE]), "d" (this) : "ecx", "cc", "memory"); // ExecuteBattlerAction
} else {
asm volatile("call *%%esi" : "=a" (ret), "=d" (_edx) : "S" (0x45CDF4), "a" (**sceneObjects[SCENE_BATTLE]), "d" (this) : "ecx", "cc", "memory"); // ExecuteBattlerAction (DynRPG)
}
return ret;
}
}
81 changes: 81 additions & 0 deletions library/Canvas.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#define DYNRPG_STATIC
#include "DynRPG.h"

namespace RPG {
unsigned short &Canvas::pixel(int x, int y) {
return getScanline(y)[x];
}

unsigned short *Canvas::getScanline(int y) {
unsigned short *ret;
asm volatile("call *%%esi" : "=a" (ret), "=d" (_edx) : "S" (0x4683B8), "a" (this), "d" (y) : "ecx", "cc", "memory"); // GetAuroraBoardPixelLineAddress
return ret;
}

int Canvas::width() {
int ret;
asm volatile("call *%%esi" : "=a" (ret) : "S" (0x4680CC), "a" (this) : "edx", "ecx", "cc", "memory"); // GetBoardBitmapWidth
return ret;
}

int Canvas::height() {
int ret;
asm volatile("call *%%esi" : "=a" (ret) : "S" (0x4680D8), "a" (this) : "edx", "ecx", "cc", "memory"); // GetBoardBitmapHeight
return ret;
}

void Canvas::draw(int x, int y, Image *image, int srcX, int srcY, int srcWidth, int srcHeight) {
if(srcWidth == -1) srcWidth = image->width;
if(srcHeight == -1) srcHeight = image->height;
RECT rc;
rc.left = srcX;
rc.top = srcY;
rc.right = srcX + srcWidth;
rc.bottom = srcY + srcHeight;
asm volatile(
"pushl %7;"
"pushl %8;"
"call *%%esi;"
: "=a" (_eax), "=d" (_edx), "=c" (_ecx) : "S" (0x4684C0), "a" (this), "d" (x), "c" (y), "m" (image), "D" (&rc) : "cc", "memory"
);
// Changed constraints to "m" for image and "D" for &rc because the new GCC would assign &rc to ESP even though I had put "g"...
// I think it's a bug, and it messes up everything because it generates a "push esp"!
}

void Canvas::drawStretched(int x, int y, int width, int height, Image *image, int srcX, int srcY, int srcWidth, int srcHeight) {
if(srcWidth == -1) srcWidth = image->width;
if(srcHeight == -1) srcHeight = image->height;
if(width == srcWidth && height == srcHeight) {
draw(x, y, image, srcX, srcY, srcWidth, srcHeight);
return;
}
RECT rc1;
RECT rc2;
rc1.left = srcX;
rc1.top = srcY;
rc1.right = srcX + srcWidth;
rc1.bottom = srcY + srcHeight;
rc2.left = x;
rc2.top = y;
rc2.right = x + width;
rc2.bottom = y + height;
asm volatile(
"pushl %7;"
"call *%%esi;"
: "=a" (_eax), "=d" (_edx), "=c" (_ecx) : "S" (0x4688B0), "a" (this), "d" (&rc2), "c" (image), "D" (&rc1) : "cc", "memory"
);
// See comment above about "D"
}

void Canvas::drawCenteredZoomed(int x, int y, double zoomX, double zoomY, Image *image, int srcX, int srcY, int srcWidth, int srcHeight) {
if(srcWidth == -1) srcWidth = image->width;
if(srcHeight == -1) srcHeight = image->height;
if(zoomX == 1.0 && zoomY == 1.0) {
draw(x - (srcWidth + 1) / 2, y - (srcHeight + 1) / 2, image, srcX, srcY, srcWidth, srcHeight);
return;
}
int newWidth = (int)((double)srcWidth * zoomX + 0.5);
int newHeight = (int)((double)srcHeight * zoomY + 0.5);
drawStretched(x - (newWidth + 1) / 2, y - (newHeight + 1) / 2, newWidth, newHeight, image, srcX, srcY, srcWidth, srcHeight);
}
}
Loading

0 comments on commit 0b14831

Please sign in to comment.