@@ -0,0 +1,129 @@
#include "npc120.h"

void npcAct139(npc *NPC)
{
RECT rcLeft[3];
RECT rcRight[3];

rcLeft[0] = { 0, 128, 24, 160 };
rcLeft[1] = { 24, 128, 48, 160 };
rcLeft[2] = { 48, 128, 72, 160 };

rcRight[0] = { 0, 160, 24, 192 };
rcRight[1] = { 24, 160, 48, 192 };
rcRight[2] = { 48, 160, 72, 192 };

switch (NPC->act_no)
{
case 0: //Stand
NPC->act_no = 1;
NPC->xm = 0;
NPC->ym = 0;
NPC->y -= 0x1000;

case 1:
if (NPC->flag & ground)
NPC->ani_no = 0;
else
NPC->ani_no = 2;

NPC->ym += 0x40;
break;

case 10: //Laughing his ass off
NPC->act_no = 11;
NPC->ani_no = 1;
NPC->ani_wait = 0;
NPC->count1 = 0;

case 11:
if (++NPC->ani_wait > 6)
{
NPC->ani_wait = 0;
++NPC->ani_no;
}

if (NPC->ani_no > 1)
{
NPC->ani_no = 0;
++NPC->count1;
}

if (NPC->count1 > 8)
{
NPC->ani_no = 0;
NPC->act_no = 1;
}

break;

case 20: //Floating
NPC->act_no = 21;
NPC->act_wait = 0;
NPC->ani_no = 2;
NPC->tgt_y = NPC->y - 0x4000;

case 21:
if (NPC->y >= NPC->tgt_y)
NPC->ym -= 0x20;
else
NPC->ym += 0x20;

if (NPC->ym > 0x200)
NPC->ym = 0x200;
if (NPC->ym < -0x200)
NPC->ym = -0x200;

break;

case 30: //Teleport away and then stop existing altogether
NPC->act_no = 31;
NPC->xm = 0;
NPC->ym = 0;
NPC->act_wait = 2 * (NPC->rect.bottom - NPC->rect.top);
//PlaySoundObject(29, 1);

case 31:
--NPC->act_wait;
NPC->ani_no = 0;

if (!NPC->act_wait)
NPC->cond = 0;

break;

case 40: //Teleport in, then float
NPC->act_no = 41;
NPC->act_wait = 0;
NPC->xm = 0;
NPC->ym = 0;
//PlaySoundObject(29, 1);

case 41:
NPC->ani_no = 2;

if (++NPC->act_wait >= 64)
NPC->act_no = 20;

break;

default:
break;
}

NPC->x += NPC->xm;
NPC->y += NPC->ym;

if (NPC->direct)
NPC->rect = rcRight[NPC->ani_no];
else
NPC->rect = rcLeft[NPC->ani_no];

if (NPC->act_no == 31 || NPC->act_no == 41)
{
NPC->rect.bottom = NPC->act_wait / 2 + NPC->rect.top;

if (NPC->act_wait / 2 & 1)
++NPC->rect.left;
}
}
@@ -0,0 +1,4 @@
#pragma once
#include "common.h"

void npcAct139(npc *NPC);
@@ -0,0 +1,81 @@
#include "npc140.h"

void npcAct145(npc *NPC) //King's blade
{
RECT rcLeft = { 96, 32, 112, 48 };
RECT rcRight = { 112, 32, 128, 48 };

if (!NPC->act_no)
{
//Some orientation stuff
if (NPC->pNpc->count2)
{
if (NPC->pNpc->direct)
NPC->direct = 0;
else
NPC->direct = 2;
}
else if (NPC->pNpc->direct)
{
NPC->direct = 2;
}
else
{
NPC->direct = 0;
}

//Set position
if (NPC->direct)
NPC->x = NPC->pNpc->x + 0x1400;
else
NPC->x = NPC->pNpc->x - 0x1400;
NPC->y = NPC->pNpc->y;
}

//Set framerect
if (NPC->direct)
NPC->rect = rcRight;
else
NPC->rect = rcLeft;
}

void npcAct146(npc *NPC)
{
switch (NPC->act_no)
{
case 0:
NPC->act_no = 1;

//if (NPC->direct == 2)
// SetFlash(0, 0, 2);

case 1:
if (++NPC->act_wait > 10)
{
NPC->act_no = 2;
//PlaySoundObject(101, 1);
}
break;

case 2:
if (++NPC->ani_wait > 2)
{
NPC->ani_wait = 0;
++NPC->ani_no;
}

if (NPC->ani_no == 2)
NPC->damage = 10;

if (NPC->ani_no > 4)
{
createSmoke(NPC->x, NPC->y, 0x1000, 8);
NPC->cond = 0;
}

default:
break;
}

NPC->rect = { 260 + (NPC->ani_no * 15), 0, 275 + (NPC->ani_no * 15), 240 };
}
@@ -0,0 +1,5 @@
#pragma once
#include "common.h"

void npcAct145(npc *NPC);
void npcAct146(npc *NPC);
@@ -6,6 +6,8 @@
#include "npc060.h"
#include "npc080.h"
#include "npc100.h"
#include "npc120.h"
#include "npc140.h"

#include "npc180.h"
#include "npc200.h"
@@ -157,14 +159,14 @@ npcAct npcActs[] =
&npcActNone,
&npcActNone,
&npcActNone,
&npcAct139,
&npcActNone,
&npcActNone,
&npcActNone,
&npcActNone,
&npcActNone,
&npcActNone,
&npcActNone,
&npcActNone,
&npcAct145,
&npcAct146,
&npcActNone,
&npcActNone,
&npcActNone,
@@ -8,6 +8,12 @@ void player::init() {
direct = 2;
view = { 0x1000, 0x1000, 0x1000, 0x1000 };
hit = { 0xA00, 0x1000, 0xA00, 0x1000 };

viewGoalX = &tgt_x;
viewGoalY = &tgt_y;

viewSpeed = 16;

life = 3;
max_life = 3;
gamePhysics = 0;
@@ -17,8 +23,8 @@ void player::setPos(int setX, int setY) {
x = setX;
y = setY;

viewGoalX = x;
viewGoalY = y;
tgt_x = x;
tgt_y = y;
index_x = 0;
index_y = 0;

@@ -476,6 +482,7 @@ void player::actNormal(bool bKey) {
if (index_x < -0x8000)
index_x = -0x8000;
}

if (bKey && isKeyDown(keyUp))
{
//Move up
@@ -502,8 +509,8 @@ void player::actNormal(bool bKey) {
index_y += 0x200;
}

viewGoalX = x + index_x;
viewGoalY = y + index_y;
tgt_x = x + index_x;
tgt_y = y + index_y;

//Move
if (xm > resist || xm < -resist)
@@ -1,12 +1,14 @@
#include "common.h"

SDL_Rect drawRectangle = {0};
SDL_Rect drawRectangle = { 0 };

int screenWidth = 0;
int screenHeight = 0;

int screenScale = 0;

int windowFlags = 0;

//Create window
int createWindow(int width, int height, int scale, bool fullscreen) {
int createWidth = width * scale;
@@ -18,19 +20,29 @@ int createWindow(int width, int height, int scale, bool fullscreen) {

//Set window
if (!window)
window = SDL_CreateWindow("Cave Story Engine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, createWidth, createHeight, 0);
window = SDL_CreateWindow("Cave Story Engine",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
createWidth, createHeight,
NULL);
else
SDL_SetWindowSize(window, createWidth, createHeight);

//Set renderer
if (!renderer)
renderer = SDL_CreateRenderer(window, -1, 0);

SDL_RenderSetLogicalSize(renderer, screenWidth, screenHeight); //This is done to make sure the view is scaled up to the window (hardware sided)
SDL_RenderSetLogicalSize(renderer, screenWidth, screenHeight);

return 0;
}

void switchScreenMode()
{
windowFlags ^= SDL_WINDOW_FULLSCREEN_DESKTOP;
SDL_SetWindowFullscreen(window, windowFlags);
return;
}

//Texture and drawing stuff
void loadImage(const char *file, SDL_Texture **tex) {
//Destroy previously existing texture and load new one
@@ -60,6 +72,7 @@ void drawTexture(SDL_Texture *texture, RECT *rect, int x, int y) {
return;
}


void drawNumber(int value, int x, int y, bool bZero)
{
RECT numbRect;
@@ -30,6 +30,7 @@ enum TextureNums
};

int createWindow(int width, int height, int scale, bool fullscreen);
void switchScreenMode();

void loadImage(const char *file, SDL_Texture **tex);

@@ -54,7 +54,8 @@ int msgBoxY = 0;
// -- display variables --
int tscNumber = 0;
int faceX = 0;
int gitNo;
int gitNo = 0;
int ynjBoxYOffset = 0;


RECT rcFrame1 = { 0, 0, 244, 8 };
@@ -169,16 +170,16 @@ void jumpScriptEvent(int event_num)
}

//renders a line of text
void renderTextLine(int x, int y, char* str)
void renderTextLine(int x, int y, char *str)
{
SDL_Rect rcChar = { 0, 0, charWidth, charHeight };
SDL_Rect dest = { 0, y, charWidth, charHeight };

for (size_t c = 0; c < strlen(str); c++)
{
rcChar.x = (charWidth << 1) + (((str[c] - 0x20) % 32)*charWidth);
rcChar.y = (charHeight << 1) + (((str[c] - 0x20) >> 5)*charHeight);
dest.x = x + (c*charWidth);
rcChar.x = ((str[c] - 0x20) % 32) * charWidth;
rcChar.y = ((str[c] - 0x20) >> 5) * charHeight;
dest.x = x + (c * charWidth);
SDL_RenderCopy(renderer, font, &rcChar, &dest);
}
return;
@@ -201,6 +202,7 @@ void updateMessageBox()
{
strncat(msgText, &tsc[tscPos], 1);
tscPos++;
playSound(2);
}
}

@@ -257,7 +259,7 @@ void drawMessageBox(int x, int y, char* str)
}
rcChar.x = (((str[c] - 0x20) % 32)*charWidth);
rcChar.y = (((str[c] - 0x20) >> 5)*charHeight);
dest.x = 8 + x + (charX*charWidth) + charWidth;
dest.x = 8 + x + (charX*charWidth) + charWidth + textOffset;
dest.y = 8 + y + ((lineY*charHeight * 4) / 3) + 1 - scrollOffset;

SDL_RenderCopy(renderer, font, &rcChar, &dest);
@@ -273,8 +275,9 @@ int mapNameDisplayTimer = 0;
void drawTSC()
{
RECT rcGit = { 0, 0, 32, 16 };
SDL_Rect rcClip = { 0, 0, 0, 0 };

if (tscMode != 0 && (tscDisplayFlags & TSCVIS) == 1)
if (tscMode != 0 && tscDisplayFlags & TSCVIS)
{

if (tscDisplayFlags & 0x20)
@@ -291,22 +294,25 @@ void drawTSC()
if (tscDisplayFlags & MSGbox)
{
drawMessageBox(msgBoxX, msgBoxY, msgText);
}

//displaying face
if (faceNo) { textOffset = 56; }
else { textOffset = 0; }
rcFace.left = 48 * (faceNo % 6);
rcFace.top = 48 * (faceNo / 6);
rcFace.right = rcFace.left + 48;
rcFace.bottom = rcFace.top + 48;

if (faceX <= 26623) { faceX += 4096; }
drawTexture(sprites[TEX_FACE], &rcFace, faceX, rcView.top - 3);

for (int i = 0; i <= 3; ++i)
{
//drawTexture(sprites[i + 30], &gRect_line, textOffset + 52, + dword_81D59CC[i + 68] + rcView.top);
//displaying face
if (faceNo)
{
textOffset = 48;
rcClip = { msgBoxX + 8, msgBoxY + 8, 48, 48 };

rcFace.left = 48 * (faceNo % 6);
rcFace.top = 48 * (faceNo / 6);
rcFace.right = rcFace.left + 48;
rcFace.bottom = rcFace.top + 48;

faceX += 8;
if (faceX >= msgBoxX + 8) { faceX = msgBoxX + 8; }
SDL_RenderSetClipRect(renderer, &rcClip);
drawTexture(sprites[TEX_FACE], &rcFace, faceX, msgBoxY + 8);
SDL_RenderSetClipRect(renderer, NULL);
}
else { textOffset = 0; }
}

//renders cursor during text when text scrolling scrolling is paused
@@ -324,7 +330,7 @@ void drawTSC()
}
SDL_SetRenderDrawColor(renderer, 255, 255, 254, 255);
drawRect(
msgBoxX + 8 + charWidth + (strlen(msgText)*charWidth) - (some_num*charWidth),
msgBoxX + 8 + charWidth + (strlen(msgText)*charWidth) - (some_num*charWidth) + textOffset,
msgBoxY + 8 + ((num*charHeight * 4) / 3) + 1,
charWidth, charHeight);
}
@@ -359,21 +365,29 @@ void drawTSC()
//renders the yes no box thing
if (tscMode == YNJ)
{
int i = 0;
if (tscCounter > 1) { i = 144; }
else { i = 4 * (38 - tscCounter); }

drawTexture(sprites[TEX_TEXTBOX], &rect_yesno, 216, i);
if (tscCounter > 15)
if (ynjBoxYOffset >= 4)
{
ynjBoxYOffset = 4;
}
else { ynjBoxYOffset++; }
rcClip = { (screenWidth >> 1) + 56, ((screenHeight >> 1) + 22), 84, 32 };
SDL_RenderSetClipRect(renderer, &rcClip);
drawTexture(sprites[TEX_TEXTBOX], &rect_yesno, (screenWidth >> 1) + 56,
((screenHeight >> 1) + 54) - (ynjBoxYOffset << 3));
SDL_RenderSetClipRect(renderer, NULL);
if (ynjBoxYOffset >= 4)
{
drawTexture(sprites[TEX_TEXTBOX], &rect_cur, 41 * yesnoSelect + 211, 154);
drawTexture(sprites[TEX_TEXTBOX], &rect_cur,
41 * yesnoSelect + ((screenWidth >> 1) + 51),
(screenHeight >> 1) + 34);
}
}
}

if (mapNameDisplayTimer++ < 160)
{
renderTextLine(screenWidth << 1, 80, stageTable[currentLevel].name);
}
if (mapNameDisplayTimer++ < 160)
{
renderTextLine((screenWidth >> 1) - ((strlen(stageTable[currentLevel].name) * charWidth) >> 1),
80, stageTable[currentLevel].name);
}
return;
}
@@ -470,7 +484,7 @@ int updateTsc() {
{
if (isKeyPressed(keyJump))
{
//PlaySoundObject(18, 1);
playSound(18);
if (yesnoSelect == 1)
{
runScriptEvent(ascii2num(&tsc[tscPos], 4));
@@ -485,12 +499,12 @@ int updateTsc() {
else if (isKeyPressed(keyLeft))
{
yesnoSelect = 0;
//PlaySoundObject(1, 1);
playSound(1);
}
else if (isKeyPressed(keyRight))
{
yesnoSelect = 1;
//PlaySoundObject(1, 1);
playSound(1);
}
}
else
@@ -621,6 +635,15 @@ int updateTsc() {
tscCleanup(0);
break;
case('<DNA'):
for (size_t i = 0; i < npcs.size(); i++)
{
if (npcs[i].code_char == ascii2num(&tsc[tscPos + 4], 4))
{
npcs[i].cond = 0;
setFlag(npcs[i].code_flag);
}
}

tscCleanup(1);
break;
case('<DNP'):
@@ -673,7 +696,8 @@ int updateTsc() {
gitNo = 0;
break;
case('<FAC'):
faceNo = ascii2num(&tsc[tscPos], 4);
faceX = msgBoxX - 40;
faceNo = ascii2num(&tsc[tscPos + 4], 4);
tscCleanup(1);
break;
case('<FAI'):
@@ -711,8 +735,8 @@ int updateTsc() {
tscCleanup(2);
break;
case('<FOM'):
viewGoalX = currentPlayer.x;
viewGoalY = currentPlayer.y;
viewGoalX = &currentPlayer.x;
viewGoalY = &currentPlayer.y;
viewSpeed = ascii2num(&tsc[tscPos + 4], 4);
tscCleanup(1);
break;
@@ -721,8 +745,8 @@ int updateTsc() {
{
if (npcs[n].code_event == ascii2num(&tsc[tscPos + 4], 4))
{
viewGoalX = npcs[n].x;
viewGoalY = npcs[n].y;
viewGoalX = &npcs[n].x;
viewGoalY = &npcs[n].y;
viewSpeed = ascii2num(&tsc[tscPos + 9], 4);
break;
}
@@ -961,6 +985,7 @@ int updateTsc() {
tscPrevMode = tscMode;
tscMode = YNJ;
yesnoSelect = 0;
ynjBoxYOffset = 0;
tscCleanup(0);
break;
case('<ZAM'):
@@ -1,5 +1,4 @@
#include "sound.h"
#include <SDL.h>

const char *sfxList[] =
{
@@ -153,12 +152,12 @@ const char *sfxList[] =
NULL,
NULL,
NULL,
"bass_01.wav",
"snare_01.wav",
"hi_close.wav",
"hi_open.wav",
"tom_01.wav",
"per_01.wav",
NULL,//"org_bass_01.wav",
NULL,//"org_snare_01.wav",
NULL,//"org_hi_close.wav",
NULL,//"org_hi_open.wav",
NULL,//"org_tom_01.wav",
NULL,//"org_per_01.wav",
NULL,
NULL,
NULL,
@@ -170,28 +169,23 @@ struct SOUND_EFFECT
BYTE *buf;
Uint32 length;
};

SOUND_EFFECT sounds[_countof(sfxList)];

SDL_AudioStream *audioStream;
SDL_AudioDeviceID soundDev = 0;
SDL_AudioSpec soundSpec;
SDL_AudioSpec want;

void mixAudio(BYTE *dst, BYTE *src, Uint32 len, Uint8 lVolume, Uint8 rVolume)
//use int pointers for easy use
void mixAudio(int *dst, int *src, Uint32 len, Uint8 lVolume, Uint8 rVolume)
{
//using 32 float point on native system
for (int f = 0; f <= len; f + 4)
for (int i = 0; i <= (len / 4); i++)
{
//left pan
if (f % 2 == 0)
{
dst[f] = (float)dst[f] + (float)src[f];
}
//right pan
else
{
dst[f] = (float)dst[f] + (float)src[f];
}
//probably shouldn't leave it like this but I'll just leave it like this for now
//technically the best algorithm if you have infinite values
dst[i] = (dst[i] + src[i]);
}
return;
}
@@ -212,7 +206,7 @@ void audio_callback(void *userdata, Uint8 *stream, int len)
{
if (audio->len > len) { tempLength = len; }
else { tempLength = audio->len; }
mixAudio(stream, audio->buf, tempLength, 100, 100);
mixAudio((int*)stream, (int*)audio->buf, tempLength, 100, 100);

audio->len -= tempLength;
audio->buf += tempLength;
@@ -235,9 +229,9 @@ void audio_callback(void *userdata, Uint8 *stream, int len)
void ini_audio()
{
want.channels = 2;
want.freq = 22050;
want.format = AUDIO_F32SYS;
want.samples = 2048;
want.freq = 44100;
want.format = AUDIO_S32SYS;
want.samples = 4096;
want.callback = audio_callback;
want.userdata = calloc(1, sizeof(AUDIO));

@@ -246,66 +240,123 @@ void ini_audio()
0,
&want,
&soundSpec,
SDL_AUDIO_ALLOW_ANY_CHANGE);
NULL);

if (soundDev == 0) { doCustomError("Sound device didn't start."); }
if (soundDev == 0)
doError();

memset(sounds, 0, sizeof(sounds));
SDL_PauseAudioDevice(soundDev, 0);

return;
}

//since sdl doesn't actually get the loaded wav in the specified format,
//we have to do it ourselves
void loadSound(char *path, SDL_AudioSpec *spec, BYTE **buf, Uint32 *length)
{
int view = 0;
SDL_AudioSpec *lSpec = nullptr;

lSpec = SDL_LoadWAV(path, spec, buf, length);

if (lSpec == nullptr)
doError();

BYTE *pBuf = *buf;
int *fakeBuf = (int*)malloc(*length * 4);

//number of data points to interolate
int dist = 2;
int *fakeFakeBuf = (int *)malloc(*length * 4 * 2);
int *realBuf = (int*)calloc(dist, *length * 4 * 2);

//converting to 32 signed int format from unsigned 8 bit
for (int b = 0; b < *length; b++)
{
fakeBuf[b] = (0x7FFFFFFF / 0xFF) * (pBuf[b] - ((0xFF / 2) + 1));
}

//channels++
for (int i = 0; i < *length; i++)
{
fakeFakeBuf[i << 1] = fakeBuf[i];
fakeFakeBuf[(i << 1) + 1] = fakeBuf[i];
}

//interpolation
for (int i = 0; i < *length; i++)
{
realBuf[i << 1] = fakeFakeBuf[i];
realBuf[(i << 1) + 1] = fakeFakeBuf[i];
}

free(fakeBuf);
free(fakeFakeBuf);
SDL_FreeWAV(*buf);

*length *= (4 * dist * 2);
*buf = (BYTE*)realBuf;
return;
}

const char *pathToSounds = "data/Sound/";
void loadSounds()
{
char path[64] = "data/soundfx/";
Uint32 silentLength = 0;
BYTE *silentBuf = nullptr;
SDL_LoadWAV("data/soundfx/silence.wav", &soundSpec, &silentBuf, &silentLength);
char path[64];

for (int s = 0; s < _countof(sounds); s++)
{
if (sfxList[s] != NULL)
{
strcpy(path, pathToSounds);
strcat(path, sfxList[s]);
SDL_LoadWAV(path, &soundSpec, &sounds[s].buf, &sounds[s].length);
if (sounds[s].buf == NULL) { doError(); }
strcpy(path, "data/soundfx/");

loadSound(path, &soundSpec, &sounds[s].buf, &sounds[s].length);

if (sounds[s].buf == NULL)
doError();
}
else
{
sounds[s].buf = silentBuf;
sounds[s].length = silentLength;
}
sounds[s].buf = NULL;
}

SDL_PauseAudioDevice(soundDev, 0);
return;
}

void freeSounds()
{
for (int s = 0; s < _countof(sounds); s++)
{
SDL_FreeWAV(sounds[s].buf);
if (sounds[s].buf != NULL)
{
free(sounds[s].buf);
}
}

return;
}

void playSound(int sound_no)
{
AUDIO *sound = nullptr;
AUDIO *lastSound = (AUDIO*)want.userdata;
if (sound_no > _countof(sounds)) { return; }

if (sound_no > _countof(sounds))
return;

sound = (AUDIO*)calloc(1, sizeof(AUDIO));
sound->buf = sounds[sound_no].buf;

if (sounds[sound_no].buf != NULL)
sound->buf = sounds[sound_no].buf;
else
return;

sound->len = sounds[sound_no].length;

while (lastSound->next != nullptr)
{
lastSound = lastSound->next;
}

lastSound->next = sound;

return;
}
}
@@ -15,4 +15,4 @@ struct AUDIO
void ini_audio();
void loadSounds();
void freeSounds();
void playSound(int sound_no);
void playSound(int sound_no);