Org and sound

This commit is contained in:
cuckydev 2019-01-19 21:23:04 -05:00
parent c84f49f1dc
commit f43a3c1130
36 changed files with 2664 additions and 41 deletions

View file

@ -20,9 +20,11 @@ LIBS += `sdl2-config --static-libs` -lSDL2_ttf -lfreetype -lharfbuzz -lfreetype
# For an accurate result to the original's code, compile in alphabetical order
SOURCES = \
Back \
Config \
Draw \
Ending \
Escape \
Flags \
Game \
Generic \
@ -31,7 +33,14 @@ SOURCES = \
KeyControl \
Main \
Map \
MapName \
NpChar \
NpcTbl \
Organya \
PixTone \
Profile \
Sound \
Stage \
TextScr \
Triangle \

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 16 KiB

BIN
build/data/WAVE100.bin Normal file

Binary file not shown.

Binary file not shown.

33
src/Back.cpp Normal file
View file

@ -0,0 +1,33 @@
#include <SDL_rwops.h>
#include "WindowsWrapper.h"
#include "Tags.h"
#include "Back.h"
#include "Draw.h"
BACK gBack;
int gWaterY;
bool InitBack(char *fName, int type)
{
//Get width and height
char path[PATH_LENGTH];
sprintf(path, "%s/%s.pbm", gDataPath, fName);
SDL_Surface *temp = SDL_LoadBMP(path);
if (!temp)
return false;
gBack.partsW = temp->w;
gBack.partsH = temp->h;
SDL_FreeSurface(temp);
//Set background stuff and load texture
gBack.flag = 1;
if (!ReloadBitmap_File(fName, 28))
return false;
gBack.type = type;
gWaterY = 0x1E0000;
return true;
}

16
src/Back.h Normal file
View file

@ -0,0 +1,16 @@
#pragma once
struct BACK
{
int flag;
int partsW;
int partsH;
int numX;
int numY;
int type;
int fx;
};
extern int gWaterY;
bool InitBack(char *fName, int type);

View file

@ -104,7 +104,7 @@ bool MakeSurface(const char *name, int surf_no)
}
//Make sure surface has color key on
SDL_SetColorKey(surface, SDL_TRUE, 0x000000);
SDL_SetColorKey(surface, SDL_TRUE, SDL_MapRGB(surface->format, 0, 0, 0));
//Get texture from surface
SDL_Texture *texture = SDL_CreateTextureFromSurface(gRenderer, surface);
@ -136,7 +136,8 @@ bool MakeSurface(const char *name, int surf_no)
surf[surf_no].texture = textureAccessible;
surf[surf_no].scale = true;
//Free surface
//Free surface and texture
SDL_DestroyTexture(texture);
SDL_FreeSurface(surface);
printf(" ^ Successfully loaded\n");
@ -239,7 +240,7 @@ void PutBitmap3(RECT *rcView, int x, int y, RECT *rect, int surf_no) //Transpare
//Draw to screen
if (SDL_RenderCopy(gRenderer, surf[surf_no].texture, &frameRect, &destRect) < 0)
printf(SDL_GetError());
printf("Failed to draw texture %d\nSDL Error: %s\n", surf_no, SDL_GetError());
//Undo cliprect
SDL_RenderSetClipRect(gRenderer, NULL);
@ -272,7 +273,7 @@ void PutBitmap4(RECT *rcView, int x, int y, RECT *rect, int surf_no) //No Transp
//Draw texture
if (SDL_RenderCopy(gRenderer, surf[surf_no].texture, &frameRect, &destRect) < 0)
printf(SDL_GetError());
printf("Failed to draw texture %d\nSDL Error: %s\n", surf_no, SDL_GetError());
//Restore original colour, and undo cliprect
SDL_RenderSetClipRect(gRenderer, NULL);
@ -297,7 +298,7 @@ void Surface2Surface(int x, int y, RECT *rect, int to, int from)
//Draw texture
if (SDL_RenderCopy(gRenderer, surf[from].texture, &frameRect, &rcSet) < 0)
printf(SDL_GetError());
printf("Failed to draw texture %d to %d\nSDL Error: %s\n", from, to, SDL_GetError());
//Stop targetting surface
SDL_SetRenderTarget(gRenderer, NULL);
@ -329,8 +330,13 @@ void CortBox2(RECT *rect, uint32_t col, int surf_no)
SDL_SetRenderTarget(gRenderer, surf[surf_no].texture);
const unsigned char col_red = col & 0xFF0000 >> 16;
const unsigned char col_green = col & 0x00FF00 >> 8;
const unsigned char col_blue = col & 0x0000FF;
const unsigned char col_alpha = (col_red || col_green || col_blue) ? 0xFF : 0;
//Set colour and draw
SDL_SetRenderDrawColor(gRenderer, col & 0xFF0000 >> 16, col & 0x00FF00 >> 8, col & 0x0000FF, 0xFF);
SDL_SetRenderDrawColor(gRenderer, col_red, col_green, col_blue, col_alpha);
SDL_RenderFillRect(gRenderer, &destRect);
//Stop targetting surface

View file

@ -191,6 +191,7 @@ bool StartCreditScript()
//Clear casts
memset(Strip, 0, sizeof(Strip));
SDL_RWclose(fp);
return true;
}

39
src/Escape.cpp Normal file
View file

@ -0,0 +1,39 @@
#include "WindowsWrapper.h"
#include "Draw.h"
#include "KeyControl.h"
int Call_Escape()
{
RECT rc = {0, 128, 208, 144};
while (Flip_SystemTask())
{
//Get pressed keys
GetTrg();
if (gKeyTrg & 0x8000) //Escape is pressed, quit game
{
gKeyTrg = 0;
return 0;
}
if (gKeyTrg & 0x400) //F1 is pressed, continue
{
gKeyTrg = 0;
return 1;
}
if (gKeyTrg & 0x800) //F2 is pressed, reset
{
gKeyTrg = 0;
return 2;
}
//Draw screen
CortBox(&grcFull, 0x000000);
PutBitmap3(&grcFull, 56, 112, &rc, 26);
//PutFramePerSecound();
}
//Quit if window is closed
gKeyTrg = 0;
return 0;
}

2
src/Escape.h Normal file
View file

@ -0,0 +1,2 @@
#pragma once
int Call_Escape();

0
src/Frame.cpp Normal file
View file

0
src/Frame.h Normal file
View file

View file

@ -1,65 +1,440 @@
#include <string>
#include <stdlib.h>
#include <SDL_timer.h>
#include "WindowsWrapper.h"
#include "Tags.h"
#include "NpcTbl.h"
#include "Generic.h"
#include "GenericLoad.h"
#include "TextScr.h"
#include "Flags.h"
#include "Escape.h"
#include "Stage.h"
#include "Map.h"
#include "MapName.h"
#include "Sound.h"
#include "Profile.h"
#include "Back.h"
#include "KeyControl.h"
#include "Draw.h"
#include "Ending.h"
int g_GameFlags;
int gCounter;
bool bContinue;
int Random(int min, int max)
{
return min + rand() % (max - min + 1);
}
void PutNumber4(int x, int y, int value, bool bZero)
{
//Define rects
RECT rcClient = grcFull;
RECT rect[10];
rect[0] = {0, 56, 8, 64};
rect[1] = {8, 56, 16, 64};
rect[2] = {16, 56, 24, 64};
rect[3] = {24, 56, 32, 64};
rect[4] = {32, 56, 40, 64};
rect[5] = {40, 56, 48, 64};
rect[6] = {48, 56, 56, 64};
rect[7] = {56, 56, 64, 64};
rect[8] = {64, 56, 72, 64};
rect[9] = {72, 56, 80, 64};
//Digits
int tbl[4] = {1000, 100, 10, 1};
//Limit value
if ( value > 9999 )
value = 9999;
//Go through number and draw digits
int offset = 0;
int sw = 0;
while (offset < 4)
{
//Get the digit that this is
int a = 0;
while (tbl[offset] <= value)
{
value -= tbl[offset];
++a;
++sw;
}
//Draw digit
if ( bZero && offset == 2 || sw != 0 || offset == 3 )
PutBitmap3(&rcClient, x + 8 * offset, y, &rect[a], SURFACE_ID_TEXT_BOX);
//Go to next digit
++offset;
}
}
int ModeOpening()
{
//InitNpChar();
//InitCaret();
//InitStar();
//InitFade();
//InitFlash();
//InitBossLife();
ChangeMusic(0);
TransferStage(72, 100, 3, 3);
//SetFrameTargetMyChar(16);
//SetFadeMask();
//Reset cliprect and flags
grcGame.left = 0;
g_GameFlags = 3;
//CutNoise();
int wait = 0;
while (wait < 500)
{
//Increase timer
++wait;
//Get pressed keys
GetTrg();
//Escape menu
if (gKey & 0x8000)
{
int escRet = Call_Escape();
if (escRet == 0)
return 0;
if (escRet == 2)
return 1;
}
//Skip intro if OK is pressed
if ( gKey & gKeyOk )
break;
//Update everything
//ActNpChar();
//ActBossChar();
//ActBack();
//ResetMyCharFlag();
//HitMyCharMap();
//HitMyCharNpChar();
//HitMyCharBoss();
//HitNpCharMap();
//HitBossMap();
//HitBossBullet();
//ActCaret();
//MoveFrame3();
//ProcFade();
//Draw everything
CortBox(&grcFull, 0x000000);
int frame_x = 0;
int frame_y = 0;
//GetFramePosition(&frame_x, &frame_y);
//PutBack(frame_x, frame_y);
PutStage_Back(frame_x, frame_y);
//PutBossChar(frame_x, frame_y);
//PutNpChar(frame_x, frame_y);
PutMapDataVector(frame_x, frame_y);
PutStage_Front(frame_x, frame_y);
//PutFront(frame_x, frame_y);
//PutCaret(frame_x, frame_y);
//PutFade();
//Update Text Script
//int tscRet = TextScriptProc();
//if (tscRet == 0)
// return 0;
//if (tscRet == 2)
// return 1;
PutMapName(false);
//PutTextScript();
//PutFramePerSecound();
if (!Flip_SystemTask())
return 0;
++gCounter;
}
wait = SDL_GetTicks();
while (SDL_GetTicks() < wait + 500)
{
CortBox(&grcGame, 0x000000);
//PutFramePerSecound();
if (!Flip_SystemTask())
return 0;
}
return 2;
}
int ModeTitle()
{
//Set rects
RECT rcTitle = {0, 0, 144, 32};
RECT rcPixel = {0, 0, 160, 16};
RECT rcNew = {144, 0, 192, 16};
RECT rcContinue = {144, 16, 192, 32};
RECT rcVersion = {152, 80, 208, 88};
RECT rcPeriod = {152, 88, 208, 96};
//Character rects
RECT rcMyChar[4];
RECT rcCurly[4];
RECT rcToroko[4];
RECT rcKing[4];
RECT rcSu[4];
rcMyChar[0] = {0, 16, 16, 32};
rcMyChar[1] = {16, 16, 32, 32};
rcMyChar[2] = {0, 16, 16, 32};
rcMyChar[3] = {32, 16, 48, 32};
rcCurly[0] = {0, 112, 16, 128};
rcCurly[1] = {16, 112, 32, 128};
rcCurly[2] = {0, 112, 16, 128};
rcCurly[3] = {32, 112, 48, 128};
rcToroko[0] = {64, 80, 80, 96};
rcToroko[1] = {80, 80, 96, 96};
rcToroko[2] = {64, 80, 80, 96};
rcToroko[3] = {96, 80, 112, 96};
rcKing[0] = {224, 48, 240, 64};
rcKing[1] = {288, 48, 304, 64};
rcKing[2] = {224, 48, 240, 64};
rcKing[3] = {304, 48, 320, 64};
rcSu[0] = {0, 16, 16, 32};
rcSu[1] = {32, 16, 48, 32};
rcSu[2] = {0, 16, 16, 32};
rcSu[3] = {48, 16, 64, 32};
//Reset everything
//InitCaret();
//InitStar();
//CutNoise();
//Create variables
int anime = 0;
int char_type = 0;
int time_counter = 0;
//Set state
bContinue = IsProfile();
//Set character
time_counter = 0;//LoadTimeCounter();
if (time_counter && time_counter < 18000)
char_type = 1;
if (time_counter && time_counter < 15000)
char_type = 2;
if (time_counter && time_counter < 12000)
char_type = 3;
if (time_counter && time_counter < 9000)
char_type = 4;
//Set music to character's specific music
switch (char_type)
{
case 1:
ChangeMusic(mus_RunningHell);
break;
case 2:
ChangeMusic(mus_TorokosTheme);
break;
case 3:
ChangeMusic(mus_White);
break;
case 4:
ChangeMusic(mus_Safety);
break;
default:
ChangeMusic(mus_Geothermal);//mus_CaveStory);
break;
}
//Reset cliprect, flags, and give the player the booster 0.8?
grcGame.left = 0;
g_GameFlags = 0;
/*
v0 = unk_81C8598;
BYTE1(v0) |= 1u;
unk_81C8598 = v0;
*/
//Start loop
int wait = 0;
while (true)
{
//Don't accept selection for 10 frames
if (wait < 10)
++wait;
//Get pressed keys
GetTrg();
//Quit when OK is pressed
if (wait >= 10)
{
if (gKeyTrg & gKeyOk)
break;
}
if (gKey & 0x8000)
{
int escRet = Call_Escape();
if (escRet == 0)
return 0;
if (escRet == 2)
return 1;
}
//Move cursor
if ((gKeyDown | gKeyUp) & gKeyTrg)
{
PlaySoundObject(1, 1);
bContinue = !bContinue;
}
//Update carets
//ActCaret();
//Animate character cursor
if ( ++anime >= 40 )
anime = 0;
//Draw title
CortBox(&grcGame, 0x202020);
//Draw version
int v1, v2, v3, v4;
PutBitmap3(&grcGame, 100, 216, &rcVersion, SURFACE_ID_TEXT_BOX);
PutBitmap3(&grcGame, 156, 216, &rcPeriod, SURFACE_ID_TEXT_BOX);
GetCompileVersion(&v1, &v2, &v3, &v4);
PutNumber4(140, 216, v1, 0);
PutNumber4(156, 216, v2, 0);
PutNumber4(172, 216, v3, 0);
PutNumber4(188, 216, v4, 0);
//Draw main title
PutBitmap3(&grcGame, 88, 40, &rcTitle, 0);
PutBitmap3(&grcGame, 136, 128, &rcNew, 0);
PutBitmap3(&grcGame, 136, 148, &rcContinue, 0);
PutBitmap3(&grcGame, 80, 192, &rcPixel, 1);
//Draw character cursor
RECT char_rc;
int char_surf;
switch ( char_type )
{
case 0:
char_rc = rcMyChar[anime / 10 % 4];
char_surf = SURFACE_ID_MY_CHAR;
break;
case 1:
char_rc = rcCurly[anime / 10 % 4];
char_surf = SURFACE_ID_NPC_REGU;
break;
case 2:
char_rc = rcToroko[anime / 10 % 4];
char_surf = SURFACE_ID_NPC_REGU;
break;
case 3:
char_rc = rcKing[anime / 10 % 4];
char_surf = SURFACE_ID_NPC_REGU;
break;
case 4:
char_rc = rcSu[anime / 10 % 4];
char_surf = SURFACE_ID_NPC_REGU;
break;
}
int char_y;
if (bContinue == 1)
char_y = 147;
else
char_y = 127;
PutBitmap3(&grcGame, 116, char_y, &char_rc, char_surf);
//Draw carets
//PutCaret(0, 0);
//if (time_counter)
// PutTimeCounter(16, 8);
//PutFramePerSecound();
if (!Flip_SystemTask())
return 0;
}
PlaySoundObject(18, 1);
ChangeMusic(0);
//Black screen when option is selected
wait = SDL_GetTicks();
while (SDL_GetTicks() < wait + 1000)
{
CortBox(&grcGame, 0);
//PutFramePerSecound();
if (!Flip_SystemTask())
return 0;
}
return 0;
}
bool Game()
{
if (LoadGenericData())
{
char path[PATH_LENGTH];
sprintf(path, "%s/npc.tbl", gDataPath);
if (LoadNpcTable(path))
if (LoadNpcTable(path) && InitStageTable())
{
InitTextScript2();
InitSkipFlags();
InitMapData2();
InitCreditScript();
StartCreditScript();
while (Flip_SystemTask())
{
ActionCredit();
ActionIllust();
ActionStripper();
CortBox(&grcFull, 0x000020);
PutIllust();
PutStripper();
}
/*
int mode = 0; //1;
int mode = 1;
while (mode)
{
//if ( mode == 1 )
// mode = ModeOpening();
//if ( mode == 2 )
// mode = ModeTitle();
//if ( mode == 3 )
if (mode == 1)
mode = ModeOpening();
if (mode == 2)
mode = ModeTitle();
//if (mode == 3)
// mode = ModeAction();
}
*/
//EndMapData();
//EndTextScript();
//ReleaseNpcTable();
//ReleaseCreditScript();
EndMapData();
EndTextScript();
ReleaseNpcTable();
ReleaseStageTable();
ReleaseCreditScript();
}
else
{

View file

@ -1,5 +1,14 @@
#include <stdint.h>
bool GetCompileVersion(int *v1, int *v2, int *v3, int *v4)
{
*v1 = 1;
*v2 = 0;
*v3 = 0;
*v4 = 6;
return true;
}
bool IsShiftJIS(uint8_t c)
{
if ( c > 0x80 && c < 0xA0 )

View file

@ -1,4 +1,5 @@
#pragma once
#include <stdint.h>
bool GetCompileVersion(int *v1, int *v2, int *v3, int *v4);
bool IsShiftJIS(uint8_t c);

View file

@ -9,6 +9,8 @@
#include "Draw.h"
#include "Input.h"
#include "Organya.h"
#include "Sound.h"
#include "Game.h"
#include "Config.h"
#include "KeyControl.h"
@ -32,9 +34,9 @@ bool bFps;
bool bActive;
#ifdef JAPANESE
const char *lpWindowName = "洞窟物語エンジン";
const char *lpWindowName = "洞窟物語エンジン2";
#else
const char *lpWindowName = "Cave Story Engine ~ Doukutsu Monogatari Enjin";
const char *lpWindowName = "Cave Story Engine 2 ~ Doukutsu Monogatari Enjin 2";
#endif
int main(int argc, char *argv[])
@ -212,7 +214,7 @@ int main(int argc, char *argv[])
if (Flip_SystemTask())
{
//Initialize sound
//InitDirectSound();
InitDirectSound();
//Initialize joystick
if (config.bJoystick && InitDirectInput())
@ -229,7 +231,7 @@ int main(int argc, char *argv[])
Game();
//End stuff
//EndDirectSound();
EndDirectSound();
EndTextObject();
EndDirectDraw();
@ -250,11 +252,11 @@ void InactiveWindow()
if (bActive)
{
bActive = false;
//StopOrganyaMusic();
StopOrganyaMusic();
//SleepNoise();
}
//PlaySoundObject(7, 0);
PlaySoundObject(7, 0);
}
void ActiveWindow()
@ -262,12 +264,12 @@ void ActiveWindow()
if (!bActive)
{
bActive = true;
//StopOrganyaMusic();
//PlayOrganyaMusic();
StopOrganyaMusic();
PlayOrganyaMusic();
//ResetNoise();
}
//PlaySoundObject(7, -1);
PlaySoundObject(7, -1);
}
void JoystickProc()

View file

@ -1,7 +1,13 @@
#include <stdint.h>
#include <string>
#include <SDL_rwops.h>
#include "WindowsWrapper.h"
#include "CommonDefines.h"
#include "Map.h"
#include "Tags.h"
#include "Draw.h"
#define PXM_BUFFER_SIZE 0x4B000
@ -12,3 +18,251 @@ bool InitMapData2()
gMap.data = (uint8_t*)malloc(PXM_BUFFER_SIZE);
return true;
}
bool LoadMapData2(char *path_map)
{
//Get path
char path[PATH_LENGTH];
sprintf(path, "%s/%s", gDataPath, path_map);
//Open file
SDL_RWops *fp = SDL_RWFromFile(path, "rb");
if (!fp)
return false;
//Make sure file begins with "PXM"
char check[3];
fp->read(fp, check, 1, 3);
if (!memcmp(check, "PXM", 3))
{
uint8_t nul;
fp->read(fp, &nul, 1, 1);
//Get width and height
gMap.width = SDL_ReadLE16(fp);
gMap.length = SDL_ReadLE16(fp);
if (gMap.data)
{
//Read tiledata
fp->read(fp, gMap.data, 1, gMap.length * gMap.width);
SDL_RWclose(fp);
return true;
}
else
{
SDL_RWclose(fp);
return false;
}
}
else
{
SDL_RWclose(fp);
return false;
}
return false;
}
bool LoadAttributeData(char *path_atrb)
{
//Open file
char path[260];
sprintf(path, "%s/%s", gDataPath, path_atrb);
SDL_RWops *fp = SDL_RWFromFile(path, "rb");
if (!fp)
return false;
//Read data
fp->read(fp, gMap.atrb, 1, 0x100);
SDL_RWclose(fp);
return true;
}
void EndMapData()
{
if (gMap.data)
free(gMap.data);
}
void ReleasePartsImage()
{
ReleaseSurface(SURFACE_ID_LEVEL_TILESET);
}
void GetMapData(uint8_t **data, int16_t *mw, int16_t *ml)
{
if (data)
*data = gMap.data;
if (mw)
*mw = gMap.width;
if (ml)
*ml = gMap.length;
}
int GetAttribute(int x, int y)
{
if (x >= 0 && y >= 0 && gMap.width > x && gMap.length > y)
return gMap.atrb[gMap.data[y * gMap.width + x]];
return false;
}
void DeleteMapParts(int x, int y)
{
gMap.data[y * gMap.width + x] = 0;
}
void ShiftMapParts(int x, int y)
{
--gMap.data[y * gMap.width + x];
}
bool ChangeMapParts(int x, int y, uint8_t no)
{
if ( gMap.data[y * gMap.width + x] == no )
return false;
gMap.data[y * gMap.width + x] = no;
//for (int i = 0; i <= 2; ++i )
// SetNpChar(4, x << 13, y << 13, 0, 0, 0, 0, 0);
return true;
}
void PutStage_Back(int fx, int fy)
{
//Get range to draw
int num_x = WINDOW_WIDTH / 2 + 1;
int num_y = WINDOW_HEIGHT / 2 + 1;
int put_x = (fx / 0x200 + 8) / 16;
int put_y = (fy / 0x200 + 8) / 16;
for (int j = put_y; put_y + num_y > j; j++)
{
for (int i = put_x; put_x + num_x > i; i++)
{
//Get attribute
int offset = i + j * gMap.width;
int atrb = GetAttribute(i, j);
if (atrb < 0x20)
{
//Draw tile
RECT rect;
rect.left = 16 * (gMap.data[offset] & 0xF);
rect.top = 16 * (gMap.data[offset] >> 4);
rect.right = rect.left + 16;
rect.bottom = rect.top + 16;
PutBitmap3(&grcGame, 8 * (2 * i - 1) - fx / 0x200, 8 * (2 * j - 1) - fy / 0x200, &rect, SURFACE_ID_LEVEL_TILESET);
}
}
}
}
void PutStage_Front(int fx, int fy)
{
RECT rcSnack = {256, 48, 272, 64};
//Get range to draw
int num_x = WINDOW_WIDTH / 2 + 1;
int num_y = WINDOW_HEIGHT / 2 + 1;
int put_x = (fx / 0x200 + 8) / 16;
int put_y = (fy / 0x200 + 8) / 16;
for (int j = put_y; put_y + num_y > j; j++)
{
for (int i = put_x; put_x + num_x > i; i++)
{
//Get attribute
int offset = i + j * gMap.width;
int atrb = GetAttribute(i, j);
if (atrb >= 0x40 && atrb < 0x80)
{
//Draw tile
RECT rect;
rect.left = 16 * (gMap.data[offset] & 0xF);
rect.top = 16 * (gMap.data[offset] >> 4);
rect.right = rect.left + 16;
rect.bottom = rect.top + 16;
PutBitmap3(&grcGame, 8 * (2 * i - 1) - fx / 0x200, 8 * (2 * j - 1) - fy / 0x200, &rect, SURFACE_ID_LEVEL_TILESET);
if (atrb == 0x43)
PutBitmap3(&grcGame, 8 * (2 * i - 1) - fx / 0x200, 8 * (2 * j - 1) - fy / 0x200, &rcSnack, SURFACE_ID_NPC_SYM);
}
}
}
}
void PutMapDataVector(int fx, int fy)
{
//Get range to draw
int num_x = WINDOW_WIDTH / 2 + 1;
int num_y = WINDOW_HEIGHT / 2 + 1;
int put_x = (fx / 0x200 + 8) / 16;
int put_y = (fy / 0x200 + 8) / 16;
//Animate the wind
static int count = 0;
count++;
for (int j = put_y; put_y + num_y > j; j++)
{
for (int i = put_x; put_x + num_x > i; i++)
{
//Get attribute
int offset = i + j * gMap.width;
int atrb = GetAttribute(i, j);
if ( atrb == 0x80
|| atrb == 0x81
|| atrb == 0x82
|| atrb == 0x83
|| atrb == 0xA0
|| atrb == 0xA1
|| atrb == 0xA2
|| atrb == 0xA3)
{
RECT rect;
switch ( atrb )
{
case 128:
case 160:
rect.left = (count & 0xF) + 224;
rect.right = (count & 0xF) + 240;
rect.top = 48;
rect.bottom = 64;
break;
case 129:
case 161:
rect.left = 224;
rect.right = 240;
rect.top = (count & 0xF) + 48;
rect.bottom = (count & 0xF) + 64;
break;
case 130:
case 162:
rect.left = 240 - (count & 0xF);
rect.right = rect.left + 16;
rect.top = 48;
rect.bottom = 64;
break;
case 131:
case 163:
rect.left = 224;
rect.right = 240;
rect.top = 64 - (count & 0xF);
rect.bottom = rect.top + 16;
break;
default:
break;
}
PutBitmap3(&grcGame, 8 * (2 * i - 1) - fx / 0x200, 8 * (2 * j - 1) - fy / 0x200, &rect, SURFACE_ID_CARET);
}
}
}
}

View file

@ -9,4 +9,18 @@ struct MAP_DATA
int16_t length;
};
extern MAP_DATA gMap;
bool InitMapData2();
bool LoadMapData2(char *path_map);
bool LoadAttributeData(char *path_atrb);
void EndMapData();
void ReleasePartsImage();
void GetMapData(uint8_t **data, int16_t *mw, int16_t *ml);
int GetAttribute(int x, int y);
void DeleteMapParts(int x, int y);
void ShiftMapParts(int x, int y);
bool ChangeMapParts(int x, int y, uint8_t no);
void PutStage_Back(int fx, int fy);
void PutStage_Front(int fx, int fy);
void PutMapDataVector(int fx, int fy);

73
src/MapName.cpp Normal file
View file

@ -0,0 +1,73 @@
#include <stdint.h>
#include <string>
#include "CommonDefines.h"
#include "MapName.h"
#include "Draw.h"
MAP_NAME gMapName;
RECT rc = { 0, 0, 160, 12 };
void ReadyMapName(char *str)
{
//Reset map name flags
gMapName.flag = 0;
gMapName.wait = 0;
//Handle "Studio Pixel presents" text in the intro
#ifdef JAPANESE
char presentText[24] = "開発室Pixel presents\x00\x01\x01\x01";
#else
char presentText[24] = " Studio Pixel presents";
#endif
if (!strcmp(str, "u"))
{
/*for (i = 0; i < strlen(presentText); i++) //No need for this, we aren't encrypting the text
++studio_pixel_presents_string[i];*/
str = presentText;
}
//Copy map's name to the MapName
strcpy(gMapName.name, str);
//Draw the text to the surface
int len = strlen(gMapName.name);
CortBox2(&rc, 0, SURFACE_ID_ROOM_NAME);
PutText2((-6 * len + 160) / 2 + 6, 1, gMapName.name, 0x110022, SURFACE_ID_ROOM_NAME);
PutText2((-6 * len + 160) / 2 + 6, 0, gMapName.name, 0xFFFFFE, SURFACE_ID_ROOM_NAME);
}
void PutMapName(bool bMini)
{
if (bMini)
{
//Map system
RECT rcBack = {0, 7, WINDOW_WIDTH, 24};
CortBox(&rcBack, 0x000000);
PutBitmap3(&grcGame, 74, 10, &rc, SURFACE_ID_ROOM_NAME);
}
else if (gMapName.flag)
{
//MNA
PutBitmap3(&grcGame, 74, 80, &rc, SURFACE_ID_ROOM_NAME);
if (++gMapName.wait > 160)
gMapName.flag = 0;
}
}
void StartMapName()
{
gMapName.flag = 1;
gMapName.wait = 0;
}
void RestoreMapName()
{
int len = strlen(gMapName.name);
CortBox2(&rc, 0, SURFACE_ID_ROOM_NAME);
PutText2((-6 * len + 160) / 2 + 6, 1, gMapName.name, 0x110022, SURFACE_ID_ROOM_NAME);
PutText2((-6 * len + 160) / 2 + 6, 0, gMapName.name, 0xFFFFFE, SURFACE_ID_ROOM_NAME);
}

12
src/MapName.h Normal file
View file

@ -0,0 +1,12 @@
#pragma once
struct MAP_NAME
{
int flag;
int wait;
char name[0x20];
};
void ReadyMapName(char *str);
void PutMapName(bool bMini);
void StartMapName();
void RestoreMapName();

12
src/NpChar.cpp Normal file
View file

@ -0,0 +1,12 @@
#include <stdint.h>
#include "NpChar.h"
#define NPC_MAX 0x200
NPCHAR gNPC[NPC_MAX];
bool LoadEvent(char *path_event)
{
return true;
}

43
src/NpChar.h Normal file
View file

@ -0,0 +1,43 @@
#pragma once
#include <stdint.h>
#include "WindowsWrapper.h"
struct NPCHAR
{
uint8_t cond;
int flag;
int x;
int y;
int xm;
int ym;
int xm2;
int ym2;
int tgt_x;
int tgt_y;
int code_char;
int code_flag;
int code_event;
int surf;
int hit_voice;
int destroy_voice;
int life;
int exp;
int size;
int direct;
uint16_t bits;
RECT rect;
int ani_wait;
int ani_no;
int count1;
int count2;
int act_no;
int act_wait;
RECT hit;
RECT view;
uint8_t shock;
int damage_view;
int damage;
NPCHAR *pNpc;
};
bool LoadEvent(char *path_event);

View file

@ -41,6 +41,13 @@ bool LoadNpcTable(const char *path)
fp->read(fp, &gNpcTable[i].hit, 4, 1);
for (size_t i = 0; i < npcCount; i++) //view
fp->read(fp, &gNpcTable[i].view, 4, 1);
SDL_RWclose(fp);
return true;
}
void ReleaseNpcTable()
{
if (gNpcTable)
free(gNpcTable);
}

View file

@ -26,3 +26,4 @@ struct NPC_TABLE
extern NPC_TABLE *gNpcTable;
bool LoadNpcTable(const char *path);
void ReleaseNpcTable();

632
src/Organya.cpp Normal file
View file

@ -0,0 +1,632 @@
#include <stdint.h>
#include <SDL_rwops.h>
#include <SDL_thread.h>
#include <SDL_timer.h>
#include <SDL_events.h>
#include "WindowsWrapper.h"
#include "CommonDefines.h"
#include "Tags.h"
#include "Organya.h"
#include "Sound.h"
#define PANDUMMY 0xFF
#define VOLDUMMY 0xFF
#define KEYDUMMY 0xFF
#define MAXTRACK 16
#define MAXMELODY 8
#define MAXDRAM 8
SOUNDBUFFER* lpORGANBUFFER[8][8][2] = {NULL};
SOUNDBUFFER** lpDRAMBUFFER = &lpSECONDARYBUFFER[0x96];
MUSICINFO info;
int gTrackVol[MAXTRACK];
int gOrgVolume = 100;
bool bFadeout = false;
bool OrganyaNoteAlloc(uint16_t alloc)
{
for(int j = 0; j < MAXTRACK; j++)
{
info.tdata[j].wave_no = 0;
info.tdata[j].note_list = NULL;
info.tdata[j].note_p = new NOTELIST[alloc];
if(info.tdata[j].note_p == NULL)
return false;
for(int i = 0; i < alloc; i++)
{
(info.tdata[j].note_p + i)->from = NULL;
(info.tdata[j].note_p + i)->to = NULL;
(info.tdata[j].note_p + i)->length = 0;
(info.tdata[j].note_p + i)->pan = PANDUMMY;
(info.tdata[j].note_p + i)->volume = VOLDUMMY;
(info.tdata[j].note_p + i)->y = KEYDUMMY;
}
}
for(int j = 0; j < MAXMELODY; j++)
MakeOrganyaWave(j, info.tdata[j].wave_no);
//for(int j = 0; j < MAXDRAM; j++)
// InitDramObject(j);
return true;
}
void OrganyaReleaseNote()
{
for(int i = 0; i < MAXTRACK; i++)
{
if(info.tdata[i].note_p != NULL)
delete info.tdata[i].note_p;
}
}
//Wave playing and loading
typedef struct {
short wave_size;
short oct_par;
short oct_size;
} OCTWAVE;
OCTWAVE oct_wave[8] = {
{ 256, 1, 4 }, //0 Oct
{ 256, 2, 8 }, //1 Oct
{ 128, 4, 12 }, //2 Oct
{ 128, 8, 16 }, //3 Oct
{ 64, 16, 20 }, //4 Oct
{ 32, 32, 24 }, //5 Oct
{ 16, 64, 28 }, //6 Oct
{ 8,128, 32 }, //7 Oct
};
bool MakeSoundObject8(int8_t *wavep, int8_t track)
{
for (int j = 0; j < 8; j++)
{
for (int k = 0; k < 2; k++)
{
size_t wave_size = oct_wave[j].wave_size;
size_t data_size = wave_size;
//Create sound buffer
lpORGANBUFFER[track][j][k] = new SOUNDBUFFER(data_size);
//Get wave data
uint8_t *wp = (uint8_t*)malloc(data_size);
uint8_t *wp_sub = wp;
size_t wav_tp = 0;
for (int i = 0; i < data_size; i++)
{
uint8_t work = *(wavep+wav_tp);
work += 0x80;
*wp_sub = work;
wav_tp += 0x100 / wave_size;
if (wav_tp >= 0x100)
wav_tp -= 0x100;
wp_sub++;
}
//Copy wave data to sound buffer
uint8_t *buf;
lpORGANBUFFER[track][j][k]->Lock(&buf, NULL);
memcpy(buf, wp, data_size);
lpORGANBUFFER[track][j][k]->Unlock();
}
}
return true;
}
//Playing melody tracks
double freq_tbl[12] = { 261.62556530060, 277.18263097687, 293.66476791741, 311.12698372208, 329.62755691287, 349.22823143300, 369.99442271163, 391.99543598175, 415.30469757995, 440.00000000000, 466.16376151809, 493.88330125612 };
void ChangeOrganFrequency(uint8_t key, uint8_t track, int32_t a)
{
for (int j = 0; j < 8; j++)
{
for (int i = 0; i < 2; i++) {
double tmpDouble = (((double)oct_wave[j].wave_size * freq_tbl[key]) * (double)oct_wave[j].oct_par) / 8.00f + ((double)a - 1000.0f);
lpORGANBUFFER[track][j][i]->SetFrequency(tmpDouble);
}
}
}
int16_t pan_tbl[13] = {0, 43, 86, 129, 172, 215, 256, 297, 340, 383, 426, 469, 512};
uint8_t old_key[MAXTRACK] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
uint8_t key_on[MAXTRACK] = {0};
uint8_t key_twin[MAXTRACK] = {0};
void ChangeOrganPan(uint8_t key, uint8_t pan, int8_t track)
{
if(old_key[track] != PANDUMMY)
lpORGANBUFFER[track][old_key[track]/12][key_twin[track]]->SetPan((pan_tbl[pan] - 0x100) * 10);
}
void ChangeOrganVolume(int no, int32_t volume, int8_t track)
{
if(old_key[track] != VOLDUMMY)
lpORGANBUFFER[track][old_key[track]/12][key_twin[track]]->SetVolume((volume - 0xFF) * 8);
}
void PlayOrganObject(uint8_t key, int mode, int8_t track, int32_t freq)
{
if(lpORGANBUFFER[track][key/12][key_twin[track]] != NULL)
{
switch(mode)
{
case 0:
lpORGANBUFFER[track][old_key[track] / 12][key_twin[track]]->Stop();
lpORGANBUFFER[track][old_key[track] / 12][key_twin[track]]->SetCurrentPosition(0);
break;
case 1:
break;
case 2:
if (old_key[track] != 0xFF)
{
lpORGANBUFFER[track][old_key[track] / 12][key_twin[track]]->Play(false);
old_key[track] = 0xFF;
}
break;
case -1:
if (old_key[track] == 0xFF)
{
ChangeOrganFrequency(key % 12, track, freq);
lpORGANBUFFER[track][key / 12][key_twin[track]]->Play(true);
old_key[track] = key;
key_on[track] = 1;
}
else if (key_on[track] == 1 && old_key[track] == key)
{
lpORGANBUFFER[track][old_key[track] / 12][key_twin[track]]->Play(false);
key_twin[track]++;
if(key_twin[track] == 2)
key_twin[track] = 0;
lpORGANBUFFER[track][key / 12][key_twin[track]]->Play(true);
}
else
{
lpORGANBUFFER[track][old_key[track]/12][key_twin[track]]->Play(false);
key_twin[track]++;
if(key_twin[track] == 2)
key_twin[track] = 0;
ChangeOrganFrequency(key % 12, track, freq);
lpORGANBUFFER[track][key / 12][key_twin[track]]->Play(true);
old_key[track] = key;
}
break;
}
}
}
//Release tracks
void ReleaseOrganyaObject(int8_t track)
{
for(int i = 0; i < 8; i++)
{
if(lpORGANBUFFER[track][i][0] != NULL)
{
lpORGANBUFFER[track][i][0]->Release();
lpORGANBUFFER[track][i][0] = NULL;
}
if(lpORGANBUFFER[track][i][1] != NULL)
{
lpORGANBUFFER[track][i][1]->Release();
lpORGANBUFFER[track][i][1] = NULL;
}
}
}
//Handling WAVE100
int8_t *wave_data = NULL;
bool InitWaveData100()
{
if (wave_data == NULL)
wave_data = (int8_t*)malloc(100 * 0x100);
char path[PATH_LENGTH];
sprintf(path, "%s/WAVE100.bin", gDataPath);
SDL_RWops *fp = SDL_RWFromFile(path, "rb");
if (!fp)
{
printf("Failed to open %s\n", path);
return false;
}
for (int i = 0; i < 100 * 0x100; i++)
wave_data[i] = SDL_ReadU8(fp);
SDL_RWclose(fp);
return true;
}
bool DeleteWaveData100()
{
free(wave_data);
return true;
}
//Create org wave
bool MakeOrganyaWave(int8_t track, int8_t wave_no)
{
if(wave_no > 99)
return false;
ReleaseOrganyaObject(track);
MakeSoundObject8(&wave_data[wave_no * 0x100], track);
return true;
}
//Dram
void ChangeDramFrequency(uint8_t key, int8_t track)
{
lpDRAMBUFFER[track]->SetFrequency(key * 800 + 100);
}
void ChangeDramPan(uint8_t pan, int8_t track)
{
lpDRAMBUFFER[track]->SetPan((pan_tbl[pan] - 0x100) * 10);
}
void ChangeDramVolume(int32_t volume, int8_t track)
{
lpDRAMBUFFER[track]->SetVolume((volume - 0xFF) * 8);
}
void PlayDramObject(unsigned char key, int mode,char track)
{
switch(mode)
{
case 0:
lpDRAMBUFFER[track]->Stop();
lpDRAMBUFFER[track]->SetCurrentPosition(0);
break;
case 1:
lpDRAMBUFFER[track]->Stop();
lpDRAMBUFFER[track]->SetCurrentPosition(0);
ChangeDramFrequency(key, track);
lpDRAMBUFFER[track]->Play(false);
break;
case 2:
break;
case -1:
break;
}
}
//Play data
int32_t play_p;
NOTELIST *play_np[MAXTRACK];
int32_t now_leng[MAXMELODY] = {0};
void OrganyaPlayData()
{
//Handle fading out
if (bFadeout && gOrgVolume)
gOrgVolume -= 2;
if (gOrgVolume < 0)
gOrgVolume = 0;
//Play melody
for(int i = 0; i < MAXMELODY; i++)
{
if (play_np[i] != NULL &&play_p == play_np[i]->x)
{
if(play_np[i]->y != KEYDUMMY)
{
PlayOrganObject(play_np[i]->y,-1,i,info.tdata[i].freq);
now_leng[i] = play_np[i]->length;
}
if(play_np[i]->pan != PANDUMMY)
ChangeOrganPan(play_np[i]->y,play_np[i]->pan, i);
if(play_np[i]->volume != VOLDUMMY)
gTrackVol[i] = play_np[i]->volume;
play_np[i] = play_np[i]->to;
}
if (now_leng[i] == 0 )
PlayOrganObject(0, 2, i, info.tdata[i].freq);
if (now_leng[i] > 0)
now_leng[i]--;
if (play_np[i])
ChangeOrganVolume(play_np[i]->y, gOrgVolume * gTrackVol[i] / 0x7F, i);
}
for(int i = MAXMELODY; i < MAXTRACK; i++)
{
if (play_np[i] != NULL && play_p == play_np[i]->x)
{
if (play_np[i]->y != KEYDUMMY)
PlayDramObject(play_np[i]->y,1,i-MAXMELODY);
if(play_np[i]->pan != PANDUMMY)
ChangeDramPan(play_np[i]->pan,i-MAXMELODY);
if(play_np[i]->volume != VOLDUMMY)
gTrackVol[i] = play_np[i]->volume;
play_np[i] = play_np[i]->to;
}
if (play_np[i])
ChangeDramVolume(gOrgVolume * gTrackVol[i] / 0x7F, i - MAXMELODY);
}
//Looping
play_p++;
if(play_p >= info.end_x)
{
play_p = info.repeat_x;
SetPlayPointer(play_p);
}
}
void SetPlayPointer(int32_t x)
{
for (int i = 0; i < MAXTRACK; i++)
{
play_np[i] = info.tdata[i].note_list;
while (play_np[i] != NULL && play_np[i]->x < x)
play_np[i] = play_np[i]->to;
}
play_p = x;
}
//Load organya file
void LoadOrganya(char *name)
{
//Unload previous things
OrganyaReleaseNote();
memset(&info, 0, sizeof(info));
OrganyaNoteAlloc(0xFFFF);
//Stop currently playing notes
memset(play_np, 0, sizeof(play_np));
memset(old_key, 0xFF, sizeof(old_key));
memset(key_on, 0, sizeof(key_on));
memset(key_twin, 0, sizeof(key_twin));
memset(now_leng, 0, sizeof(now_leng));
//Open file
char path[PATH_LENGTH];
sprintf(path, "%s/Org/%s.org", gDataPath, name);
SDL_RWops *fp = SDL_RWFromFile(path, "rb");
if (!fp)
{
printf("Failed to open.org\nSDL Error: %s\n", SDL_GetError());
return;
}
//Version Check
uint8_t ver = 0;
char pass_check[6];
SDL_RWread(fp, &pass_check[0], sizeof(char), 6);
if (!memcmp(pass_check, "Org-01", 6))ver = 1;
if (!memcmp(pass_check, "Org-02", 6))ver = 2;
//if (!memcmp(pass_check, "Org-03", 6))ver = 2;
if (!ver)
{
printf("Failed to open.org, invalid version %s", pass_check);
return;
}
//Set song information
info.wait = SDL_ReadLE16(fp);
info.line = SDL_ReadU8(fp);
info.dot = SDL_ReadU8(fp);
info.repeat_x = SDL_ReadLE32(fp);
info.end_x = SDL_ReadLE32(fp);
for (int i = 0; i < 16; i++) {
info.tdata[i].freq = SDL_ReadLE16(fp);
info.tdata[i].wave_no = SDL_ReadU8(fp);
SDL_ReadU8(fp);
info.tdata[i].note_num = SDL_ReadLE16(fp);
}
//Load notes
NOTELIST *np;
for (int j = 0; j < 16; j++) {
//The first note from is NULL
if (info.tdata[j].note_num == 0) {
info.tdata[j].note_list = nullptr;
continue;
}
//Make note list
np = info.tdata[j].note_p;
info.tdata[j].note_list = info.tdata[j].note_p;
np->from = nullptr;
np->to = (np + 1);
np++;
for (int i = 1; i < info.tdata[j].note_num; i++) {
np->from = (np - 1);
np->to = (np + 1);
np++;
}
//The last note to is NULL
np--;
np->to = nullptr;
//Set note properties
np = info.tdata[j].note_p; //X position
for (int i = 0; i < info.tdata[j].note_num; i++) {
np->x = SDL_ReadLE32(fp);
np++;
}
np = info.tdata[j].note_p; //Y position
for (int i = 0; i < info.tdata[j].note_num; i++) {
np->y = SDL_ReadU8(fp);
np++;
}
np = info.tdata[j].note_p; //Length
for (int i = 0; i < info.tdata[j].note_num; i++) {
np->length = SDL_ReadU8(fp);
np++;
}
np = info.tdata[j].note_p; //Volume
for (int i = 0; i < info.tdata[j].note_num; i++) {
np->volume = SDL_ReadU8(fp);
np++;
}
np = info.tdata[j].note_p; //Pan
for (int i = 0; i < info.tdata[j].note_num; i++) {
np->pan = SDL_ReadU8(fp);
np++;
}
}
SDL_RWclose(fp);
//Create waves
for (int j = 0; j < 8; j++)
MakeOrganyaWave(j, info.tdata[j].wave_no);
//Reset position
SetPlayPointer(0);
//Set as loaded
info.loaded = true;
}
void SetOrganyaPosition(unsigned int x)
{
SetPlayPointer(x);
gOrgVolume = 100;
bFadeout = false;
}
unsigned int GetOrganyaPosition()
{
return play_p;
}
void PlayOrganyaMusic()
{
//Start timer
OrganyaStartTimer(info.wait);
}
bool ChangeOrganyaVolume(signed int volume)
{
if ( volume >= 0 && volume <= 100 )
{
gOrgVolume = volume;
return true;
}
return false;
}
void StopOrganyaMusic()
{
//Stop timer
OrganyaEndTimer();
//Stop notes
for (int i = 0; i < MAXMELODY; i++)
PlayOrganObject(0, 2, i, 0);
memset(old_key, 255, sizeof(old_key));
memset(key_on, 0, sizeof(key_on));
memset(key_twin, 0, sizeof(key_twin));
}
//Org timer
SDL_Thread *OrganyaTimer = nullptr;
bool bEndTimer = false;
int OrganyaPlayTimer(void *ptr)
{
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
//Set time for next step to play
uint32_t NextTick = SDL_GetTicks() + info.wait;
while (bEndTimer == false)
{
if (info.loaded)
{
//Play music
OrganyaPlayData();
//Wait until this step is over
while (NextTick > SDL_GetTicks())
SDL_Delay(1);
//Get time for next step to play
while (NextTick <= SDL_GetTicks())
NextTick += info.wait;
}
else
{
//Wait until the org is loaded
SDL_Delay(1);
}
}
return 0;
}
void OrganyaStartTimer(unsigned int wait)
{
OrganyaEndTimer();
bEndTimer = false;
OrganyaTimer = SDL_CreateThread(OrganyaPlayTimer, "OrganyaPlayTimer", (void*)NULL);
}
void OrganyaEndTimer()
{
bEndTimer = true; //Tell thread to end
SDL_WaitThread(OrganyaTimer, NULL); //Wait for thread to end
OrganyaTimer = nullptr;
}
//Start and end organya
void StartOrganya()
{
//Initialize org stuff
InitWaveData100();
}
void EndOrganya()
{
//End timer
OrganyaEndTimer();
//Release everything related to org
OrganyaReleaseNote();
DeleteWaveData100();
for (int i = 0; i < MAXMELODY; i++)
ReleaseOrganyaObject(i);
}

51
src/Organya.h Normal file
View file

@ -0,0 +1,51 @@
#pragma once
#include <stdint.h>
//Below are Organya song data structures
struct NOTELIST {
NOTELIST *from; //Previous address
NOTELIST *to; //Next address
int32_t x; //Position
unsigned char length; //Sound length
unsigned char y; //Sound height
unsigned char volume; //Volume
unsigned char pan;
};
//Track data * 8
struct TRACKDATA {
uint16_t freq; //Frequency (1000 is default)
uint8_t wave_no; //Waveform No.
uint16_t note_num; //Number of notes
NOTELIST *note_p;
NOTELIST *note_list;
};
//Unique information held in songs
struct MUSICINFO {
uint16_t wait;
bool loaded;
bool playing;
unsigned char line; //Number of lines in one measure
unsigned char dot; //Number of dots per line
uint16_t alloc_note; //Number of allocated notes
int32_t repeat_x; //Repeat
int32_t end_x; //End of song (Return to repeat)
TRACKDATA tdata[16];
};
bool MakeOrganyaWave(int8_t track, int8_t wave_no);
void OrganyaPlayData();
void SetPlayPointer(int32_t x);
void LoadOrganya(char *name);
void SetOrganyaPosition(unsigned int x);
unsigned int GetOrganyaPosition();
void PlayOrganyaMusic();
bool ChangeOrganyaVolume(signed int volume);
void StopOrganyaMusic();
void OrganyaStartTimer(unsigned int wait);
void OrganyaEndTimer();
void StartOrganya();
void EndOrganya();

288
src/PixTone.cpp Normal file
View file

@ -0,0 +1,288 @@
#include <cstdio>
#include <cstdlib>
#include <stdint.h>
#include <vector>
#include <cstring>
#include <math.h>
#include "CommonDefines.h"
#include "Tags.h"
#include "PixTone.h"
int8_t gWaveModelTable[6][0x100];
void MakeWaveTables()
{
/* Sine wave */
for (int i = 0; i < 0x100; i++)
gWaveModelTable[0][i] = (sin(i * 6.283184 / 256.0) * 64.0);
/* Triangle wave */
int triangle = 0;
for (int i = 0; i < 0x40; ++i) //Upwards
gWaveModelTable[1][i] = (triangle++ << 6) / 0x40;
triangle = 0;
for (int i = 0x40; i < 0xC0; ++i) //Downwards
gWaveModelTable[1][i] = 0x40 - (triangle++ << 6) / 0x40;
triangle = 0;
for (int i = 0xC0; i < 0x100; ++i) //Back upwards
gWaveModelTable[1][i] = (triangle++ << 6) / 0x40 - 0x40;
/* Saw up wave */
for (int i = 0; i < 0x100; i++)
gWaveModelTable[2][i] = i / 2 - 0x40;
/* Saw down wave */
for (int i = 0; i < 0x100; i++)
gWaveModelTable[3][i] = 0x40 - i / 2;
/* Square wave */
for (int i = 0; i < 0x80; i++)
gWaveModelTable[4][i] = 0x40;
for (int i = 0x80; i < 0x100; i++)
gWaveModelTable[4][i] = -0x40;
/* White noise wave */
srand(0);
for (int i = 0; i < 0x100; i++)
gWaveModelTable[5][i] = (int8_t)rand() / 2;
}
//Loading .pxt files
double fgetv(FILE *fp) // Load a numeric value from text file; one per line.
{
//Create buffer
char Buf[0x1000];
Buf[0xFFF] = '\0';
char *p = Buf;
if (!std::fgets(Buf, sizeof(Buf) - 1, fp))
return 0.0;
// Ignore empty lines. If the line was empty, try next line.
if (!Buf[0] || Buf[0] == '\r' || Buf[0] == '\n')
return fgetv(fp);
while (*p && *p++ != ':')
{
}
return std::strtod(p, 0); // Parse the value and return it.
}
bool MakePixelWaveData(const std::vector<double>& pxtData, uint8_t *data)
{
//Get some envelope stuff
char envelopeTable[0x100];
memset(envelopeTable, 0, sizeof(envelopeTable));
size_t i = 0;
//Point A
long double currentEnvelope = pxtData[14];
while (i < pxtData[15])
{
envelopeTable[i] = (char)currentEnvelope;
currentEnvelope = (pxtData[16] - pxtData[14])
/ pxtData[15]
+ currentEnvelope;
++i;
}
//Point B
long double currentEnvelopea = pxtData[16];
while (i < pxtData[17])
{
envelopeTable[i] = (char)currentEnvelopea;
currentEnvelopea = (pxtData[18] - pxtData[16])
/ (pxtData[17] - pxtData[15])
+ currentEnvelopea;
++i;
}
//Point C
long double currentEnvelopeb = pxtData[18];
while (i < pxtData[19])
{
envelopeTable[i] = (char)currentEnvelopeb;
currentEnvelopeb = (pxtData[20] - pxtData[18])
/ (pxtData[19] - pxtData[17])
+ currentEnvelopeb;
++i;
}
//End
long double currentEnvelopec = pxtData[20];
while (i < 0x100)
{
envelopeTable[i] = (char)currentEnvelopec;
currentEnvelopec = currentEnvelopec
- pxtData[20] / (0x100 - pxtData[19]);
++i;
}
long double pitchOffset = pxtData[9];
long double mainOffset = pxtData[5];
long double volumeOffset = pxtData[13];
//Main
long double mainFreq;
if (pxtData[3] == 0.0)
mainFreq = 0.0;
else
mainFreq = 256.0 / (pxtData[1] / pxtData[3]);
//Pitch
long double pitchFreq;
if (pxtData[7] == 0.0)
pitchFreq = 0.0;
else
pitchFreq = 256.0 / (pxtData[1] / pxtData[7]);
//Volume
long double volumeFreq;
if (pxtData[11] == 0.0)
volumeFreq = 0.0;
else
volumeFreq = 256.0 / (pxtData[1] / pxtData[11]);
for (i = 0; i < pxtData[1]; ++i)
{
const int a = (int)(uint64_t)mainOffset % 256;
const int v2 = (int)(uint64_t)pitchOffset % 256;
//Input data
data[i] = envelopeTable[(unsigned __int64)((long double)(i << 8) / pxtData[1])]
* (pxtData[4]
* gWaveModelTable[(size_t)pxtData[2]][a]
/ 0x40
* (pxtData[12]
* gWaveModelTable[(size_t)pxtData[10]][(signed int)(uint64_t)volumeOffset % 0x100]
/ 0x40
+ 0x40)
/ 0x40)
/ 0x40
+ 0x80;
long double newMainOffset;
if (gWaveModelTable[(size_t)pxtData[6]][v2] >= 0)
newMainOffset = (mainFreq * 2)
* (long double)gWaveModelTable[(size_t)pxtData[6]][(signed int)(unsigned __int64)pitchOffset % 256]
* pxtData[8]
/ 64.0
/ 64.0
+ mainFreq
+ mainOffset;
else
newMainOffset = mainFreq
- mainFreq
* 0.5
* (long double)-gWaveModelTable[(size_t)pxtData[6]][v2]
* pxtData[8]
/ 64.0
/ 64.0
+ mainOffset;
mainOffset = newMainOffset;
pitchOffset = pitchOffset + pitchFreq;
volumeOffset = volumeOffset + volumeFreq;
}
return true;
}
bool LoadPxt(char *name, uint8_t **buf, size_t *length)
{
//Open file
char path[PATH_LENGTH];
sprintf(path, "%s/Sound/%s", gDataPath, name);
FILE *fp = fopen(path, "rb");
if (!fp)
return false;
//Read data
std::vector<double> lineNumbers[4];
for (int i = 0; i < 4; ++i)
{
for (int j = 0; j < 21; j++)
{
double val = fgetv(fp);
lineNumbers[i].push_back(val);
}
}
//Close file
fclose(fp);
//Get size
size_t size;
for (int i = 0; i < 4; i++)
{
if (lineNumbers[i][1] > size)
size = (size_t)lineNumbers[i][1];
}
//Allocate buffers
uint8_t *dest = (uint8_t*)malloc(size);
uint8_t *pBlock = (uint8_t*)malloc(size);
if (dest && pBlock)
{
//Set buffers to default value of 0x80
memset(dest, 0x80, size);
memset(pBlock, 0x80, size);
for (int i = 0; i < 4; ++i)
{
//Get wave data
if (!MakePixelWaveData(lineNumbers[i], dest))
{
printf("MakePixelWaveData failed for %s\n", name);
free(dest);
free(pBlock);
return -1;
}
//Put data into buffer
for (int j = 0; j < lineNumbers[i][1]; ++j)
{
if (dest[j] + pBlock[j] - 0x100 >= -0x7F)
{
if (dest[j] + pBlock[j] - 0x100 <= 0x7F)
pBlock[j] += dest[j] - 0x80;
else
pBlock[j] = (uint8_t)-1;
}
else
{
pBlock[j] = 0;
}
}
}
//Put data from buffers into main sound buffer
*buf = (uint8_t*)malloc(size);
if (!*buf)
{
printf("Failed to allocate buffer for %s\n", name);
free(dest);
free(pBlock);
return false;
}
*length = size;
memcpy(*buf, pBlock, size);
//Free the two buffers
free(dest);
free(pBlock);
return true;
}
printf("Failed to allocate dest or pBlock for %s\n", name);
free(dest);
free(pBlock);
return false;
}

5
src/PixTone.h Normal file
View file

@ -0,0 +1,5 @@
#pragma once
#include <stdint.h>
void MakeWaveTables();
bool LoadPxt(char *name, uint8_t **buf, size_t *length);

24
src/Profile.cpp Normal file
View file

@ -0,0 +1,24 @@
#include <stdint.h>
#include <SDL_rwops.h>
#include "WindowsWrapper.h"
#include "CommonDefines.h"
#include "Tags.h"
#include "Profile.h"
const char *gDefaultName = "Profile.dat";
const char *gProfileCode = "Do041220";
bool IsProfile()
{
char path[PATH_LENGTH];
sprintf(path, "%s/%s", gModulePath, gDefaultName);
SDL_RWops *fp = SDL_RWFromFile(path, "rb");
if (!fp)
return false;
SDL_RWclose(fp);
return true;
}

4
src/Profile.h Normal file
View file

@ -0,0 +1,4 @@
#pragma once
#include <stdint.h>
bool IsProfile();

324
src/Sound.cpp Normal file
View file

@ -0,0 +1,324 @@
#include <string>
#include <math.h>
#include <algorithm>
#include <stdint.h>
#include <SDL_audio.h>
#include "Sound.h"
#include "Organya.h"
#include "PixTone.h"
#define FREQUENCY 44100
#define STREAM_SIZE (FREQUENCY / 100)
#define clamp(x, y, z) ((x > z) ? z : (x < y) ? y : x)
//Audio device
SDL_AudioDeviceID audioDevice;
//Keep track of all existing sound buffers
SOUNDBUFFER *soundBuffers;
//Sound buffer code
SOUNDBUFFER::SOUNDBUFFER(size_t bufSize)
{
//Lock audio buffer
SDL_LockAudioDevice(audioDevice);
//Set parameters
size = bufSize;
playing = false;
looping = false;
frequency = 0.0;
volume = 1.0;
volume_l = 1.0;
volume_r = 1.0;
samplePosition = 0.0;
//Create waveform buffer
data = new uint8_t[bufSize];
memset(data, 0x80, bufSize);
//Add to buffer list
this->next = soundBuffers;
soundBuffers = this;
//Unlock audio buffer
SDL_UnlockAudioDevice(audioDevice);
}
SOUNDBUFFER::~SOUNDBUFFER()
{
//Lock audio buffer
SDL_LockAudioDevice(audioDevice);
//Free buffer
if (data)
delete[] data;
//Remove from buffer list
for (SOUNDBUFFER **soundBuffer = &soundBuffers; *soundBuffer != nullptr; soundBuffer = &(*soundBuffer)->next)
{
if (*soundBuffer == this)
{
*soundBuffer = this->next;
break;
}
}
//Unlock audio buffer
SDL_UnlockAudioDevice(audioDevice);
}
void SOUNDBUFFER::Release()
{
//TODO: find a better and more stable(?) way to handle this function
delete this;
}
void SOUNDBUFFER::Lock(uint8_t **outBuffer, size_t *outSize)
{
SDL_LockAudioDevice(audioDevice);
if (outBuffer != nullptr)
*outBuffer = data;
if (outSize != nullptr)
*outSize = size;
}
void SOUNDBUFFER::Unlock()
{
SDL_UnlockAudioDevice(audioDevice);
}
void SOUNDBUFFER::SetCurrentPosition(uint32_t dwNewPosition)
{
SDL_LockAudioDevice(audioDevice);
samplePosition = dwNewPosition;
SDL_UnlockAudioDevice(audioDevice);
}
void SOUNDBUFFER::SetFrequency(uint32_t dwFrequency)
{
SDL_LockAudioDevice(audioDevice);
frequency = (double)dwFrequency;
SDL_UnlockAudioDevice(audioDevice);
}
float MillibelToVolume(int32_t lVolume)
{
//Volume is in hundredths of decibels, from 0 to -10000
lVolume = clamp(lVolume, (decltype(lVolume))-10000, (decltype(lVolume))0);
return pow(10.0f, lVolume / 2000.0f);
}
void SOUNDBUFFER::SetVolume(int32_t lVolume)
{
SDL_LockAudioDevice(audioDevice);
volume = MillibelToVolume(lVolume);
SDL_UnlockAudioDevice(audioDevice);
}
void SOUNDBUFFER::SetPan(int32_t lPan)
{
SDL_LockAudioDevice(audioDevice);
volume_l = MillibelToVolume(-lPan);
volume_r = MillibelToVolume(lPan);
SDL_UnlockAudioDevice(audioDevice);
}
void SOUNDBUFFER::Play(bool bLooping)
{
SDL_LockAudioDevice(audioDevice);
playing = true;
looping = bLooping;
SDL_UnlockAudioDevice(audioDevice);
}
void SOUNDBUFFER::Stop()
{
SDL_LockAudioDevice(audioDevice);
playing = false;
SDL_UnlockAudioDevice(audioDevice);
}
void SOUNDBUFFER::Mix(float *buffer, int len)
{
if (!playing) //This sound buffer isn't playing
return;
size_t samples = len / (sizeof(float) * 2);
for (size_t sample = 0; sample < samples; sample++)
{
double freqPosition = (frequency / (double)FREQUENCY); //This is added to position at the end
//Get the in-between sample this is (linear interpolation)
uint8_t sample1 = ((looped || ((size_t)samplePosition) >= 1) ? data[(size_t)samplePosition] : 0x80);
uint8_t sample2 = 0x80;
if (looping || (((size_t)samplePosition) + 1) < size)
sample2 = data[(((size_t)samplePosition) + 1) % size];
//Interpolate sample
float subPos = std::fmod(samplePosition, 1.0);
float sampleA = (float)sample1 + ((float)sample2 - (float)sample1) * subPos;
//Convert sample to float32
float sampleConvert = (sampleA - 128.0) / 256.0;
//Mix
buffer[sample * 2] += sampleConvert * volume * volume_l;
buffer[sample * 2 + 1] += sampleConvert * volume * volume_r;
//Increment position
samplePosition += freqPosition;
if (samplePosition >= size)
{
if (looping)
{
samplePosition = std::fmod(samplePosition, size);
looped = true;
}
else
{
samplePosition = 0.0;
playing = false;
looped = false;
break;
}
}
}
}
//Sound mixer
void AudioCallback(void *userdata, uint8_t *stream, int len)
{
//Clear stream
memset(stream, 0, len);
//Mix sounds to primary buffer
for (SOUNDBUFFER *sound = soundBuffers; sound != nullptr; sound = sound->next)
{
sound->Mix((float*)stream, len);
}
}
//Sound things
SOUNDBUFFER* lpSECONDARYBUFFER[SOUND_NO];
bool InitDirectSound()
{
SDL_AudioSpec want, have;
//Set specifications we want
SDL_memset(&want, 0, sizeof(want));
want.freq = FREQUENCY;
want.format = AUDIO_F32;
want.channels = 2;
want.samples = STREAM_SIZE;
want.callback = AudioCallback;
audioDevice = SDL_OpenAudioDevice(NULL, 0, &want, &have, 0);
if (audioDevice == 0)
{
printf("Failed to open audio device\nSDL Error: %s\n", SDL_GetError());
return false;
}
//Unpause audio device
SDL_PauseAudioDevice(audioDevice, 0);
//Start organya
StartOrganya();
//Load sound effects
MakeWaveTables();
char path[0x100];
uint8_t *buf = nullptr;
size_t len;
for (size_t n = 0; n < SOUND_NO; n++)
{
sprintf(path, "%2.2X.pxt", n);
if (LoadPxt(path, &buf, &len))
{
lpSECONDARYBUFFER[n] = new SOUNDBUFFER(len);
uint8_t *sBuf;
size_t sLen;
lpSECONDARYBUFFER[n]->Lock(&sBuf, &sLen);
memcpy(sBuf, buf, sLen);
lpSECONDARYBUFFER[n]->Unlock();
lpSECONDARYBUFFER[n]->SetFrequency(22050);
}
//Free buffer, we're done with it
if (buf)
{
free(buf);
buf = nullptr;
}
}
return true;
}
void EndDirectSound()
{
//Close audio device
SDL_CloseAudioDevice(audioDevice);
//End organya
EndOrganya();
}
//Sound effects playing
void PlaySoundObject(int no, int mode)
{
if (lpSECONDARYBUFFER[no])
{
if (mode == -1)
{
lpSECONDARYBUFFER[no]->Play(true);
}
else if ( mode )
{
if ( mode == 1 )
{
lpSECONDARYBUFFER[no]->Stop();
lpSECONDARYBUFFER[no]->SetCurrentPosition(0);
lpSECONDARYBUFFER[no]->Play(false);
}
}
else
{
lpSECONDARYBUFFER[no]->Stop();
}
}
}
void ChangeSoundFrequency(int no, uint32_t rate)
{
if (lpSECONDARYBUFFER[no])
lpSECONDARYBUFFER[no]->SetFrequency(10 * rate + 100);
}
void ChangeSoundVolume(int no, int32_t volume)
{
if (lpSECONDARYBUFFER[no])
lpSECONDARYBUFFER[no]->SetVolume(8 * volume - 2400);
}
void ChangeSoundPan(int no, int32_t pan)
{
if (lpSECONDARYBUFFER[no])
lpSECONDARYBUFFER[no]->SetPan(10 * (pan - 256));
}

96
src/Sound.h Normal file
View file

@ -0,0 +1,96 @@
#pragma once
#include <stdint.h>
class SOUNDBUFFER
{
public:
SOUNDBUFFER(size_t bufSize);
~SOUNDBUFFER();
void Release();
void Lock(uint8_t **buffer, size_t *size);
void Unlock();
void SetCurrentPosition(uint32_t dwNewPosition);
void SetFrequency(uint32_t dwFrequency);
void SetVolume(int32_t lVolume);
void SetPan(int32_t lPan);
void Play(bool bLooping);
void Stop();
void Mix(float *buffer, int len);
SOUNDBUFFER *next;
private:
uint8_t *data;
size_t size;
bool playing;
bool looping;
bool looped;
double frequency;
double volume;
double volume_l;
double volume_r;
double samplePosition;
};
//Music ID enum
enum MUSIC_IDS
{
mus_Silence = 0x0,
mus_MischievousRobot = 0x1,
mus_Safety = 0x2,
mus_GameOver = 0x3,
mus_Gravity = 0x4,
mus_OnToGrasstown = 0x5,
mus_Meltdown2 = 0x6,
mus_EyesOfFlame = 0x7,
mus_Gestation = 0x8,
mus_MimigaTown = 0x9,
mus_GetItem = 0xA,
mus_BalrogsTheme = 0xB,
mus_Cemetary = 0xC,
mus_Plant = 0xD,
mus_Pulse = 0xE,
mus_Victory = 0xF,
mus_GetLifeCapsule = 0x10,
mus_Tyrant = 0x11,
mus_Run = 0x12,
mus_Jenka1 = 0x13,
mus_LabyrinthFight = 0x14,
mus_Access = 0x15,
mus_Oppression = 0x16,
mus_Geothermal = 0x17,
mus_CaveStory = 0x18,
mus_Moonsong = 0x19,
mus_Herosend = 0x1A,
mus_ScorchingBack = 0x1B,
mus_Quiet = 0x1C,
mus_FinalCave = 0x1D,
mus_Balcony = 0x1E,
mus_Charge = 0x1F,
mus_LastBattle = 0x20,
mus_TheWayBackHome = 0x21,
mus_Zombie = 0x22,
mus_BreakDown = 0x23,
mus_RunningHell = 0x24,
mus_Jenka2 = 0x25,
mus_LivingWaterway = 0x26,
mus_SealChamber = 0x27,
mus_TorokosTheme = 0x28,
mus_White = 0x29,
};
#define SOUND_NO 0x100
extern SOUNDBUFFER* lpSECONDARYBUFFER[SOUND_NO];
bool InitDirectSound();
void EndDirectSound();
void PlaySoundObject(int no, int mode);
void ChangeSoundFrequency(int no, uint32_t rate);
void ChangeSoundVolume(int no, int32_t volume);
void ChangeSoundPan(int no, int32_t pan);

229
src/Stage.cpp Normal file
View file

@ -0,0 +1,229 @@
#include <stdint.h>
#include <string.h>
#include <SDL_rwops.h>
#include "WindowsWrapper.h"
#include "CommonDefines.h"
#include "Map.h"
#include "MapName.h"
#include "Draw.h"
#include "Tags.h"
#include "NpChar.h"
#include "TextScr.h"
#include "Organya.h"
#include "Back.h"
#include "Stage.h"
STAGE_TABLE *gTMT;
int gStageNo;
//Stage table functions
bool InitStageTable()
{
//Get path
char path[PATH_LENGTH];
sprintf(path, "%s/stage.tbl", gDataPath);
//Open file
SDL_RWops *fp = SDL_RWFromFile(path, "rb");
if (!fp)
return false;
//Get amount of stages and allocate stage data
size_t stages = SDL_RWsize(fp) / 0xC8;
gTMT = (STAGE_TABLE*)calloc(stages, sizeof(STAGE_TABLE));
//Read data
for (size_t i = 0; i < stages; i++)
{
SDL_RWread(fp, &gTMT[i].parts, 1, 0x20);
SDL_RWread(fp, &gTMT[i].map, 1, 0x20);
gTMT[i].bkType = SDL_ReadLE32(fp);
SDL_RWread(fp, &gTMT[i].back, 1, 0x20);
SDL_RWread(fp, &gTMT[i].npc, 1, 0x20);
SDL_RWread(fp, &gTMT[i].boss, 1, 0x20);
gTMT[i].boss_no = SDL_ReadU8(fp);
SDL_RWread(fp, &gTMT[i].name, 1, 0x20);
//Padding (3 bytes)
uint8_t nul[3];
SDL_RWread(fp, &nul, 1, 3);
}
SDL_RWclose(fp);
return true;
}
void ReleaseStageTable()
{
free(gTMT);
gTMT = nullptr;
}
bool TransferStage(int no, int w, int x, int y)
{
//Move character
//SetMyCharPosition(x << 13, y << 13);
bool bError = false;
bool result;
//Get path
char path_dir[20];
strcpy(path_dir, "Stage");
//Load tileset
char path[PATH_LENGTH];
sprintf(path, "%s/Prt%s", path_dir, gTMT[no].parts);
if (!ReloadBitmap_File(path, SURFACE_ID_LEVEL_TILESET))
bError = true;
sprintf(path, "%s/%s.pxa", path_dir, gTMT[no].parts);
if (!LoadAttributeData(path))
bError = true;
//Load tilemap
sprintf(path, "%s/%s.pxm", path_dir, gTMT[no].map);
if (!LoadMapData2(path))
bError = true;
//Load NPCs
sprintf(path, "%s/%s.pxe", path_dir, gTMT[no].map);
if (!LoadEvent(path))
bError = true;
//Load script
sprintf(path, "%s/%s.tsc", path_dir, gTMT[no].map);
if (!LoadTextScript_Stage(path))
bError = true;
//Load background
strcpy(path, gTMT[no].back);
if (!InitBack(path, gTMT[no].bkType))
bError = true;
//Get path
strcpy(path_dir, "Npc");
//Load NPC sprite sheets
sprintf(path, "%s/Npc%s", path_dir, gTMT[no].npc);
if (!ReloadBitmap_File(path, SURFACE_ID_LEVEL_SPRITESET_1))
bError = true;
sprintf(path, "%s/Npc%s", path_dir, gTMT[no].boss);
if (!ReloadBitmap_File(path, SURFACE_ID_LEVEL_SPRITESET_2))
bError = true;
if (bError)
{
printf("Failed to load stage %d\n", no);
return false;
}
else
{
//Load map name
ReadyMapName(gTMT[no].name);
//StartTextScript(w);
//SetFrameMyChar();
//ClearBullet();
//InitCaret();
//ClearValueView();
//ResetQuake();
//InitBossChar(gTMT[no].boss_no);
//ResetFlash();
gStageNo = no;
return true;
}
return false;
}
//Music
const char *gMusicTable[42] =
{
"xxxx",
"wanpaku",
"anzen",
"gameover",
"gravity",
"weed",
"mdown2",
"fireeye",
"vivi",
"mura",
"fanfale1",
"ginsuke",
"cemetery",
"plant",
"kodou",
"fanfale3",
"fanfale2",
"dr",
"escape",
"jenka",
"maze",
"access",
"ironh",
"grand",
"curly",
"oside",
"requiem",
"wanpak2",
"quiet",
"lastcave",
"balcony",
"lastbtl",
"lastbt3",
"ending",
"zonbie",
"breakdown",
"hell",
"jenka2",
"marine",
"ballos",
"toroko",
"white"
};
unsigned int gOldPos;
int gOldNo;
int gMusicNo;
void ChangeMusic(int no)
{
//Stop and keep track of old song
gOldPos = GetOrganyaPosition();
gOldNo = gMusicNo;
StopOrganyaMusic();
//Load .org
char *name = (char*)malloc(strlen(gMusicTable[no]) + 1);
strcpy(name, gMusicTable[no]);
LoadOrganya(name);
//Reset position, volume, and then play the song
ChangeOrganyaVolume(100);
SetOrganyaPosition(0);
PlayOrganyaMusic();
gMusicNo = no;
}
void ReCallMusic()
{
//Stop old song
StopOrganyaMusic();
//Load .org that was playing before
char *name = (char*)malloc(strlen(gMusicTable[gOldNo]) + 1);
strcpy(name, gMusicTable[gOldNo]);
LoadOrganya(name);
//Reset position, volume, and then play the song
SetOrganyaPosition(gOldPos);
ChangeOrganyaVolume(100);
PlayOrganyaMusic();
gMusicNo = gOldNo;
}

19
src/Stage.h Normal file
View file

@ -0,0 +1,19 @@
#pragma once
struct STAGE_TABLE
{
char parts[0x20];
char map[0x20];
int bkType;
char back[0x20];
char npc[0x20];
char boss[0x20];
char boss_no;
char name[0x20];
};
bool InitStageTable();
void ReleaseStageTable();
bool TransferStage(int no, int w, int x, int y);
void ChangeMusic(int no);
void ReCallMusic();

View file

@ -1,8 +1,10 @@
#include <stdint.h>
#include <string>
#include "CommonDefines.h"
#include "TextScr.h"
#include "Draw.h"
#include "Tags.h"
#include "Game.h"
#define TSC_BUFFER_SIZE 0x5000
@ -61,3 +63,42 @@ void EncryptionBinaryData2(uint8_t *pData, int size)
pData[i] += val1;
}
}
//Load stage .tsc
bool LoadTextScript_Stage(char *name)
{
//Open Head.tsc
char path[PATH_LENGTH];
sprintf(path, "%s/%s", gDataPath, "Head.tsc");
SDL_RWops *fp = SDL_RWFromFile(path, "rb");
if (!fp)
return false;
//Read Head.tsc
int head_size = SDL_RWsize(fp);
fp->read(fp, gTS.data, 1, head_size);
EncryptionBinaryData2((uint8_t*)gTS.data, head_size);
gTS.data[head_size] = 0;
SDL_RWclose(fp);
//Open stage's .tsc
sprintf(path, "%s/%s", gDataPath, name);
fp = SDL_RWFromFile(path, "rb");
if (!fp)
return false;
//Read stage's tsc
int body_size = SDL_RWsize(fp);
fp->read(fp, &gTS.data[head_size], 1, body_size);
EncryptionBinaryData2((uint8_t*)&gTS.data[head_size], body_size);
gTS.data[head_size + body_size] = 0;
SDL_RWclose(fp);
//Set parameters
gTS.size = head_size + body_size;
strcpy(gTS.path, name);
return true;
}

View file

@ -57,3 +57,4 @@ struct TEXT_SCRIPT
bool InitTextScript2();
void EndTextScript();
void EncryptionBinaryData2(uint8_t *pData, int size);
bool LoadTextScript_Stage(char *name);