From ba13b8aeea9623c69118e4ce2b70616ddb79731c Mon Sep 17 00:00:00 2001 From: Clownacy Date: Tue, 29 Jan 2019 22:42:26 +0000 Subject: [PATCH 1/7] More NPCs --- src/NpcAct.h | 7 +- src/NpcAct020.cpp | 36 +++++ src/NpcAct060.cpp | 402 ++++++++++++++++++++++++++++++++++++++++++++++ src/NpcAct140.cpp | 40 +++++ src/NpcTbl.cpp | 8 +- 5 files changed, 487 insertions(+), 6 deletions(-) diff --git a/src/NpcAct.h b/src/NpcAct.h index 90677526..02c839df 100644 --- a/src/NpcAct.h +++ b/src/NpcAct.h @@ -32,7 +32,7 @@ void ActNpc032(NPCHAR *npc); void ActNpc034(NPCHAR *npc); void ActNpc037(NPCHAR *npc); - +void ActNpc038(NPCHAR *npc); void ActNpc039(NPCHAR *npc); void ActNpc042(NPCHAR *npc); @@ -42,7 +42,8 @@ void ActNpc046(NPCHAR *npc); void ActNpc058(NPCHAR *npc); void ActNpc059(NPCHAR *npc); - +void ActNpc060(NPCHAR *npc); +void ActNpc061(NPCHAR *npc); void ActNpc062(NPCHAR *npc); void ActNpc064(NPCHAR *npc); @@ -71,6 +72,8 @@ void ActNpc119(NPCHAR *npc); void ActNpc125(NPCHAR *npc); +void ActNpc145(NPCHAR *npc); + void ActNpc151(NPCHAR *npc); void ActNpc211(NPCHAR *npc); diff --git a/src/NpcAct020.cpp b/src/NpcAct020.cpp index 046db7fd..72dee4ec 100644 --- a/src/NpcAct020.cpp +++ b/src/NpcAct020.cpp @@ -383,6 +383,42 @@ void ActNpc037(NPCHAR *npc) npc->rect = rect[npc->ani_no]; } +//Fireplace +void ActNpc038(NPCHAR *npc) +{ + RECT rect[4]; + + rect[0] = {128, 64, 144, 80}; + rect[1] = {144, 64, 160, 80}; + rect[2] = {160, 64, 176, 80}; + rect[3] = {176, 64, 192, 80}; + + switch (npc->act_no) + { + case 0: + if (++npc->ani_wait > 3) + { + npc->ani_wait = 0; + ++npc->ani_no; + } + + if (npc->ani_no > 3) + npc->ani_no = 0; + + npc->rect = rect[npc->ani_no]; + break; + + case 10: + npc->act_no = 11; + SetDestroyNpChar(npc->x, npc->y, npc->view.back, 8); + // Fallthrough + case 11: + npc->rect.left = 0; + npc->rect.right = 0; + break; + } +} + //Save sign void ActNpc039(NPCHAR *npc) { diff --git a/src/NpcAct060.cpp b/src/NpcAct060.cpp index 04acf303..163fd438 100644 --- a/src/NpcAct060.cpp +++ b/src/NpcAct060.cpp @@ -11,6 +11,408 @@ #include "Map.h" #include "CommonDefines.h" +//Toroko +void ActNpc060(NPCHAR *npc) +{ + RECT rcLeft[8]; + RECT rcRight[8]; + + rcLeft[0] = {0, 64, 16, 80}; + rcLeft[1] = {16, 64, 32, 80}; + rcLeft[2] = {32, 64, 48, 80}; + rcLeft[3] = {16, 64, 32, 80}; + rcLeft[4] = {48, 64, 64, 80}; + rcLeft[5] = {16, 64, 32, 80}; + rcLeft[6] = {112, 64, 128, 80}; + rcLeft[7] = {128, 64, 144, 80}; + + rcRight[0] = {0, 80, 16, 96}; + rcRight[1] = {16, 80, 32, 96}; + rcRight[2] = {32, 80, 48, 96}; + rcRight[3] = {16, 80, 32, 96}; + rcRight[4] = {48, 80, 64, 96}; + rcRight[5] = {16, 80, 32, 96}; + rcRight[6] = {112, 80, 128, 96}; + rcRight[7] = {128, 80, 144, 96}; + + switch ( npc->act_no ) + { + case 0: + npc->act_no = 1; + npc->ani_no = 0; + npc->ani_wait = 0; + npc->xm = 0; + // Fallthrough + case 1: + if (Random(0, 120) == 10) + { + npc->act_no = 2; + npc->act_wait = 0; + npc->ani_no = 1; + } + + if (npc->x - 0x2000 < gMC.x && npc->x + 0x2000 > gMC.x && npc->y - 0x2000 < gMC.y && npc->y + 0x2000 > gMC.y) + { + if (npc->x <= gMC.x) + npc->direct = 2; + else + npc->direct = 0; + } + + break; + + case 2: + if (++npc->act_wait > 8) + { + npc->act_no = 1; + npc->ani_no = 0; + } + + break; + + case 3: + npc->act_no = 4; + npc->ani_no = 1; + npc->ani_wait = 0; + // Fallthrough + case 4: + if (++npc->ani_wait > 2) + { + npc->ani_wait = 0; + ++npc->ani_no; + } + + if (npc->ani_no > 4) + npc->ani_no = 1; + + if (npc->flag & 1) + { + npc->direct = 2; + npc->xm = 0x200; + } + + if (npc->flag & 4) + { + npc->direct = 0; + npc->xm = -0x200; + } + + if (npc->direct) + npc->xm = 0x400; + else + npc->xm = -0x400; + + break; + + case 6: + npc->act_no = 7; + npc->act_wait = 0; + npc->ani_no = 1; + npc->ani_wait = 0; + npc->ym = -0x400; + // Fallthrough + case 7: + if (++npc->ani_wait > 2) + { + npc->ani_wait = 0; + ++npc->ani_no; + } + + if (npc->ani_no > 4) + npc->ani_no = 1; + + if (npc->direct) + npc->xm = 0x100; + else + npc->xm = -0x100; + + if (npc->act_wait++ && npc->flag & 8) + npc->act_no = 3; + + break; + + case 8: + npc->ani_no = 1; + npc->act_wait = 0; + npc->act_no = 9; + npc->ym = -0x200; + // Fallthrough + case 9: + if (npc->act_wait++ && npc->flag & 8) + npc->act_no = 0; + + break; + + case 10: + npc->act_no = 11; + npc->ani_no = 6; + npc->ym = -0x400; + PlaySoundObject(50, 1); + + if (npc->direct) + npc->xm = 0x100; + else + npc->xm = -0x100; + + break; + + case 11: + if ( npc->act_wait++ && npc->flag & 8 ) + { + npc->act_no = 12; + npc->ani_no = 7; + npc->bits |= 0x2000; + } + + break; + + case 12: + npc->xm = 0; + break; + } + + npc->ym += 0x40; + + if (npc->xm > 0x400) + npc->xm = 0x400; + if (npc->xm < -0x400) + npc->xm = -0x400; + + if (npc->ym > 0x5FF) + npc->ym = 0x5FF; + + npc->x += npc->xm; + npc->y += npc->ym; + + if (npc->direct == 0) + npc->rect = rcLeft[npc->ani_no]; + else + npc->rect = rcRight[npc->ani_no]; +} + +//King +void ActNpc061(NPCHAR *npc) +{ + RECT rcLeft[11]; + RECT rcRight[11]; + + rcLeft[0] = {224, 32, 240, 48}; + rcLeft[1] = {240, 32, 256, 48}; + rcLeft[2] = {256, 32, 272, 48}; + rcLeft[3] = {272, 32, 288, 48}; + rcLeft[4] = {288, 32, 304, 48}; + rcLeft[5] = {224, 32, 240, 48}; + rcLeft[6] = {304, 32, 320, 48}; + rcLeft[7] = {224, 32, 240, 48}; + rcLeft[8] = {272, 32, 288, 48}; + rcLeft[9] = {0, 0, 0, 0}; + rcLeft[10] = {112, 32, 128, 48}; + + rcRight[0] = {224, 48, 240, 64}; + rcRight[1] = {240, 48, 256, 64}; + rcRight[2] = {256, 48, 272, 64}; + rcRight[3] = {272, 48, 288, 64}; + rcRight[4] = {288, 48, 304, 64}; + rcRight[5] = {224, 48, 240, 64}; + rcRight[6] = {304, 48, 320, 64}; + rcRight[7] = {224, 48, 240, 64}; + rcRight[8] = {272, 48, 288, 64}; + rcRight[9] = {0, 0, 0, 0}; + rcRight[10] = {112, 32, 128, 48}; + + switch (npc->act_no) + { + case 0: + npc->act_no = 1; + npc->ani_no = 0; + npc->ani_wait = 0; + npc->xm = 0; + // Fallthrough + case 1: + if (Random(0, 120) == 10) + { + npc->act_no = 2; + npc->act_wait = 0; + npc->ani_no = 1; + } + + break; + + case 2: + if (++npc->act_wait > 8) + { + npc->act_no = 1; + npc->ani_no = 0; + } + + break; + + case 5: + npc->ani_no = 3; + npc->xm = 0; + break; + + case 6: + npc->act_no = 7; + npc->act_wait = 0; + npc->ani_wait = 0; + npc->ym = -0x400; + // Fallthrough + case 7: + npc->ani_no = 2; + + if (npc->direct) + npc->xm = 0x200; + else + npc->xm = -0x200; + + if (npc->act_wait++ && npc->flag & 8) + npc->act_no = 5; + + break; + case 8: + npc->act_no = 9; + npc->ani_no = 4; + npc->ani_wait = 0; + // Fallthrough + case 9: + if (++npc->ani_wait > 4) + { + npc->ani_wait = 0; + ++npc->ani_no; + } + + if (npc->ani_no > 7) + npc->ani_no = 4; + + if (npc->direct) + npc->xm = 0x200; + else + npc->xm = -0x200; + + break; + + case 10: + npc->act_no = 11; + npc->ani_no = 4; + npc->ani_wait = 0; + // Fallthrough + case 11: + if (++npc->ani_wait > 2) + { + npc->ani_wait = 0; + ++npc->ani_no; + } + + if (npc->ani_no > 7) + npc->ani_no = 4; + + if (npc->direct) + npc->xm = 0x400; + else + npc->xm = -0x400; + + break; + + case 20: + SetNpChar(145, 0, 0, 0, 0, 2, npc, 0x100); + npc->ani_no = 0; + npc->act_no = 0; + break; + + case 30: + npc->act_no = 31; + npc->act_wait = 0; + npc->ani_wait = 0; + npc->ym = 0; + // Fallthrough + case 31: + npc->ani_no = 2; + + if (npc->direct) + npc->xm = 0x600; + else + npc->xm = -0x600; + + if (npc->flag & 1) + { + npc->direct = 2; + npc->act_no = 7; + npc->act_wait = 0; + npc->ani_wait = 0; + npc->ym = -0x400; + npc->xm = 0x200; + PlaySoundObject(71, 1); + SetDestroyNpChar(npc->x, npc->y, 0x800, 4); + } + + break; + + case 40: + npc->act_no = 42; + npc->act_wait = 0; + npc->ani_no = 8; + PlaySoundObject(29, 1); + // Fallthrough + case 42: + if (++npc->ani_no > 9) + npc->ani_no = 8; + + if (++npc->act_wait > 100) + { + for (int i = 0; i < 4; ++i) + SetNpChar(4, npc->x + (Random(-12, 12) * 0x200), npc->y + (Random(-12, 12) * 0x200), Random(-341, 341), Random(-0x600, 0), 0, 0, 0x100); + + npc->act_no = 50; + npc->surf = 20; + npc->ani_no = 10; + } + + break; + + case 60: + npc->ani_no = 6; + npc->act_no = 61; + npc->ym = -0x5FF; + npc->xm = 0x400; + npc->count2 = 1; + break; + + case 61: + npc->ym += 0x40; + + if (npc->flag & 8) + { + npc->act_no = 0; + npc->count2 = 0; + npc->xm = 0; + } + + break; + } + + if (npc->act_no < 30 || npc->act_no >= 40) + { + npc->ym += 0x40; + + if (npc->xm > 0x400) + npc->xm = 0x400; + if (npc->xm < -0x400) + npc->xm = -0x400; + + if (npc->ym > 0x5FF) + npc->ym = 0x5FF; + } + + npc->x += npc->xm; + npc->y += npc->ym; + + if (npc->direct == 0) + npc->rect = rcLeft[npc->ani_no]; + else + npc->rect = rcRight[npc->ani_no]; +} + //Kazuma at computer void ActNpc062(NPCHAR *npc) { diff --git a/src/NpcAct140.cpp b/src/NpcAct140.cpp index 232a4857..7a83e0d6 100644 --- a/src/NpcAct140.cpp +++ b/src/NpcAct140.cpp @@ -9,6 +9,46 @@ #include "Back.h" #include "Triangle.h" +//King's sword +void ActNpc145(NPCHAR *npc) +{ + RECT rcLeft[1]; + RECT rcRight[1]; + + rcLeft[0] = {96, 32, 112, 48}; + rcRight[0] = {112, 32, 128, 48}; + + if (npc->act_no == 0) + { + if (npc->pNpc->count2 == 0) + { + if (npc->pNpc->direct == 0) + npc->direct = 0; + else + npc->direct = 2; + } + else + { + if (npc->pNpc->direct == 0) + npc->direct = 2; + else + npc->direct = 0; + } + + if (npc->direct == 0) + npc->x = npc->pNpc->x - 0x1400; + else + npc->x = npc->pNpc->x + 0x1400; + + npc->y = npc->pNpc->y; + } + + if (npc->direct == 0) + npc->rect = rcLeft[npc->ani_no]; + else + npc->rect = rcRight[npc->ani_no]; +} + //Blue robot (standing) void ActNpc151(NPCHAR *npc) { diff --git a/src/NpcTbl.cpp b/src/NpcTbl.cpp index 61e54126..8b41e041 100644 --- a/src/NpcTbl.cpp +++ b/src/NpcTbl.cpp @@ -94,7 +94,7 @@ NPCFUNCTION gpNpcFuncTbl[361] = nullptr, nullptr, ActNpc037, - nullptr, + ActNpc038, ActNpc039, nullptr, nullptr, @@ -116,8 +116,8 @@ NPCFUNCTION gpNpcFuncTbl[361] = nullptr, ActNpc058, ActNpc059, - nullptr, - nullptr, + ActNpc060, + ActNpc061, ActNpc062, nullptr, ActNpc064, @@ -201,7 +201,7 @@ NPCFUNCTION gpNpcFuncTbl[361] = nullptr, nullptr, nullptr, - nullptr, + ActNpc145, nullptr, nullptr, nullptr, From 4f7db164d68fa3ad6f062b5c5911c5b6d59ea150 Mon Sep 17 00:00:00 2001 From: Clownacy Date: Wed, 30 Jan 2019 14:56:17 +0000 Subject: [PATCH 2/7] Overhauled graphics system Along with being more accurate to the original, this fixes switching out of fullscreen causing textures to disappear. This was caused by DirectX destroying textures that are marked as render-targets when a device-loss occurs. SDL2 doesn't do anything to recover them, unlike regular textures, so my solution is just to avoid render-target textures entirely. On the upside, this should make drawing text to surfaces much faster, since we're not reading back bitmaps from the GPU. --- src/Draw.cpp | 424 +++++++++++++++++++++++++++------------------------ src/Draw.h | 3 + src/Font.cpp | 24 +-- src/Font.h | 2 +- 4 files changed, 233 insertions(+), 220 deletions(-) diff --git a/src/Draw.cpp b/src/Draw.cpp index 77ef3d0a..cf8fee50 100644 --- a/src/Draw.cpp +++ b/src/Draw.cpp @@ -64,101 +64,157 @@ bool Flip_SystemTask() return true; } -bool StartDirectDraw() +static bool IsEnableBitmap(SDL_RWops *fp) { - //Create renderer - gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE); - return true; -} + char str[16]; + const char *extra_text = "(C)Pixel"; -void EndDirectDraw() -{ - //Release all surfaces - for (int i = 0; i < SURFACE_ID_MAX; i++) - { - if (surf[i].texture) - { - SDL_DestroyTexture(surf[i].texture); - surf[i].texture = NULL; - } - } + const size_t len = strlen(extra_text); + + fp->seek(fp, -len, RW_SEEK_END); + fp->read(fp, str, 1, len); + fp->seek(fp, 0, RW_SEEK_SET); + return memcmp(str, extra_text, len) == 0; } void ReleaseSurface(int s) { //Release the surface we want to release - if (surf[s].texture) + if (surf[s].in_use) { SDL_DestroyTexture(surf[s].texture); - surf[s].texture = NULL; + SDL_FreeSurface(surf[s].surface); + surf[s].in_use = false; } } -bool MakeSurface(SDL_RWops *fp, int surf_no) +bool MakeSurface_Generic(int bxsize, int bysize, int surf_no) { - //Check if surf_no can be used - if (surf_no > SURFACE_ID_MAX) - { - printf("Tried to create surface with invalid id %d\n", surf_no); - return false; - } - if (surf[surf_no].texture) - { - printf("Tried to create surface at id %d, but there's already a texture there\n", surf_no); - return false; - } - - //Load surface from file - SDL_Surface *surface = SDL_LoadBMP_RW(fp, 1); - if (!surface) - { - printf("Couldn't load bitmap for surface id %d\nSDL Error: %s\n", surf_no, SDL_GetError()); - return false; - } - - //Make sure surface has color key on - SDL_SetColorKey(surface, SDL_TRUE, SDL_MapRGB(surface->format, 0, 0, 0)); - - //Get texture from surface - SDL_Texture *texture = SDL_CreateTextureFromSurface(gRenderer, surface); - if (!texture) - { - printf("Failed to convert SDL_Surface to SDL_Texture for surface id %d\nSDL Error: %s\n", surf_no, SDL_GetError()); - return false; - } - - //Create real texture, and copy loaded texture here (has texture target access) - int w, h; - SDL_QueryTexture(texture, NULL, NULL, &w, &h); + bool success = false; - SDL_Texture *textureAccessible = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, w * gWindowScale, h * gWindowScale); - - if (!textureAccessible) +#ifdef FIX_BUGS + if (surf_no >= SURFACE_ID_MAX) +#else + if (surf_no > SURFACE_ID_MAX) // OOPS (should be '>=') +#endif { - printf("Failed to create real texture for surface id %d\nSDL Error: %s\n", surf_no, SDL_GetError()); - return false; + printf("Tried to create drawable surface at invalid slot (%d - maximum is %d)\n", surf_no, SURFACE_ID_MAX); } - - SDL_SetTextureBlendMode(textureAccessible, SDL_BLENDMODE_BLEND); - - SDL_SetRenderTarget(gRenderer, textureAccessible); - SDL_SetRenderDrawColor(gRenderer, 0, 0, 0, 0); - SDL_RenderClear(gRenderer); - SDL_RenderCopy(gRenderer, texture, NULL, NULL); - SDL_SetRenderTarget(gRenderer, NULL); - - //Set surface's metadata - surf[surf_no].texture = textureAccessible; - - //Free surface and texture - SDL_DestroyTexture(texture); - SDL_FreeSurface(surface); - - printf(" ^ Successfully loaded\n"); - return true; + else + { + if (surf[surf_no].in_use == true) + { + printf("Tried to create drawable surface at occupied slot (%d)\n", surf_no); + } + else + { + //Create surface + surf[surf_no].surface = SDL_CreateRGBSurfaceWithFormat(0, bxsize * gWindowScale, bysize * gWindowScale, 0, SDL_PIXELFORMAT_RGBA32); + + if (surf[surf_no].surface == NULL) + { + printf("Failed to create drawable surface %d (SDL_CreateRGBSurfaceWithFormat)\nSDL Error: %s\n", surf_no, SDL_GetError()); + } + else + { + surf[surf_no].texture = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STREAMING, bxsize * gWindowScale, bysize * gWindowScale); + + if (surf[surf_no].texture == NULL) + { + printf("Failed to create drawable surface %d (SDL_CreateTexture)\nSDL Error: %s\n", surf_no, SDL_GetError()); + SDL_FreeSurface(surf[surf_no].surface); + } + else + { + surf[surf_no].in_use = true; + success = true; + } + } + } + } + + return success; } -bool MakeSurface_File(const char *name, int surf_no) +static void FlushSurface(int surf_no) +{ + unsigned char *raw_pixels; + int pitch; + SDL_LockTexture(surf[surf_no].texture, NULL, (void**)&raw_pixels, &pitch); + + unsigned char (*src_pixels)[surf[surf_no].surface->pitch / 4][4] = (unsigned char (*)[surf[surf_no].surface->pitch/ 4][4])surf[surf_no].surface->pixels; + unsigned char (*dst_pixels)[pitch / 4][4] = (unsigned char (*)[pitch/ 4][4])raw_pixels; + + for (unsigned int h = 0; h < surf[surf_no].surface->h; ++h) + { + for (unsigned int w = 0; w < surf[surf_no].surface->w; ++w) + { + dst_pixels[h][w][0] = src_pixels[h][w][0]; + dst_pixels[h][w][1] = src_pixels[h][w][1]; + dst_pixels[h][w][2] = src_pixels[h][w][2]; + + if (src_pixels[h][w][0] || src_pixels[h][w][1] || src_pixels[h][w][2]) // Colour-key + dst_pixels[h][w][3] = 0xFF; + else + dst_pixels[h][w][3] = 0; + } + } + + SDL_UnlockTexture(surf[surf_no].texture); +} + +static bool LoadBitmap(SDL_RWops *fp, int surf_no, bool create_surface) +{ + bool success = false; + + if (surf_no >= SURFACE_ID_MAX) + { + printf("Tried to load bitmap at invalid slot (%d - maximum is %d\n", surf_no, SURFACE_ID_MAX); + } + else + { + if (create_surface && surf[surf_no].in_use) + { + printf("Tried to create drawable surface at occupied slot (%d)\n", surf_no); + } + else + { + SDL_Surface *surface = SDL_LoadBMP_RW(fp, 1); + + if (surface == NULL) + { + printf("Couldn't load bitmap for surface id %d\nSDL Error: %s\n", surf_no, SDL_GetError()); + } + else + { + if (create_surface == false || MakeSurface_Generic(surface->w, surface->h, surf_no)) + { + SDL_Surface *converted_surface = SDL_ConvertSurface(surface, surf[surf_no].surface->format, 0); + + if (converted_surface == NULL) + { + printf("Couldn't convert bitmap to surface format (surface id %d)\nSDL Error: %s\n", surf_no, SDL_GetError()); + } + else + { + SDL_Rect dst_rect = {0, 0, converted_surface->w * gWindowScale, converted_surface->h * gWindowScale}; + SDL_BlitScaled(converted_surface, NULL, surf[surf_no].surface, &dst_rect); + SDL_FreeSurface(converted_surface); + surf[surf_no].needs_updating = true; + printf(" ^ Successfully loaded\n"); + success = true; + } + } + + SDL_FreeSurface(surface); + } + } + } + + return success; +} + +static bool LoadBitmap_File(const char *name, int surf_no, bool create_surface) { char path[PATH_LENGTH]; SDL_RWops *fp; @@ -168,9 +224,16 @@ bool MakeSurface_File(const char *name, int surf_no) fp = SDL_RWFromFile(path, "rb"); if (fp) { - printf("Loading surface (as .pbm) from %s for surface id %d\n", path, surf_no); - if (MakeSurface(fp, surf_no)) - return true; + if (!IsEnableBitmap(fp)) + { + printf("Tried to load bitmap to surface %d, but it's missing the '(C)Pixel' string\n", surf_no); + } + else + { + printf("Loading surface (as .pbm) from %s for surface id %d\n", path, surf_no); + if (LoadBitmap(fp, surf_no, create_surface)) + return true; + } } //Attempt to load BMP @@ -178,23 +241,31 @@ bool MakeSurface_File(const char *name, int surf_no) fp = SDL_RWFromFile(path, "rb"); if (fp) { - printf("Loading surface (as .bmp) from %s for surface id %d\n", path, surf_no); - if (MakeSurface(fp, surf_no)) - return true; + if (!IsEnableBitmap(fp)) + { + printf("Tried to load bitmap to surface %d, but it's missing the '(C)Pixel' string\n", surf_no); + } + else + { + + printf("Loading surface (as .bmp) from %s for surface id %d\n", path, surf_no); + if (LoadBitmap(fp, surf_no, create_surface)) + return true; + } } printf("Failed to open file %s\n", name); return false; } -bool MakeSurface_Resource(const char *res, int surf_no) +static bool LoadBitmap_Resource(const char *res, int surf_no, bool create_surface) { SDL_RWops *fp = FindResource(res); if (fp) { printf("Loading surface from resource %s for surface id %d\n", res, surf_no); - if (MakeSurface(fp, surf_no)) + if (LoadBitmap(fp, surf_no, create_surface)) return true; } @@ -202,34 +273,24 @@ bool MakeSurface_Resource(const char *res, int surf_no) return false; } +bool MakeSurface_File(const char *name, int surf_no) +{ + return LoadBitmap_File(name, surf_no, true); +} + +bool MakeSurface_Resource(const char *res, int surf_no) +{ + return LoadBitmap_Resource(res, surf_no, true); +} + bool ReloadBitmap_File(const char *name, int surf_no) { - ReleaseSurface(surf_no); - return MakeSurface_File(name, surf_no); + return LoadBitmap_File(name, surf_no, false); } bool ReloadBitmap_Resource(const char *res, int surf_no) { - ReleaseSurface(surf_no); - return MakeSurface_Resource(res, surf_no); -} - -bool MakeSurface_Generic(int bxsize, int bysize, int surf_no) -{ - //Delete old surface - ReleaseSurface(surf_no); - - //Create surface - surf[surf_no].texture = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, bxsize * gWindowScale, bysize * gWindowScale); - - if (!surf[surf_no].texture) - { - printf("Failed to create drawable surface %d\nSDL Error: %s\n", surf_no, SDL_GetError()); - return false; - } - - SDL_SetTextureBlendMode(surf[surf_no].texture, SDL_BLENDMODE_BLEND); - return true; + return LoadBitmap_Resource(res, surf_no, false); } SDL_Rect RectToSDLRect(RECT *rect) @@ -246,42 +307,27 @@ void BackupSurface(int surf_no, RECT *rect) //Get texture of what's currently rendered on screen SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, w, h, 0, SDL_PIXELFORMAT_RGBA32); - SDL_RenderReadPixels(gRenderer, nullptr, SDL_PIXELFORMAT_RGBA32, surface->pixels, surface->pitch); + SDL_RenderReadPixels(gRenderer, NULL, SDL_PIXELFORMAT_RGBA32, surface->pixels, surface->pitch); - SDL_Texture *screenTexture = SDL_CreateTextureFromSurface(gRenderer, surface); - - //Free surface - SDL_FreeSurface(surface); - //Get rects SDL_Rect frameRect = RectToSDLRect(rect); frameRect = {frameRect.x * gWindowScale, frameRect.y * gWindowScale, frameRect.w * gWindowScale, frameRect.h * gWindowScale}; - - SDL_Texture *textureAccessible = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, frameRect.w, frameRect.h); - - if (!textureAccessible) - { - printf("Failed to create real texture for surface id %d\nSDL Error: %s\n", surf_no, SDL_GetError()); - return; - } - - SDL_SetTextureBlendMode(textureAccessible, SDL_BLENDMODE_BLEND); - - SDL_SetRenderTarget(gRenderer, textureAccessible); - SDL_SetRenderDrawColor(gRenderer, 0, 0, 0, 0); - SDL_RenderClear(gRenderer); - SDL_RenderCopy(gRenderer, screenTexture, &frameRect, NULL); - SDL_SetRenderTarget(gRenderer, NULL); - - //Set surface's metadata - surf[surf_no].texture = textureAccessible; - - //Free stuff - SDL_DestroyTexture(screenTexture); + + SDL_BlitSurface(surface, &frameRect, surf[surf_no].surface, &frameRect); + surf[surf_no].needs_updating = true; + + //Free surface + SDL_FreeSurface(surface); } -void PutBitmap3(RECT *rcView, int x, int y, RECT *rect, int surf_no) //Transparency +static void DrawBitmap(RECT *rcView, int x, int y, RECT *rect, int surf_no, bool transparent) { + if (surf[surf_no].needs_updating) + { + FlushSurface(surf_no); + surf[surf_no].needs_updating = false; + } + //Get SDL_Rects SDL_Rect clipRect = RectToSDLRect(rcView); @@ -295,6 +341,8 @@ void PutBitmap3(RECT *rcView, int x, int y, RECT *rect, int surf_no) //Transpare clipRect = {clipRect.x * gWindowScale, clipRect.y * gWindowScale, clipRect.w * gWindowScale, clipRect.h * gWindowScale}; SDL_RenderSetClipRect(gRenderer, &clipRect); + SDL_SetTextureBlendMode(surf[surf_no].texture, transparent ? SDL_BLENDMODE_BLEND : SDL_BLENDMODE_NONE); + //Draw to screen if (SDL_RenderCopy(gRenderer, surf[surf_no].texture, &frameRect, &destRect) < 0) printf("Failed to draw texture %d\nSDL Error: %s\n", surf_no, SDL_GetError()); @@ -303,36 +351,14 @@ void PutBitmap3(RECT *rcView, int x, int y, RECT *rect, int surf_no) //Transpare SDL_RenderSetClipRect(gRenderer, NULL); } +void PutBitmap3(RECT *rcView, int x, int y, RECT *rect, int surf_no) //Transparency +{ + DrawBitmap(rcView, x, y, rect, surf_no, true); +} + void PutBitmap4(RECT *rcView, int x, int y, RECT *rect, int surf_no) //No Transparency { - //Get SDL_Rects - SDL_Rect clipRect = RectToSDLRect(rcView); - - SDL_Rect frameRect = RectToSDLRect(rect); - frameRect = {frameRect.x * gWindowScale, frameRect.y * gWindowScale, frameRect.w * gWindowScale, frameRect.h * gWindowScale}; - - //Get dest rect - SDL_Rect destRect = {x * gWindowScale, y * gWindowScale, frameRect.w, frameRect.h}; - - //Set cliprect - clipRect = {clipRect.x * gWindowScale, clipRect.y * gWindowScale, clipRect.w * gWindowScale, clipRect.h * gWindowScale}; - SDL_RenderSetClipRect(gRenderer, &clipRect); - - //Get original drawing colour - uint8_t origR, origG, origB, origA; - SDL_GetRenderDrawColor(gRenderer, &origR, &origG, &origB, &origA); - - //Draw black behind texture - SDL_SetRenderDrawColor(gRenderer, 0, 0, 0, 0xFF); - SDL_RenderFillRect(gRenderer, &destRect); - - //Draw texture - if (SDL_RenderCopy(gRenderer, surf[surf_no].texture, &frameRect, &destRect) < 0) - printf("Failed to draw texture %d\nSDL Error: %s\n", surf_no, SDL_GetError()); - - //Restore original colour, and undo cliprect - SDL_RenderSetClipRect(gRenderer, NULL); - SDL_SetRenderDrawColor(gRenderer, origR, origG, origB, origA); + DrawBitmap(rcView, x, y, rect, surf_no, false); } void Surface2Surface(int x, int y, RECT *rect, int to, int from) @@ -341,22 +367,9 @@ void Surface2Surface(int x, int y, RECT *rect, int to, int from) SDL_Rect rcSet = {x * gWindowScale, y * gWindowScale, (rect->right - rect->left) * gWindowScale, (rect->bottom - rect->top) * gWindowScale}; SDL_Rect frameRect = RectToSDLRect(rect); frameRect = {frameRect.x * gWindowScale, frameRect.y * gWindowScale, frameRect.w * gWindowScale, frameRect.h * gWindowScale}; - - //Target surface - if (!surf[to].texture) - { - printf("Tried to draw to surface %d, which doesn't exist\n", to); - return; - } - - SDL_SetRenderTarget(gRenderer, surf[to].texture); - - //Draw texture - if (SDL_RenderCopy(gRenderer, surf[from].texture, &frameRect, &rcSet) < 0) - printf("Failed to draw texture %d to %d\nSDL Error: %s\n", from, to, SDL_GetError()); - - //Stop targetting surface - SDL_SetRenderTarget(gRenderer, NULL); + + SDL_BlitSurface(surf[from].surface, &frameRect, surf[to].surface, &rcSet); + surf[to].needs_updating = true; } void CortBox(RECT *rect, uint32_t col) @@ -375,27 +388,12 @@ void CortBox2(RECT *rect, uint32_t col, int surf_no) //Get rect SDL_Rect destRect = RectToSDLRect(rect); destRect = {destRect.x * gWindowScale, destRect.y * gWindowScale, destRect.w * gWindowScale, destRect.h * gWindowScale}; - - //Target surface - if (!surf[surf_no].texture) - { - printf("Tried to draw a rectangle to surface %d, which doesn't exist\n", surf_no); - return; - } - - 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_red, col_green, col_blue, col_alpha); - SDL_RenderFillRect(gRenderer, &destRect); - - //Stop targetting surface - SDL_SetRenderTarget(gRenderer, NULL); + SDL_FillRect(surf[surf_no].surface, &destRect, SDL_MapRGB(surf[surf_no].surface->format, col_red, col_green, col_blue)); + surf[surf_no].needs_updating = true; } #ifdef WINDOWS @@ -491,12 +489,24 @@ void InitTextObject(const char *font_name) void PutText(int x, int y, const char *text, uint32_t color) { - DrawText(gFont, gRenderer, NULL, x * gWindowScale, y * gWindowScale, color, text, strlen(text)); + int surface_width, surface_height; + SDL_GetRendererOutputSize(gRenderer, &surface_width, &surface_height); + + SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, surface_width, surface_height, 0, SDL_PIXELFORMAT_RGBA32); + SDL_RenderReadPixels(gRenderer, NULL, SDL_PIXELFORMAT_RGBA32, surface->pixels, surface->pitch); + + DrawText(gFont, surface, x * gWindowScale, y * gWindowScale, color, text, strlen(text)); + + SDL_Texture *screen_texture = SDL_CreateTextureFromSurface(gRenderer, surface); + SDL_FreeSurface(surface); + SDL_RenderCopy(gRenderer, screen_texture, NULL, NULL); + SDL_DestroyTexture(screen_texture); } void PutText2(int x, int y, const char *text, uint32_t color, int surf_no) { - DrawText(gFont, gRenderer, surf[surf_no].texture, x * gWindowScale, y * gWindowScale, color, text, strlen(text)); + DrawText(gFont, surf[surf_no].surface, x * gWindowScale, y * gWindowScale, color, text, strlen(text)); + surf[surf_no].needs_updating = true; } void EndTextObject() @@ -505,3 +515,17 @@ void EndTextObject() UnloadFont(gFont); gFont = nullptr; } + +bool StartDirectDraw() +{ + //Create renderer + gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED); + return true; +} + +void EndDirectDraw() +{ + //Release all surfaces + for (int i = 0; i < SURFACE_ID_MAX; i++) + ReleaseSurface(i); +} diff --git a/src/Draw.h b/src/Draw.h index 9305b816..08bc07b9 100644 --- a/src/Draw.h +++ b/src/Draw.h @@ -45,6 +45,9 @@ enum Surface_Ids struct SURFACE { + bool in_use; + bool needs_updating; + SDL_Surface *surface; SDL_Texture *texture; }; diff --git a/src/Font.cpp b/src/Font.cpp index fa097b8d..4f1613c0 100644 --- a/src/Font.cpp +++ b/src/Font.cpp @@ -175,20 +175,12 @@ FontObject* LoadFont(const char *font_filename, unsigned int cell_width, unsigne return font_object; } -void DrawText(FontObject *font_object, SDL_Renderer *renderer, SDL_Texture *texture, int x, int y, unsigned long colour, const char *string, size_t string_length) +void DrawText(FontObject *font_object, SDL_Surface *surface, int x, int y, unsigned long colour, const char *string, size_t string_length) { if (font_object != NULL) { const unsigned char colours[3] = {(unsigned char)(colour >> 16), (unsigned char)(colour >> 8), (unsigned char)colour}; - SDL_Texture *old_render_target = SDL_GetRenderTarget(renderer); - SDL_SetRenderTarget(renderer, texture); - - int surface_width, surface_height; - SDL_GetRendererOutputSize(renderer, &surface_width, &surface_height); - - SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, surface_width, surface_height, 0, SDL_PIXELFORMAT_RGBA32); - SDL_RenderReadPixels(renderer, NULL, SDL_PIXELFORMAT_RGBA32, surface->pixels, surface->pitch); unsigned char (*surface_buffer)[surface->pitch / 4][4] = (unsigned char (*)[surface->pitch / 4][4])surface->pixels; FT_Face face = font_object->face; @@ -238,11 +230,11 @@ void DrawText(FontObject *font_object, SDL_Renderer *renderer, SDL_Texture *text const int letter_x = x + pen_x + face->glyph->bitmap_left; const int letter_y = y + ((FT_MulFix(face->ascender, face->size->metrics.y_scale) + (64 - 1)) / 64) - (face->glyph->metrics.horiBearingY / 64); - for (int iy = MAX(-letter_y, 0); letter_y + iy < MIN(letter_y + converted.rows, surface_height); ++iy) + for (int iy = MAX(-letter_y, 0); letter_y + iy < MIN(letter_y + converted.rows, surface->h); ++iy) { if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD) { - for (int ix = MAX(-letter_x, 0); letter_x + ix < MIN(letter_x + (int)converted.width / 3, surface_width); ++ix) + for (int ix = MAX(-letter_x, 0); letter_x + ix < MIN(letter_x + (int)converted.width / 3, surface->w); ++ix) { const unsigned char (*font_buffer)[converted.pitch / 3][3] = (unsigned char (*)[converted.pitch / 3][3])converted.buffer; @@ -263,7 +255,7 @@ void DrawText(FontObject *font_object, SDL_Renderer *renderer, SDL_Texture *text } else if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) { - for (int ix = MAX(-letter_x, 0); letter_x + ix < MIN(letter_x + (int)converted.width, surface_width); ++ix) + for (int ix = MAX(-letter_x, 0); letter_x + ix < MIN(letter_x + (int)converted.width, surface->w); ++ix) { unsigned char (*font_buffer)[converted.pitch] = (unsigned char (*)[converted.pitch])converted.buffer; @@ -282,7 +274,7 @@ void DrawText(FontObject *font_object, SDL_Renderer *renderer, SDL_Texture *text } else if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) { - for (int ix = MAX(-letter_x, 0); letter_x + ix < MIN(letter_x + (int)converted.width, surface_width); ++ix) + for (int ix = MAX(-letter_x, 0); letter_x + ix < MIN(letter_x + (int)converted.width, surface->w); ++ix) { unsigned char (*font_buffer)[converted.pitch] = (unsigned char (*)[converted.pitch])converted.buffer; @@ -303,12 +295,6 @@ void DrawText(FontObject *font_object, SDL_Renderer *renderer, SDL_Texture *text pen_x += face->glyph->advance.x / 64; } - - SDL_Texture *screen_texture = SDL_CreateTextureFromSurface(renderer, surface); - SDL_FreeSurface(surface); - SDL_RenderCopy(renderer, screen_texture, NULL, NULL); - SDL_DestroyTexture(screen_texture); - SDL_SetRenderTarget(renderer, old_render_target); } } diff --git a/src/Font.h b/src/Font.h index fbd7ddc4..528bf65a 100644 --- a/src/Font.h +++ b/src/Font.h @@ -8,5 +8,5 @@ typedef struct FontObject FontObject; FontObject* LoadFontFromData(const unsigned char *data, size_t data_size, unsigned int cell_width, unsigned int cell_height); FontObject* LoadFont(const char *font_filename, unsigned int cell_width, unsigned int cell_height); -void DrawText(FontObject *font_object, SDL_Renderer *renderer, SDL_Texture *texture, int x, int y, unsigned long colour, const char *string, size_t string_length); +void DrawText(FontObject *font_object, SDL_Surface *surface, int x, int y, unsigned long colour, const char *string, size_t string_length); void UnloadFont(FontObject *font_object); From 74bdbf86ca1ca3f78025ab92c37248419d9e8907 Mon Sep 17 00:00:00 2001 From: Clownacy Date: Wed, 30 Jan 2019 18:13:23 +0000 Subject: [PATCH 3/7] More NPCs Cemetery done (minus Ma Pignon of course) --- Makefile | 1 + src/NpcAct.h | 5 + src/NpcAct060.cpp | 136 +++++++++++++++++++++ src/NpcAct080.cpp | 292 ++++++++++++++++++++++++++++++++++++++++++++++ src/NpcAct260.cpp | 122 +++++++++++++++++++ src/NpcTbl.cpp | 8 +- 6 files changed, 560 insertions(+), 4 deletions(-) create mode 100644 src/NpcAct260.cpp diff --git a/Makefile b/Makefile index fc8a1d64..ddeef95b 100644 --- a/Makefile +++ b/Makefile @@ -73,6 +73,7 @@ SOURCES = \ NpcAct120 \ NpcAct140 \ NpcAct200 \ + NpcAct260 \ NpcAct280 \ NpcAct300 \ NpcAct340 \ diff --git a/src/NpcAct.h b/src/NpcAct.h index 02c839df..56199a52 100644 --- a/src/NpcAct.h +++ b/src/NpcAct.h @@ -49,6 +49,7 @@ void ActNpc062(NPCHAR *npc); void ActNpc064(NPCHAR *npc); void ActNpc065(NPCHAR *npc); +void ActNpc069(NPCHAR *npc); void ActNpc070(NPCHAR *npc); void ActNpc071(NPCHAR *npc); void ActNpc072(NPCHAR *npc); @@ -59,6 +60,8 @@ void ActNpc076(NPCHAR *npc); void ActNpc077(NPCHAR *npc); void ActNpc078(NPCHAR *npc); void ActNpc079(NPCHAR *npc); +void ActNpc080(NPCHAR *npc); +void ActNpc081(NPCHAR *npc); void ActNpc083(NPCHAR *npc); void ActNpc084(NPCHAR *npc); @@ -78,6 +81,8 @@ void ActNpc151(NPCHAR *npc); void ActNpc211(NPCHAR *npc); +void ActNpc278(NPCHAR *npc); + void ActNpc298(NPCHAR *npc); void ActNpc299(NPCHAR *npc); void ActNpc300(NPCHAR *npc); diff --git a/src/NpcAct060.cpp b/src/NpcAct060.cpp index 163fd438..573e8b60 100644 --- a/src/NpcAct060.cpp +++ b/src/NpcAct060.cpp @@ -660,6 +660,142 @@ void ActNpc065(NPCHAR *npc) npc->rect = rect_right[npc->ani_no]; } +//Sparkle +void ActNpc069(NPCHAR *npc) +{ + RECT rcLeft[6]; + RECT rcRight[6]; + + rcLeft[0] = {48, 0, 64, 16}; + rcLeft[1] = {64, 0, 80, 16}; + rcLeft[2] = {80, 0, 96, 16}; + rcLeft[3] = {96, 0, 112, 16}; + rcLeft[4] = {48, 0, 64, 16}; + rcLeft[5] = {112, 0, 128, 16}; + + rcRight[0] = {48, 16, 64, 32}; + rcRight[1] = {64, 16, 80, 32}; + rcRight[2] = {80, 16, 96, 32}; + rcRight[3] = {96, 16, 112, 32}; + rcRight[4] = {48, 16, 64, 32}; + rcRight[5] = {112, 16, 128, 32}; + + switch (npc->act_no) + { + case 0: + npc->act_no = 1; + npc->ani_no = 0; + npc->ani_wait = 0; + npc->xm = 0; + // Fallthrough + case 1: + if (Random(0, 100) == 1) + { + npc->act_no = 2; + npc->act_wait = 0; + npc->ani_no = 1; + } + else + { + if (Random(0, 150) == 1) + { + if (npc->direct == 0) + npc->direct = 2; + else + npc->direct = 0; + } + + if (Random(0, 150) == 1) + { + npc->act_no = 3; + npc->act_wait = 50; + npc->ani_no = 0; + } + } + + break; + + case 2: + if (++npc->act_wait > 8) + { + npc->act_no = 1; + npc->ani_no = 0; + } + + break; + + case 3: + npc->act_no = 4; + npc->ani_no = 2; + npc->ani_wait = 0; + // Fallthrough + case 4: + if (--npc->act_wait == 0) + npc->act_no = 0; + + if (++npc->ani_wait > 2) + { + npc->ani_wait = 0; + ++npc->ani_no; + } + + if (npc->ani_no > 4) + npc->ani_no = 2; + + if (npc->flag & 1) + { + npc->direct = 2; + npc->xm = 0x200; + } + + if (npc->flag & 4) + { + npc->direct = 0; + npc->xm = -0x200; + } + + if (npc->direct == 0) + npc->xm = -0x100u; + else + npc->xm = 0x100; + + break; + + case 5: + if (npc->flag & 8) + npc->act_no = 0; + + break; + } + + switch (npc->act_no) + { + case 1: + case 2: + case 4: + if (npc->shock) + { + npc->ym = -0x200; + npc->ani_no = 5; + npc->act_no = 5; + } + + break; + } + + npc->ym += 0x40; + if (npc->ym > 0x5FF) + npc->ym = 0x5FF; + + npc->x += npc->xm; + npc->y += npc->ym; + + if (npc->direct == 0) + npc->rect = rcLeft[npc->ani_no]; + else + npc->rect = rcRight[npc->ani_no]; +} + //Sparkle void ActNpc070(NPCHAR *npc) { diff --git a/src/NpcAct080.cpp b/src/NpcAct080.cpp index 7855b0db..429ba103 100644 --- a/src/NpcAct080.cpp +++ b/src/NpcAct080.cpp @@ -10,6 +10,298 @@ #include "Triangle.h" #include "Caret.h" +//Gravekeeper +void ActNpc080(NPCHAR *npc) +{ + RECT rcLeft[7]; + RECT rcRight[7]; + + rcLeft[0] = {0, 64, 24, 88}; + rcLeft[1] = {24, 64, 48, 88}; + rcLeft[2] = {0, 64, 24, 88}; + rcLeft[3] = {48, 64, 72, 88}; + rcLeft[4] = {72, 64, 96, 88}; + rcLeft[5] = {96, 64, 120, 88}; + rcLeft[6] = {120, 64, 144, 88}; + + rcRight[0] = {0, 88, 24, 112}; + rcRight[1] = {24, 88, 48, 112}; + rcRight[2] = {0, 88, 24, 112}; + rcRight[3] = {48, 88, 72, 112}; + rcRight[4] = {72, 88, 96, 112}; + rcRight[5] = {96, 88, 120, 112}; + rcRight[6] = {120, 88, 144, 112}; + + switch (npc->act_no) + { + case 0: + npc->bits &= ~0x20; + npc->act_no = 1; + npc->damage = 0; + npc->hit.front = 0x800; + // Fallthrough + case 1: + npc->ani_no = 0; + + if (npc->x - 0x10000 < gMC.x && npc->x + 0x10000 > gMC.x && npc->y - 0x6000 < gMC.y && npc->y + 0x4000 > gMC.y) + { + npc->ani_wait = 0; + npc->act_no = 2; + } + + if (npc->shock) + { + npc->ani_no = 1; + npc->ani_wait = 0; + npc->act_no = 2; + npc->bits &= ~0x20u; + } + + if (gMC.x >= npc->x) + npc->direct = 2; + else + npc->direct = 0; + + break; + + case 2: + if (++npc->ani_wait > 6) + { + npc->ani_wait = 0; + ++npc->ani_no; + } + + if (npc->ani_no > 3) + npc->ani_no = 0; + + if (npc->x - 0x2000 < gMC.x && npc->x + 0x2000 > gMC.x) + { + npc->hit.front = 0x2400; + npc->act_wait = 0; + npc->act_no = 3; + npc->bits |= 0x20; + PlaySoundObject(34, 1); + + if (npc->direct == 0) + npc->xm = -0x400; + else + npc->xm = 0x400; + } + + if (gMC.x >= npc->x) + { + npc->direct = 2; + npc->xm = 0x100; + } + else + { + npc->direct = 0; + npc->xm = -0x100; + } + + break; + + case 3: + npc->xm = 0; + + if (++npc->act_wait > 40) + { + npc->act_wait = 0; + npc->act_no = 4; + PlaySoundObject(106, 1); + } + + npc->ani_no = 4; + break; + + case 4: + npc->damage = 10; + + if (++npc->act_wait > 2) + { + npc->act_wait = 0; + npc->act_no = 5; + } + + npc->ani_no = 5; + break; + + case 5: + npc->ani_no = 6; + + if (++npc->act_wait > 60) + npc->act_no = 0; + + break; + } + + if (npc->xm < 0 && npc->flag & 1) + npc->xm = 0; + if (npc->xm > 0 && npc->flag & 4) + npc->xm = 0; + + npc->ym += 0x20; + + if (npc->xm > 0x400) + npc->xm = 0x400; + if (npc->xm < -0x400) + npc->xm = -0x400; + + if (npc->ym > 0x5FF) + npc->xm = 0x5FF; + if (npc->ym < -0x5FF) + npc->xm = -0x5FF; + + npc->x += npc->xm; + npc->y += npc->ym; + + if (npc->direct == 0) + npc->rect = rcLeft[npc->ani_no]; + else + npc->rect = rcRight[npc->ani_no]; +} + +//Giant pignon +void ActNpc081(NPCHAR *npc) +{ + RECT rcLeft[6]; + RECT rcRight[6]; + + rcLeft[0] = {144, 64, 168, 88}; + rcLeft[1] = {168, 64, 192, 88}; + rcLeft[2] = {192, 64, 216, 88}; + rcLeft[3] = {216, 64, 240, 88}; + rcLeft[4] = {144, 64, 168, 88}; + rcLeft[5] = {240, 64, 264, 88}; + + rcRight[0] = {144, 88, 168, 112}; + rcRight[1] = {168, 88, 192, 112}; + rcRight[2] = {192, 88, 216, 112}; + rcRight[3] = {216, 88, 240, 112}; + rcRight[4] = {144, 88, 168, 112}; + rcRight[5] = {240, 88, 264, 112}; + + switch (npc->act_no) + { + case 0: + npc->act_no = 1; + npc->ani_no = 0; + npc->ani_wait = 0; + npc->xm = 0; + // Fallthrough + case 1: + if (Random(0, 100) == 1) + { + npc->act_no = 2; + npc->act_wait = 0; + npc->ani_no = 1; + } + else + { + if (Random(0, 150) == 1) + { + if (npc->direct == 0) + npc->direct = 2; + else + npc->direct = 0; + } + + if (Random(0, 150) == 1) + { + npc->act_no = 3; + npc->act_wait = 50; + npc->ani_no = 0; + } + } + + break; + + case 2: + if (++npc->act_wait > 8) + { + npc->act_no = 1; + npc->ani_no = 0; + } + + break; + + case 3: + npc->act_no = 4; + npc->ani_no = 2; + npc->ani_wait = 0; + // Fallthrough + case 4: + if (--npc->act_wait == 0) + npc->act_no = 0; + + if (++npc->ani_wait > 2) + { + npc->ani_wait = 0; + ++npc->ani_no; + } + + if (npc->ani_no > 4) + npc->ani_no = 2; + + if (npc->flag & 1) + { + npc->direct = 2; + npc->xm = 0x200; + } + + if (npc->flag & 4) + { + npc->direct = 0; + npc->xm = -0x200; + } + + if (npc->direct == 0) + npc->xm = -0x100; + else + npc->xm = 0x100; + + break; + + case 5: + if (npc->flag & 8) + npc->act_no = 0; + + break; + } + + switch (npc->act_no) + { + case 1: + case 2: + case 4: + if (npc->shock ) + { + npc->ym = -0x200; + npc->ani_no = 5; + npc->act_no = 5; + + if (npc->x >= gMC.x) + npc->xm = -0x100; + else + npc->xm = 0x100; + } + + break; + } + + npc->ym += 0x40; + if (npc->ym > 0x5FF) + npc->ym = 0x5FF; + + npc->x += npc->xm; + npc->y += npc->ym; + + if (npc->direct == 0) + npc->rect = rcLeft[npc->ani_no]; + else + npc->rect = rcRight[npc->ani_no]; +} + //Igor (cutscene) void ActNpc083(NPCHAR *npc) { diff --git a/src/NpcAct260.cpp b/src/NpcAct260.cpp new file mode 100644 index 00000000..1c24abcd --- /dev/null +++ b/src/NpcAct260.cpp @@ -0,0 +1,122 @@ +#include "WindowsWrapper.h" + +#include "NpcAct.h" + +#include "MyChar.h" +#include "NpChar.h" +#include "Game.h" +#include "Sound.h" +#include "Back.h" +#include "Triangle.h" + +//Little family +void ActNpc278(NPCHAR *npc) +{ + RECT rcMama[2]; + RECT rcPapa[2]; + RECT rcKodomo[2]; + + rcPapa[0] = {0, 120, 8, 128}; + rcPapa[1] = {8, 120, 16, 128}; + + rcMama[0] = {16, 120, 24, 128}; + rcMama[1] = {24, 120, 32, 128}; + + rcKodomo[0] = {32, 120, 40, 128}; + rcKodomo[1] = {40, 120, 48, 128}; + + switch (npc->act_no) + { + case 0: + npc->act_no = 1; + npc->ani_no = 0; + npc->ani_wait = 0; + npc->xm = 0; + // Fallthrough + case 1: + if (Random(0, 60) == 1) + { + npc->act_no = 2; + npc->act_wait = 0; + npc->ani_no = 1; + } + + if (Random(0, 60) == 1) + { + npc->act_no = 10; + npc->act_wait = 0; + npc->ani_no = 1; + } + + break; + + case 2: + if (++npc->act_wait > 8) + { + npc->act_no = 1; + npc->ani_no = 0; + } + + break; + + case 10: + npc->act_no = 11; + npc->act_wait = Random(0, 16); + npc->ani_no = 0; + npc->ani_wait = 0; + + if (Random(0, 9) % 2) + npc->direct = 0; + else + npc->direct = 2; + + // Fallthrough + case 11: + if (npc->direct == 0 && (npc->flag & 1)) + npc->direct = 2; + else if ( npc->direct == 2 && npc->flag & 4 ) + npc->direct = 0; + + if (npc->direct == 0) + npc->xm = -0x100; + else + npc->xm = 0x100; + + if (++npc->ani_wait > 4) + { + npc->ani_wait = 0; + ++npc->ani_no; + } + + if (npc->ani_no > 1) + npc->ani_no = 0; + + if (++npc->act_wait > 0x20) + npc->act_no = 0; + + break; + } + + npc->ym += 0x20; + if (npc->ym > 0x5FF) + npc->ym = 0x5FF; + + npc->x += npc->xm; + npc->y += npc->ym; + + + switch (npc->code_event) + { + case 200: + npc->rect = rcPapa[npc->ani_no]; + break; + + case 210: + npc->rect = rcMama[npc->ani_no]; + break; + + default: + npc->rect = rcKodomo[npc->ani_no]; + break; + } +} diff --git a/src/NpcTbl.cpp b/src/NpcTbl.cpp index 8b41e041..8fb6aeb0 100644 --- a/src/NpcTbl.cpp +++ b/src/NpcTbl.cpp @@ -125,7 +125,7 @@ NPCFUNCTION gpNpcFuncTbl[361] = nullptr, nullptr, nullptr, - nullptr, + ActNpc069, ActNpc070, ActNpc071, ActNpc072, @@ -136,8 +136,8 @@ NPCFUNCTION gpNpcFuncTbl[361] = ActNpc077, ActNpc078, ActNpc079, - nullptr, - nullptr, + ActNpc080, + ActNpc081, nullptr, ActNpc083, ActNpc084, @@ -334,7 +334,7 @@ NPCFUNCTION gpNpcFuncTbl[361] = nullptr, nullptr, nullptr, - nullptr, + ActNpc278, nullptr, nullptr, nullptr, From b62471120416b1eaeb1274d0beb08191592a51d6 Mon Sep 17 00:00:00 2001 From: Clownacy Date: Wed, 30 Jan 2019 18:56:01 +0000 Subject: [PATCH 4/7] Added Grasstown Critters --- src/NpcAct.h | 3 +- src/NpcAct020.cpp | 359 ++++++++++++++++++++++++++++++++++++++++++++++ src/NpcTbl.cpp | 4 +- 3 files changed, 363 insertions(+), 3 deletions(-) diff --git a/src/NpcAct.h b/src/NpcAct.h index 56199a52..ca40f6ea 100644 --- a/src/NpcAct.h +++ b/src/NpcAct.h @@ -21,9 +21,10 @@ void ActNpc020(NPCHAR *npc); void ActNpc021(NPCHAR *npc); void ActNpc022(NPCHAR *npc); void ActNpc023(NPCHAR *npc); - +void ActNpc024(NPCHAR *npc); void ActNpc025(NPCHAR *npc); +void ActNpc028(NPCHAR *npc); void ActNpc029(NPCHAR *npc); void ActNpc030(NPCHAR *npc); diff --git a/src/NpcAct020.cpp b/src/NpcAct020.cpp index 72dee4ec..09d9d06a 100644 --- a/src/NpcAct020.cpp +++ b/src/NpcAct020.cpp @@ -9,6 +9,7 @@ #include "Back.h" #include "Triangle.h" #include "Caret.h" +#include "Frame.h" //Computer void ActNpc020(NPCHAR *npc) @@ -108,6 +109,184 @@ void ActNpc023(NPCHAR *npc) npc->rect = rect[npc->ani_no]; } +//Power Critter +void ActNpc024(NPCHAR *npc) +{ + RECT rcLeft[6]; + RECT rcRight[6]; + + rcLeft[0] = {0, 0, 24, 24}; + rcLeft[1] = {24, 0, 48, 24}; + rcLeft[2] = {48, 0, 72, 24}; + rcLeft[3] = {72, 0, 96, 24}; + rcLeft[4] = {96, 0, 120, 24}; + rcLeft[5] = {120, 0, 144, 24}; + + rcRight[0] = {0, 24, 24, 48}; + rcRight[1] = {24, 24, 48, 48}; + rcRight[2] = {48, 24, 72, 48}; + rcRight[3] = {72, 24, 96, 48}; + rcRight[4] = {96, 24, 120, 48}; + rcRight[5] = {120, 24, 144, 48}; + + switch (npc->act_no) + { + case 0: + npc->y += 0x600; + npc->act_no = 1; + // Fallthrough + case 1: + if (npc->act_wait >= 8 && gMC.x > npc->x - 0x10000 && gMC.x < npc->x + 0x10000 && gMC.y > npc->y - 0x10000 && gMC.y < npc->y + 0x6000) + { + if (gMC.x < npc->x) + npc->direct = 0; + else + npc->direct = 2; + + npc->ani_no = 1; + } + else + { + if (npc->act_wait < 8) + ++npc->act_wait; + + npc->ani_no = 0; + } + + if (npc->shock) + { + npc->act_no = 2; + npc->ani_no = 0; + npc->act_wait = 0; + } + + if (npc->act_wait >= 8 && gMC.x > npc->x - 0xC000 && gMC.x < npc->x + 0xC000 && gMC.y > npc->y - 0xC000 && gMC.y < npc->y + 0x6000) + { + npc->act_no = 2; + npc->ani_no = 0; + npc->act_wait = 0; + } + + break; + + case 2: + if (++npc->act_wait > 8) + { + npc->act_no = 3; + npc->ani_no = 2; + npc->ym = -0x5FF; + PlaySoundObject(108, 1); + + if (gMC.x < npc->x) + npc->direct = 0; + else + npc->direct = 2; + + if (npc->direct == 0) + npc->xm = -0x100; + else + npc->xm = 0x100; + } + + break; + + case 3: + if (npc->ym > 0x200) + { + npc->tgt_y = npc->y; + npc->act_no = 4; + npc->ani_no = 3; + npc->act_wait = 0; + npc->act_wait = 0; + } + + break; + + case 4: + if (gMC.x > npc->x) + npc->direct = 2; + else + npc->direct = 0; + + ++npc->act_wait; + + if (npc->flag & 7 || npc->act_wait > 100) + { + npc->damage = 12; + npc->act_no = 5; + npc->ani_no = 2; + npc->xm /= 2; + } + else + { + if (npc->act_wait % 4 == 1) + PlaySoundObject(110, 1); + + if (++npc->ani_wait > 0) + { + npc->ani_wait = 0; + ++npc->ani_no; + } + + if (npc->ani_no > 5) + npc->ani_no = 3; + } + + break; + + case 5: + if (npc->flag & 8) + { + npc->damage = 2; + npc->xm = 0; + npc->act_wait = 0; + npc->ani_no = 0; + npc->act_no = 1; + PlaySoundObject(26, 1); + SetQuake(30); + } + + break; + } + + if (npc->act_no == 4) + { + if (gMC.x > npc->x) + npc->xm += 0x20; + else + npc->xm -= 0x20; + + if (npc->tgt_y < npc->y) + npc->ym -= 0x10; + else + npc->ym += 0x10; + + if (npc->ym > 0x200) + npc->ym = 0x200; + if (npc->ym < -0x200) + npc->ym = -0x200; + + if (npc->xm > 0x200) + npc->xm = 0x200; + if (npc->xm < -0x200) + npc->xm = -0x200; + } + else + { + npc->ym += 0x20; + if (npc->ym > 0x5FF) + npc->ym = 0x5FF; + } + + npc->x += npc->xm; + npc->y += npc->ym; + + if (npc->direct == 0) + npc->rect = rcLeft[npc->ani_no]; + else + npc->rect = rcRight[npc->ani_no]; +} + // Egg Corridor lift void ActNpc025(NPCHAR *npc) { @@ -234,6 +413,186 @@ void ActNpc025(NPCHAR *npc) npc->rect = rcLeft[npc->ani_no]; } +//Flying Critter (Grasstown) +void ActNpc028(NPCHAR *npc) +{ + RECT rcLeft[6]; + RECT rcRight[6]; + + rcLeft[0] = {0, 48, 16, 64}; + rcLeft[1] = {16, 48, 32, 64}; + rcLeft[2] = {32, 48, 48, 64}; + rcLeft[3] = {48, 48, 64, 64}; + rcLeft[4] = {64, 48, 80, 64}; + rcLeft[5] = {80, 48, 96, 64}; + + rcRight[0] = {0, 64, 16, 80}; + rcRight[1] = {16, 64, 32, 80}; + rcRight[2] = {32, 64, 48, 80}; + rcRight[3] = {48, 64, 64, 80}; + rcRight[4] = {64, 64, 80, 80}; + rcRight[5] = {80, 64, 96, 80}; + + switch (npc->act_no) + { + case 0: + npc->y += 0x600; + npc->act_no = 1; + // Fallthrough + case 1: + if (npc->act_wait >= 8 && gMC.x > npc->x - 0x10000 && gMC.x < npc->x + 0x10000 && gMC.y > npc->y - 0x10000 && gMC.y < npc->y + 0x6000) + { + if (gMC.x < npc->x) + npc->direct = 0; + else + npc->direct = 2; + + npc->ani_no = 1; + } + else + { + if (npc->act_wait < 8) + ++npc->act_wait; + + npc->ani_no = 0; + } + + if (npc->shock) + { + npc->act_no = 2; + npc->ani_no = 0; + npc->act_wait = 0; + } + + if ( npc->act_wait >= 8 && gMC.x > npc->x - 0xC000 && gMC.x < npc->x + 0xC000 && gMC.y > npc->y - 0xC000 && gMC.y < npc->y + 0x6000) + { + npc->act_no = 2; + npc->ani_no = 0; + npc->act_wait = 0; + } + + break; + + case 2: + if (++npc->act_wait > 8) + { + npc->act_no = 3; + npc->ani_no = 2; + npc->ym = -1228; + PlaySoundObject(30, 1); + + if (gMC.x < npc->x) + npc->direct = 0; + else + npc->direct = 2; + + if (npc->direct == 0) + npc->xm = -0x100u; + else + npc->xm = 0x100; + } + + break; + + case 3: + if (npc->ym > 0x100) + { + npc->tgt_y = npc->y; + npc->act_no = 4; + npc->ani_no = 3; + npc->act_wait = 0; + npc->act_wait = 0; + } + + break; + + case 4: + if (gMC.x > npc->x) + npc->direct = 2; + else + npc->direct = 0; + + ++npc->act_wait; + + if (npc->flag & 7 || npc->act_wait > 100) + { + npc->damage = 3; + npc->act_no = 5; + npc->ani_no = 2; + npc->xm /= 2; + } + else + { + if (npc->act_wait % 4 == 1) + PlaySoundObject(109, 1); + + if (npc->flag & 8) + npc->ym = -0x200; + + if (++npc->ani_wait > 0) + { + npc->ani_wait = 0; + ++npc->ani_no; + } + + if (npc->ani_no > 5) + npc->ani_no = 3; + } + + break; + + case 5: + if (npc->flag & 8) + { + npc->damage = 2; + npc->xm = 0; + npc->act_wait = 0; + npc->ani_no = 0; + npc->act_no = 1; + PlaySoundObject(23, 1); + } + + break; + } + + if (npc->act_no == 4) + { + if (gMC.x > npc->x) + npc->xm += 0x20; + else + npc->xm -= 0x20; + + if (npc->tgt_y < npc->y) + npc->ym -= 0x10; + else + npc->ym += 0x10; + + if (npc->ym > 0x200) + npc->ym = 0x200; + if (npc->ym < -0x200) + npc->ym = -0x200; + + if (npc->xm > 0x200) + npc->xm = 0x200; + if (npc->xm < -0x200) + npc->xm = -0x200; + } + else + { + npc->ym += 0x40; + if (npc->ym > 0x5FF) + npc->ym = 0x5FF; + } + + npc->x += npc->xm; + npc->y += npc->ym; + + if (npc->direct == 0) + npc->rect = rcLeft[npc->ani_no]; + else + npc->rect = rcRight[npc->ani_no]; +} + //Cthulhu void ActNpc029(NPCHAR *npc) { diff --git a/src/NpcTbl.cpp b/src/NpcTbl.cpp index 8fb6aeb0..0b79d230 100644 --- a/src/NpcTbl.cpp +++ b/src/NpcTbl.cpp @@ -80,11 +80,11 @@ NPCFUNCTION gpNpcFuncTbl[361] = ActNpc021, ActNpc022, ActNpc023, - nullptr, + ActNpc024, ActNpc025, nullptr, nullptr, - nullptr, + ActNpc028, ActNpc029, ActNpc030, nullptr, From ad6e7d98eab8ad7da27cdb0b9c23810396d6368f Mon Sep 17 00:00:00 2001 From: Clownacy Date: Wed, 30 Jan 2019 19:22:24 +0000 Subject: [PATCH 5/7] Fixed audio volume being half of what it should be --- src/Sound.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sound.cpp b/src/Sound.cpp index e5763a9b..0ffa620f 100644 --- a/src/Sound.cpp +++ b/src/Sound.cpp @@ -199,7 +199,7 @@ void SOUNDBUFFER::Mix(float *buffer, int len) float sampleA = (float)sample1 + ((float)sample2 - (float)sample1) * subPos; //Convert sample to float32 - float sampleConvert = (sampleA - 128.0) / 256.0; + float sampleConvert = (sampleA - 128.0) / 128.0; //Mix buffer[sample * 2] += sampleConvert * volume * volume_l; From 763c7d56c5fe13500ebc2d0e6f76ca3ef4dc7a8b Mon Sep 17 00:00:00 2001 From: Clownacy Date: Wed, 30 Jan 2019 19:48:57 +0000 Subject: [PATCH 6/7] Sound.cpp cleanup --- src/Sound.cpp | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/Sound.cpp b/src/Sound.cpp index 0ffa620f..39c0734e 100644 --- a/src/Sound.cpp +++ b/src/Sound.cpp @@ -129,7 +129,7 @@ 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); + return pow(10.0, lVolume / 2000.0); } void SOUNDBUFFER::SetVolume(int32_t lVolume) @@ -174,36 +174,32 @@ void SOUNDBUFFER::Stop() SDL_UnlockAudioDevice(audioDevice); } -void SOUNDBUFFER::Mix(float *buffer, int len) +void SOUNDBUFFER::Mix(float (*buffer)[2], size_t samples) { if (this == NULL) return; 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 + const double freqPosition = frequency / 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]; + const float sample1 = ((looped || ((size_t)samplePosition) >= 1) ? data[(size_t)samplePosition] : 0x80); + const float sample2 = ((looping || (((size_t)samplePosition) + 1) < size) ? data[(((size_t)samplePosition) + 1) % size] : 0x80); //Interpolate sample - float subPos = std::fmod(samplePosition, 1.0); - float sampleA = (float)sample1 + ((float)sample2 - (float)sample1) * subPos; + const float subPos = std::fmod(samplePosition, 1.0); + const float sampleA = sample1 + (sample2 - sample1) * subPos; //Convert sample to float32 - float sampleConvert = (sampleA - 128.0) / 128.0; + const float sampleConvert = (sampleA - 128.0f) / 128.0f; //Mix - buffer[sample * 2] += sampleConvert * volume * volume_l; - buffer[sample * 2 + 1] += sampleConvert * volume * volume_r; + buffer[sample][0] += sampleConvert * volume * volume_l; + buffer[sample][1] += sampleConvert * volume * volume_r; //Increment position samplePosition += freqPosition; @@ -229,14 +225,19 @@ void SOUNDBUFFER::Mix(float *buffer, int len) //Sound mixer void AudioCallback(void *userdata, uint8_t *stream, int len) { + float (*buffer)[2] = (float(*)[2])stream; + const size_t samples = len / (sizeof(float) * 2); + //Clear stream - memset(stream, 0, len); + for (size_t sample = 0; sample < samples; ++sample) + { + buffer[sample][0] = 0.0f; + buffer[sample][1] = 0.0f; + } //Mix sounds to primary buffer for (SOUNDBUFFER *sound = soundBuffers; sound != nullptr; sound = sound->next) - { - sound->Mix((float*)stream, len); - } + sound->Mix(buffer, samples); } //Sound things From cc3c12d065433e00e8fddd311f7098463633d958 Mon Sep 17 00:00:00 2001 From: Clownacy Date: Wed, 30 Jan 2019 20:08:56 +0000 Subject: [PATCH 7/7] Fix some dumbs and comment some funnies --- src/NpcAct020.cpp | 6 +++--- src/Sound.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/NpcAct020.cpp b/src/NpcAct020.cpp index 09d9d06a..83c7a49c 100644 --- a/src/NpcAct020.cpp +++ b/src/NpcAct020.cpp @@ -197,7 +197,7 @@ void ActNpc024(NPCHAR *npc) npc->act_no = 4; npc->ani_no = 3; npc->act_wait = 0; - npc->act_wait = 0; + npc->act_wait = 0; // lol duplicate line } break; @@ -487,7 +487,7 @@ void ActNpc028(NPCHAR *npc) npc->direct = 2; if (npc->direct == 0) - npc->xm = -0x100u; + npc->xm = -0x100; else npc->xm = 0x100; } @@ -501,7 +501,7 @@ void ActNpc028(NPCHAR *npc) npc->act_no = 4; npc->ani_no = 3; npc->act_wait = 0; - npc->act_wait = 0; + npc->act_wait = 0; // lol duplicate line } break; diff --git a/src/Sound.h b/src/Sound.h index 3c02e75f..2e78292c 100644 --- a/src/Sound.h +++ b/src/Sound.h @@ -20,7 +20,7 @@ class SOUNDBUFFER void Play(bool bLooping); void Stop(); - void Mix(float *buffer, int len); + void Mix(float (*buffer)[2], size_t samples); SOUNDBUFFER *next;