From 243fbb27620eb7a33c87f6af734d0546013406d6 Mon Sep 17 00:00:00 2001 From: KaiN Date: Wed, 19 Jul 2023 16:01:44 +0200 Subject: [PATCH 01/33] fix showcase asset copy --- showcase/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/showcase/CMakeLists.txt b/showcase/CMakeLists.txt index f1bb2145..2212c273 100644 --- a/showcase/CMakeLists.txt +++ b/showcase/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.5) +cmake_minimum_required(VERSION 3.14) project(showcase) # Lowercase project name for binaries and packaging @@ -56,4 +56,4 @@ endif() target_link_libraries(${GAME_LINKED} ace) # Copy example maps files as is -file(COPY "${RES_DIR}/data" DESTINATION ${DATA_DIR}) +file(COPY "${RES_DIR}/data" DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) From a62f4b4b51bce8bdff0a09beee569ba64a7daf16 Mon Sep 17 00:00:00 2001 From: KaiN Date: Wed, 19 Jul 2023 16:02:10 +0200 Subject: [PATCH 02/33] add input handler for reading keyboard state when os is alive --- include/ace/managers/system.h | 6 +- src/ace/managers/key.c | 17 +++- src/ace/managers/system.c | 152 ++++++++++++++++++++++++++++------ 3 files changed, 144 insertions(+), 31 deletions(-) diff --git a/include/ace/managers/system.h b/include/ace/managers/system.h index 68d591ee..d4b1d132 100644 --- a/include/ace/managers/system.h +++ b/include/ace/managers/system.h @@ -21,6 +21,8 @@ typedef void (*tAceIntHandler)( REGARG(volatile tCustom *pCustom, "a0"), REGARG(volatile void *pData, "a1") ); +typedef void (*tKeyInputHandler)(UBYTE ubRawKeyCode); + //-------------------------------------------------------------------- FUNCTIONS /** @@ -54,10 +56,12 @@ UBYTE systemBlitterIsUsed(void); void systemDump(void); +void systemSetKeyInputHandler(tKeyInputHandler cbKeyInputHandler); + void systemSetInt(UBYTE ubIntNumber, tAceIntHandler pHandler, void *pIntData); void systemSetCiaInt( - UBYTE ubCia, UBYTE ubIntBit, tAceIntHandler pHandler, void *pIntData + UBYTE ubCia, UBYTE ubIntBit, tAceIntHandler cbHandler, void *pIntData ); void systemSetCiaCr(UBYTE ubCia, UBYTE isCrB, UBYTE ubCrValue); diff --git a/src/ace/managers/key.c b/src/ace/managers/key.c index 86ff6349..24d9e862 100644 --- a/src/ace/managers/key.c +++ b/src/ace/managers/key.c @@ -8,7 +8,8 @@ #include #include #include // INTB_PORTS -#define KEY_RELEASED_BIT 1 +#define KEY_INTERRUPT_RELEASED_BIT 1 +#define KEY_INPUT_HANDLER_RELEASED_MASK BV(7) #if defined ACE_DEBUG static UBYTE s_bInitCount = 0; @@ -35,13 +36,19 @@ void keySetState(UBYTE ubKeyCode, UBYTE ubKeyState) { keyIntSetState(&g_sKeyManager, ubKeyCode, ubKeyState); } +void onRawKeyInput(UBYTE ubRawKey) { + UBYTE isKeyReleased = ubRawKey & KEY_INPUT_HANDLER_RELEASED_MASK; + ubRawKey &= ~KEY_INPUT_HANDLER_RELEASED_MASK; + keySetState(ubRawKey, isKeyReleased ? KEY_NACTIVE : KEY_ACTIVE); +} + /** * Key interrupt server * Gets key press/release from kbd controller and confirms reception * by handshake */ FN_HOTSPOT -void INTERRUPT keyIntServer( +void INTERRUPT onKeyInterrupt( REGARG(volatile tCustom *pCustom, "a0"), REGARG(volatile void *pData, "a1") ) { @@ -54,7 +61,7 @@ void INTERRUPT keyIntServer( UWORD uwStart = pRayPos->bfPosY; // Get keypress flag and shift key code - UBYTE ubKeyReleased = ubKeyCode & KEY_RELEASED_BIT; + UBYTE ubKeyReleased = ubKeyCode & KEY_INTERRUPT_RELEASED_BIT; ubKeyCode >>= 1; keyIntSetState( pKeyManager, ubKeyCode, ubKeyReleased ? KEY_NACTIVE : KEY_ACTIVE @@ -99,7 +106,8 @@ void keyCreate(void) { logWrite("ERR: Keyboard already initialized!\n"); } #endif - systemSetCiaInt(CIA_A, CIAICRB_SERIAL, keyIntServer, &g_sKeyManager); + systemSetCiaInt(CIA_A, CIAICRB_SERIAL, onKeyInterrupt, &g_sKeyManager); + systemSetKeyInputHandler(onRawKeyInput); logBlockEnd("keyCreate()"); } @@ -112,6 +120,7 @@ void keyDestroy(void) { } #endif systemSetCiaInt(CIA_A, CIAICRB_SERIAL, 0, 0); + systemSetKeyInputHandler(0); logBlockEnd("keyDestroy()"); } diff --git a/src/ace/managers/system.c b/src/ace/managers/system.c index d41f52f7..67446ef5 100644 --- a/src/ace/managers/system.c +++ b/src/ace/managers/system.c @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include #include @@ -86,6 +88,7 @@ static tHwIntVector s_pOsHwInterrupts[SYSTEM_INT_VECTOR_COUNT] = {0}; static tAceInterrupt s_pAceInterrupts[SYSTEM_INT_HANDLER_COUNT] = {{0}}; static tAceInterrupt s_pAceCiaInterrupts[CIA_COUNT][5] = {{{0}}}; static UWORD s_uwAceIntEna = INTF_VERTB | INTF_PORTS | INTF_EXTER; +static tKeyInputHandler s_cbKeyInputHandler; // Manager logic vars static WORD s_wSystemUses; @@ -95,8 +98,10 @@ struct GfxBase *GfxBase = 0; struct View *s_pOsView; static const UWORD s_uwOsMinDma = DMAF_DISK | DMAF_BLITTER; static struct IOAudio s_sIoAudio = {0}; +static struct IOStdReq s_sIoRequestInput = {0}; static struct Library *s_pCiaResource[CIA_COUNT]; static struct Process *s_pProcess; +static struct Interrupt s_sHandlerIo; #if defined(BARTMAN_GCC) struct DosLibrary *DOSBase = 0; @@ -303,6 +308,29 @@ void HWINTERRUPT int7Handler(void) { //-------------------------------------------------------------------- FUNCTIONS +static ULONG aceInputHandler(void) { + register volatile ULONG regNewEventChain __asm("d0"); + register volatile ULONG regOldEventChain __asm("a0"); + // register volatile ULONG regData __asm("a1"); + + if(s_cbKeyInputHandler) { + struct InputEvent *pEvent = (struct InputEvent *)regOldEventChain; + while(pEvent) { + if(pEvent->ie_Class == IECLASS_RAWKEY) { + // logWrite("OS key event: %hu\n", pEvent->ie_Code); + s_cbKeyInputHandler(pEvent->ie_Code); + } + // TODO: handle IECLASS_DISKREMOVED, IECLASS_DISKINSERTED ? + + pEvent = pEvent->ie_NextEvent; + } + } + + // Don't propagate any input events to other stuff - ensure full takeover + regNewEventChain = 0; + return regNewEventChain; +} + // Messageport creation for KS1.3 // http://amigadev.elowar.com/read/ADCD_2.1/Libraries_Manual_guide/node02EC.html static struct MsgPort *msgPortCreate(char *name, LONG pri) { @@ -341,42 +369,40 @@ static void msgPortDelete(struct MsgPort *mp) { FreeMem(mp, sizeof(*mp)); } -static UBYTE audioChannelAlloc(struct IOAudio *pIoAudio) { - struct MsgPort *pMsgPort = 0; - - pMsgPort = msgPortCreate("audio alloc", ADALLOC_MAXPREC); +static UBYTE audioChannelAlloc(void) { + struct MsgPort *pMsgPort = msgPortCreate("audio alloc", ADALLOC_MAXPREC); if(!pMsgPort) { logWrite("ERR: Couldn't open message port for audio alloc\n"); goto fail; } // We don't have CreateIORequest on ks1.3, so do what AROS does - memset(pIoAudio, 0, sizeof(*pIoAudio)); - pIoAudio->ioa_Request.io_Message.mn_Node.ln_Type = NT_MESSAGE; - pIoAudio->ioa_Request.io_Message.mn_ReplyPort = pMsgPort; - pIoAudio->ioa_Request.io_Message.mn_Length = sizeof(*pIoAudio); + memset(&s_sIoAudio, 0, sizeof(s_sIoAudio)); + s_sIoAudio.ioa_Request.io_Message.mn_Node.ln_Type = NT_MESSAGE; + s_sIoAudio.ioa_Request.io_Message.mn_ReplyPort = pMsgPort; + s_sIoAudio.ioa_Request.io_Message.mn_Length = sizeof(s_sIoAudio); UBYTE isError = OpenDevice( - (CONST_STRPTR)"audio.device", 0, (struct IORequest *)pIoAudio, 0 + (CONST_STRPTR)"audio.device", 0, (struct IORequest *)&s_sIoAudio, 0 ); if(isError) { logWrite( "ERR: Couldn't alloc Audio channels, code: %d\n", - pIoAudio->ioa_Request.io_Error + s_sIoAudio.ioa_Request.io_Error ); goto fail; } UBYTE ubChannelMask = 0b1111; // Allocate all 4 channels. - pIoAudio->ioa_Data = &ubChannelMask; - pIoAudio->ioa_Length = sizeof(ubChannelMask); - pIoAudio->ioa_Request.io_Command = ADCMD_ALLOCATE; - pIoAudio->ioa_Request.io_Flags = ADIOF_NOWAIT; - isError = DoIO((struct IORequest *)pIoAudio); + s_sIoAudio.ioa_Data = &ubChannelMask; + s_sIoAudio.ioa_Length = sizeof(ubChannelMask); + s_sIoAudio.ioa_Request.io_Command = ADCMD_ALLOCATE; + s_sIoAudio.ioa_Request.io_Flags = ADIOF_NOWAIT; + isError = DoIO((struct IORequest *)&s_sIoAudio); if(isError) { logWrite( - "ERR: io audio request fail, code: %d\n", pIoAudio->ioa_Request.io_Error + "ERR: io audio request fail, code: %d\n", s_sIoAudio.ioa_Request.io_Error ); goto fail; } @@ -389,20 +415,86 @@ static UBYTE audioChannelAlloc(struct IOAudio *pIoAudio) { return 0; } -void audioChannelFree(struct IOAudio *pIoAudio) { - struct MsgPort *pMsgPort = pIoAudio->ioa_Request.io_Message.mn_ReplyPort; +static void audioChannelFree(void) { + struct MsgPort *pMsgPort = s_sIoAudio.ioa_Request.io_Message.mn_ReplyPort; - pIoAudio->ioa_Request.io_Command = ADCMD_FINISH; - pIoAudio->ioa_Request.io_Flags = 0; - pIoAudio->ioa_Request.io_Unit = (APTR)1; - UBYTE isError = DoIO((struct IORequest *)pIoAudio); + s_sIoAudio.ioa_Request.io_Command = ADCMD_FINISH; + s_sIoAudio.ioa_Request.io_Flags = 0; + s_sIoAudio.ioa_Request.io_Unit = (APTR)1; + UBYTE isError = DoIO((struct IORequest *)&s_sIoAudio); if(isError) { logWrite( - "ERR: io audio request fail, code: %d\n", pIoAudio->ioa_Request.io_Error + "ERR: io audio request fail, code: %d\n", s_sIoAudio.ioa_Request.io_Error ); } - CloseDevice((struct IORequest *)pIoAudio); + CloseDevice((struct IORequest *)&s_sIoAudio); + msgPortDelete(pMsgPort); +} + +static UBYTE inputHandlerAdd(void) { + struct MsgPort *pMsgPort = msgPortCreate("input handler register", ADALLOC_MAXPREC); + if(!pMsgPort) { + logWrite("ERR: Couldn't open message port for audio alloc\n"); + goto fail; + } + + // We don't have CreateIORequest on ks1.3, so just zero stuff + memset(&s_sIoRequestInput, 0, sizeof(s_sIoRequestInput)); + UBYTE isError = OpenDevice( + (CONST_STRPTR)"input.device", 0, (struct IORequest *)&s_sIoRequestInput, 0 + ); + if(isError) { + logWrite( + "ERR: Couldn't open input device, code: %d\n", + s_sIoRequestInput.io_Error + ); + goto fail; + } + + memset(&s_sHandlerIo, 0, sizeof(s_sHandlerIo)); + s_sHandlerIo.is_Code = (void(*)(void))aceInputHandler; + s_sHandlerIo.is_Data = 0; + s_sHandlerIo.is_Node.ln_Pri = 127; + s_sHandlerIo.is_Node.ln_Name = "ACE Input handler"; + s_sIoRequestInput.io_Data = (APTR)&s_sHandlerIo; + s_sIoRequestInput.io_Command = IND_ADDHANDLER; + s_sIoRequestInput.io_Message.mn_ReplyPort = pMsgPort; + isError = DoIO((struct IORequest *)&s_sIoRequestInput); + + if(isError) { + logWrite( + "ERR: io audio request fail, code: %d\n", s_sIoRequestInput.io_Error + ); + goto fail; + } + logWrite("Registered event handler at %p", aceInputHandler); + return 1; + +fail: + if(pMsgPort) { + msgPortDelete(pMsgPort); + } + return 0; +} + +static void inputHandlerRemove(void) { + // http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_2._guide/node04E2.html + + struct MsgPort *pMsgPort = s_sIoRequestInput.io_Message.mn_ReplyPort; + + s_sIoRequestInput.io_Command = IND_REMHANDLER; + s_sIoRequestInput.io_Data=(APTR)&s_sHandlerIo; + UBYTE isError = DoIO((struct IORequest *)&s_sIoRequestInput); + if(isError) { + logWrite( + "ERR: io audio request fail, code: %d\n", s_sIoRequestInput.io_Error + ); + } + + // NOTE: IND_REMHANDLER is not immediate + + CloseDevice((struct IORequest *)&s_sIoRequestInput); msgPortDelete(pMsgPort); } @@ -498,7 +590,9 @@ void systemCreate(void) { // Reserve all audio channels - apparantly this allows for int flag polling // From https://gist.github.com/johngirvin/8fb0c4bb83b7c80427e2f439bb074e95 - audioChannelAlloc(&s_sIoAudio); + audioChannelAlloc(); + + inputHandlerAdd(); s_pCiaResource[CIA_A] = OpenResource((CONST_STRPTR)CIAANAME); s_pCiaResource[CIA_B] = OpenResource((CONST_STRPTR)CIABNAME); @@ -569,7 +663,9 @@ void systemDestroy(void) { g_pCustom->dmacon = DMAF_SETCLR | DMAF_MASTER | s_uwOsInitialDma; // Free audio channels - audioChannelFree(&s_sIoAudio); + audioChannelFree(); + + inputHandlerRemove(); // restore old view WaitTOF(); @@ -766,6 +862,10 @@ UBYTE systemBlitterIsUsed(void) { return s_wSystemBlitterUses > 0; } +void systemSetKeyInputHandler(tKeyInputHandler cbKeyInputHandler) { + s_cbKeyInputHandler = cbKeyInputHandler; +} + void systemSetInt( UBYTE ubIntNumber, tAceIntHandler pHandler, void *pIntData ) { From a6c3da4b078d9f921a8d76b7a9836302b0694ab8 Mon Sep 17 00:00:00 2001 From: KaiN Date: Wed, 19 Jul 2023 16:05:13 +0200 Subject: [PATCH 03/33] removed keyboard hack :tada: --- src/ace/managers/system.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/ace/managers/system.c b/src/ace/managers/system.c index 67446ef5..f70103e7 100644 --- a/src/ace/managers/system.c +++ b/src/ace/managers/system.c @@ -818,10 +818,6 @@ void systemUse(void) { // All interrupts but only needed DMA g_pCustom->dmacon = DMAF_SETCLR | DMAF_MASTER | (s_uwOsDmaCon & s_uwOsMinDma); g_pCustom->intena = INTF_SETCLR | INTF_INTEN | s_uwOsIntEna; - - // Nasty keyboard hack - if any key gets pressed / released while system is - // inactive, we won't be able to catch it. - keyReset(); } ++s_wSystemUses; From efcdce3f8152d84ec64d7f4fe65a623247bd1b45 Mon Sep 17 00:00:00 2001 From: KaiN Date: Wed, 19 Jul 2023 16:53:32 +0200 Subject: [PATCH 04/33] simplify handler code --- src/ace/managers/system.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/ace/managers/system.c b/src/ace/managers/system.c index f70103e7..2f26cde9 100644 --- a/src/ace/managers/system.c +++ b/src/ace/managers/system.c @@ -306,10 +306,9 @@ void HWINTERRUPT int7Handler(void) { logPopInt(); } -//-------------------------------------------------------------------- FUNCTIONS +//------------------------------------------------------------------ OS HANDLERS static ULONG aceInputHandler(void) { - register volatile ULONG regNewEventChain __asm("d0"); register volatile ULONG regOldEventChain __asm("a0"); // register volatile ULONG regData __asm("a1"); @@ -326,11 +325,12 @@ static ULONG aceInputHandler(void) { } } - // Don't propagate any input events to other stuff - ensure full takeover - regNewEventChain = 0; - return regNewEventChain; + // Don't propagate any input events to other stuff - ensure full takeover by clearing d0 + return 0; } +//-------------------------------------------------------------------- FUNCTIONS + // Messageport creation for KS1.3 // http://amigadev.elowar.com/read/ADCD_2.1/Libraries_Manual_guide/node02EC.html static struct MsgPort *msgPortCreate(char *name, LONG pri) { @@ -468,7 +468,6 @@ static UBYTE inputHandlerAdd(void) { ); goto fail; } - logWrite("Registered event handler at %p", aceInputHandler); return 1; fail: From 352d78bf09b9f0eb97cef3d16748216d6bfe05ed Mon Sep 17 00:00:00 2001 From: KaiN Date: Wed, 19 Jul 2023 17:44:47 +0200 Subject: [PATCH 05/33] remove vbcc defines because it's unsupported anyway --- include/ace/types.h | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/include/ace/types.h b/include/ace/types.h index e8f89c66..3433b9b4 100644 --- a/include/ace/types.h +++ b/include/ace/types.h @@ -52,24 +52,6 @@ typedef int32_t LONG; #define FN_HOTSPOT #define FN_COLDSPOT #define BITFIELD_STRUCT struct __attribute__((packed)) -#elif defined(__VBCC__) -#if defined(CONFIG_SYSTEM_OS_FRIENDLY) -#define INTERRUPT __amigainterrupt __saveds -#define INTERRUPT_END do {} while(0) -#elif defined(CONFIG_SYSTEM_OS_TAKEOVER) -#define INTERRUPT -#define INTERRUPT_END do {} while(0) -#endif - -#define HWINTERRUPT __interrupt __saveds -#define UNUSED_ARG -#define REGARG(arg, reg) __reg(reg) arg -#define CHIP __chip -#define FAR -#define INTERRUPT_END do {} while(0) -#define FN_HOTSPOT -#define FN_COLDSPOT -#define BITFIELD_STRUCT struct #elif defined(BARTMAN_GCC) #define INTERRUPT #define INTERRUPT_END do {} while(0) From c41ba1229a71b6564fa2f301d9f84042d3b17484 Mon Sep 17 00:00:00 2001 From: KaiN Date: Wed, 19 Jul 2023 17:45:11 +0200 Subject: [PATCH 06/33] added os-friendly CIA handling --- src/ace/managers/system.c | 49 +++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/src/ace/managers/system.c b/src/ace/managers/system.c index 2f26cde9..7a20d468 100644 --- a/src/ace/managers/system.c +++ b/src/ace/managers/system.c @@ -102,6 +102,7 @@ static struct IOStdReq s_sIoRequestInput = {0}; static struct Library *s_pCiaResource[CIA_COUNT]; static struct Process *s_pProcess; static struct Interrupt s_sHandlerIo; +static struct Interrupt s_pCiaIcrHandlers[CIA_COUNT][5]; #if defined(BARTMAN_GCC) struct DosLibrary *DOSBase = 0; @@ -329,6 +330,18 @@ static ULONG aceInputHandler(void) { return 0; } +ULONG ciaIcrHandler(void) { + register volatile ULONG regData __asm("a1"); + + tAceInterrupt *pAceInt = (tAceInterrupt *)regData; + if(pAceInt->pHandler) { + pAceInt->pHandler(g_pCustom, pAceInt->pData); + } + + // set the Z flag + return 0; +} + //-------------------------------------------------------------------- FUNCTIONS // Messageport creation for KS1.3 @@ -497,6 +510,25 @@ static void inputHandlerRemove(void) { msgPortDelete(pMsgPort); } +void ciaIcrHandlerAdd(UBYTE ubCia, UBYTE ubIcrBit) { + memset(&s_pCiaIcrHandlers[ubCia][ubIcrBit], 0, sizeof(s_pCiaIcrHandlers[ubCia][ubIcrBit])); + s_pCiaIcrHandlers[ubCia][ubIcrBit].is_Code = (void(*)(void))ciaIcrHandler; + s_pCiaIcrHandlers[ubCia][ubIcrBit].is_Data = (void*)&s_pAceCiaInterrupts[ubCia][ubIcrBit]; + s_pCiaIcrHandlers[ubCia][ubIcrBit].is_Node.ln_Name = "ACE CIA ICR handler"; + s_pCiaIcrHandlers[ubCia][ubIcrBit].is_Node.ln_Pri = 127; + s_pCiaIcrHandlers[ubCia][ubIcrBit].is_Node.ln_Type = NT_INTERRUPT; + if(AddICRVector(s_pCiaResource[ubCia], ubIcrBit, &s_pCiaIcrHandlers[ubCia][ubIcrBit])) { + logWrite("CIA %c ICR %d add failed", CIA_A ? 'A' : 'B', ubIcrBit); + } + + // Disable interrupt since AddICRVector auto-enables it + // AbleICR(s_pCiaResource[CIA_B], CIAICRF_TIMER_A); +} + +void ciaIcrHandlerRemove(UBYTE ubCia, UBYTE ubIcrBit) { + RemICRVector(s_pCiaResource[ubCia], ubIcrBit, &s_pCiaIcrHandlers[ubCia][ubIcrBit]); +} + /** * @brief Flushes FDD disk activity. * Originally written by Asman in asm, known as osflush @@ -596,6 +628,9 @@ void systemCreate(void) { s_pCiaResource[CIA_A] = OpenResource((CONST_STRPTR)CIAANAME); s_pCiaResource[CIA_B] = OpenResource((CONST_STRPTR)CIABNAME); + ciaIcrHandlerAdd(CIA_B, CIAICRB_TIMER_A); + ciaIcrHandlerAdd(CIA_B, CIAICRB_TIMER_B); + // Disable as much of OS stuff as possible so that it won't trash stuff when // re-enabled periodically. // Save the system copperlists and flush the view @@ -661,7 +696,9 @@ void systemDestroy(void) { systemReleaseBlitterToOs(); g_pCustom->dmacon = DMAF_SETCLR | DMAF_MASTER | s_uwOsInitialDma; - // Free audio channels + ciaIcrHandlerRemove(CIA_B, CIAICRB_TIMER_A); + ciaIcrHandlerRemove(CIA_B, CIAICRB_TIMER_B); + audioChannelFree(); inputHandlerRemove(); @@ -898,15 +935,13 @@ void systemSetCiaInt( void systemSetCiaCr(UBYTE ubCia, UBYTE isCrB, UBYTE ubCrValue) { if(isCrB) { s_pAceCiaCrb[ubCia] = ubCrValue; - if(!s_wSystemUses) { - g_pCia[ubCia]->crb = ubCrValue; - } + s_pOsCiaCrb[ubCia] = ubCrValue; + g_pCia[ubCia]->crb = ubCrValue; } else { s_pAceCiaCra[ubCia] = ubCrValue; - if(!s_wSystemUses) { - g_pCia[ubCia]->cra = ubCrValue; - } + s_pOsCiaCra[ubCia] = ubCrValue; + g_pCia[ubCia]->cra = ubCrValue; } } From 67daa09a89ba40a571b0222de1a07ac7ba2218a0 Mon Sep 17 00:00:00 2001 From: KaiN Date: Fri, 28 Jul 2023 18:48:41 +0200 Subject: [PATCH 07/33] add os-friendly audio interrupt handling --- src/ace/managers/system.c | 283 +++++++++++++++++++++++++------------- 1 file changed, 188 insertions(+), 95 deletions(-) diff --git a/src/ace/managers/system.c b/src/ace/managers/system.c index 7a20d468..a6deaa99 100644 --- a/src/ace/managers/system.c +++ b/src/ace/managers/system.c @@ -59,6 +59,7 @@ static const UWORD s_pGetVbrCode[] = {0x4e7a, 0x0801, 0x4e73}; // Saved regs static UWORD s_uwOsIntEna; +static UWORD s_uwOsInitialIntEna; ///< Before ACE's OS handlers got installed static UWORD s_uwOsDmaCon; static UWORD s_uwAceDmaCon = 0; static UWORD s_uwOsInitialDma; @@ -101,8 +102,14 @@ static struct IOAudio s_sIoAudio = {0}; static struct IOStdReq s_sIoRequestInput = {0}; static struct Library *s_pCiaResource[CIA_COUNT]; static struct Process *s_pProcess; -static struct Interrupt s_sHandlerIo; -static struct Interrupt s_pCiaIcrHandlers[CIA_COUNT][5]; +static struct Interrupt s_sOsHandlerIo; +static struct Interrupt s_pOsCiaIcrHandlers[CIA_COUNT][5]; +static struct Interrupt *s_pOsOldInterruptHandlers[14]; +static struct Interrupt s_pOsInterruptHandlers[14]; +static UWORD s_uwOsVectorInts = ( + INTF_TBE | INTF_DSKBLK | INTF_SOFTINT | + INTF_AUD0 | INTF_AUD1 | INTF_AUD2 | INTF_AUD3 | INTF_RBF | INTF_DSKSYNC +); #if defined(BARTMAN_GCC) struct DosLibrary *DOSBase = 0; @@ -342,6 +349,39 @@ ULONG ciaIcrHandler(void) { return 0; } +void osIntVector(void) { + register volatile ULONG regData __asm("a1"); + + UBYTE ubIntBit = regData; + if(s_pAceInterrupts[ubIntBit].pHandler) { + s_pAceInterrupts[ubIntBit].pHandler( + g_pCustom, s_pAceInterrupts[ubIntBit].pData + ); + } + + UWORD uwIntMask = BV(ubIntBit); + g_pCustom->intreq = uwIntMask; + g_pCustom->intreq = uwIntMask; +} + +ULONG osIntServer(void) { + register volatile ULONG regData __asm("a1"); + + UBYTE ubIntBit = regData; + if(s_pAceInterrupts[ubIntBit].pHandler) { + s_pAceInterrupts[ubIntBit].pHandler( + g_pCustom, s_pAceInterrupts[ubIntBit].pData + ); + } + + UWORD uwIntMask = BV(ubIntBit); + g_pCustom->intreq = uwIntMask; + g_pCustom->intreq = uwIntMask; + + // End chain for non-VERTB ints + return ubIntBit == INTB_VERTB ? 0 : 1; +} + //-------------------------------------------------------------------- FUNCTIONS // Messageport creation for KS1.3 @@ -465,12 +505,12 @@ static UBYTE inputHandlerAdd(void) { goto fail; } - memset(&s_sHandlerIo, 0, sizeof(s_sHandlerIo)); - s_sHandlerIo.is_Code = (void(*)(void))aceInputHandler; - s_sHandlerIo.is_Data = 0; - s_sHandlerIo.is_Node.ln_Pri = 127; - s_sHandlerIo.is_Node.ln_Name = "ACE Input handler"; - s_sIoRequestInput.io_Data = (APTR)&s_sHandlerIo; + memset(&s_sOsHandlerIo, 0, sizeof(s_sOsHandlerIo)); + s_sOsHandlerIo.is_Code = (void(*)(void))aceInputHandler; + s_sOsHandlerIo.is_Data = 0; + s_sOsHandlerIo.is_Node.ln_Pri = 127; + s_sOsHandlerIo.is_Node.ln_Name = "ACE Input handler"; + s_sIoRequestInput.io_Data = (APTR)&s_sOsHandlerIo; s_sIoRequestInput.io_Command = IND_ADDHANDLER; s_sIoRequestInput.io_Message.mn_ReplyPort = pMsgPort; isError = DoIO((struct IORequest *)&s_sIoRequestInput); @@ -496,7 +536,7 @@ static void inputHandlerRemove(void) { struct MsgPort *pMsgPort = s_sIoRequestInput.io_Message.mn_ReplyPort; s_sIoRequestInput.io_Command = IND_REMHANDLER; - s_sIoRequestInput.io_Data=(APTR)&s_sHandlerIo; + s_sIoRequestInput.io_Data=(APTR)&s_sOsHandlerIo; UBYTE isError = DoIO((struct IORequest *)&s_sIoRequestInput); if(isError) { logWrite( @@ -510,14 +550,125 @@ static void inputHandlerRemove(void) { msgPortDelete(pMsgPort); } +static void interruptHandlerAdd(UBYTE ubIntBit) { + struct Interrupt *pInterrupt = &s_pOsInterruptHandlers[ubIntBit]; + memset(pInterrupt, 0, sizeof(*pInterrupt)); + pInterrupt->is_Data = (void*)(ULONG)ubIntBit; + pInterrupt->is_Node.ln_Name = "ACE interrupt handler"; + pInterrupt->is_Node.ln_Type = NT_INTERRUPT; + if(BV(ubIntBit) & s_uwOsVectorInts) { + pInterrupt->is_Code = osIntVector; + + // Disable interrupt and swap the int vector + g_pCustom->intena = BV(ubIntBit); + s_pOsOldInterruptHandlers[ubIntBit] = SetIntVector(ubIntBit, pInterrupt); + } + else { + // VERTB servers should always return Z set and can't be sole handler + // NOTE: VERTB server with priority of 10 or greater must set a0 to 0xDFF000 + pInterrupt->is_Code = (void(*)(void))osIntServer; + pInterrupt->is_Node.ln_Pri = (ubIntBit == INTB_VERTB) ? 9 : 127; + // Auto-enables intena bit if first server is adder + AddIntServer(ubIntBit, pInterrupt); + } +} + +static void interruptHandlerRemove(UBYTE ubIntBit) { + if(BV(ubIntBit) & s_uwOsVectorInts) { + // Disable interrupt in case handler is set to null + g_pCustom->intena = BV(ubIntBit); + SetIntVector(ubIntBit, s_pOsOldInterruptHandlers[ubIntBit]); + + // A 3rd party handler could be installed but be inactive + if(s_uwOsInitialIntEna & BV(ubIntBit)) { + g_pCustom->intena = INTF_SETCLR | BV(ubIntBit); + } + } + else { + // Auto-disables intena bit if sole server is removed + RemIntServer(ubIntBit, &s_pOsInterruptHandlers[ubIntBit]); + } +} + +static void systemOsDisable(void) { + // Disable interrupts (this is the actual "kill system/OS" part) + g_pCustom->intena = 0x7FFF; + g_pCustom->intreq = 0x7FFF; + + // Query CIA ICR bits set by OS for later CIA takeover restore + s_pOsCiaIcr[CIA_A] = AbleICR(s_pCiaResource[CIA_A], 0); + s_pOsCiaIcr[CIA_B] = AbleICR(s_pCiaResource[CIA_B], 0); + + // Disable CIA interrupts + g_pCia[CIA_A]->icr = 0x7F; + g_pCia[CIA_B]->icr = 0x7F; + + // Save CRA bits + s_pOsCiaCra[CIA_A] = g_pCia[CIA_A]->cra; + s_pOsCiaCrb[CIA_A] = g_pCia[CIA_A]->crb; + s_pOsCiaCra[CIA_B] = g_pCia[CIA_B]->cra; + s_pOsCiaCrb[CIA_B] = g_pCia[CIA_B]->crb; + + // Disable timers and trigger reload of value to read preset val + g_pCia[CIA_A]->cra = CIACRA_LOAD; // CIACRA_START=0, timer is stopped + g_pCia[CIA_A]->crb = CIACRB_LOAD; + g_pCia[CIA_B]->cra = CIACRA_LOAD; // CIACRA_START=0, timer is stopped + g_pCia[CIA_B]->crb = CIACRB_LOAD; + + // Save OS CIA timer values + s_pOsCiaTimerA[CIA_A] = ciaGetTimerA(g_pCia[CIA_A]); + s_pOsCiaTimerB[CIA_A] = ciaGetTimerB(g_pCia[CIA_A]); + s_pOsCiaTimerA[CIA_B] = ciaGetTimerA(g_pCia[CIA_B]); + s_pOsCiaTimerB[CIA_B] = ciaGetTimerB(g_pCia[CIA_B]); + + // set ACE CIA timers + ciaSetTimerA(g_pCia[CIA_A], s_pAceCiaTimerA[CIA_A]); + ciaSetTimerB(g_pCia[CIA_A], s_pAceCiaTimerB[CIA_A]); + ciaSetTimerA(g_pCia[CIA_B], s_pAceCiaTimerA[CIA_B]); + ciaSetTimerB(g_pCia[CIA_B], s_pAceCiaTimerB[CIA_B]); + + // Enable ACE CIA interrupts + g_pCia[CIA_A]->icr = ( + CIAICRF_SETCLR | CIAICRF_SERIAL | CIAICRF_TIMER_A | CIAICRF_TIMER_B + ); + g_pCia[CIA_B]->icr = ( + CIAICRF_SETCLR | CIAICRF_SERIAL | CIAICRF_TIMER_A | CIAICRF_TIMER_B + ); + + // Restore ACE CIA CRA/CRB state + g_pCia[CIA_A]->cra = CIACRA_LOAD | s_pAceCiaCra[CIA_A]; + g_pCia[CIA_A]->crb = CIACRA_LOAD | s_pAceCiaCrb[CIA_A]; + g_pCia[CIA_B]->cra = CIACRA_LOAD | s_pAceCiaCra[CIA_B]; + g_pCia[CIA_B]->crb = CIACRA_LOAD | s_pAceCiaCrb[CIA_B]; + + // Game's bitplanes & copperlists are still used so don't disable them + // Wait for vbl before disabling sprite DMA + while (!(g_pCustom->intreqr & INTF_VERTB)) continue; + g_pCustom->dmacon = s_uwOsMinDma; + + // Save OS interrupt vectors and enable ACE's + g_pCustom->intreq = 0x7FFF; + for(UWORD i = 0; i < SYSTEM_INT_VECTOR_COUNT; ++i) { + s_pOsHwInterrupts[i] = s_pHwVectors[SYSTEM_INT_VECTOR_FIRST + i]; + s_pHwVectors[SYSTEM_INT_VECTOR_FIRST + i] = s_pAceHwInterrupts[i]; + } + + // Enable needed DMA (and interrupt) channels + g_pCustom->dmacon = DMAF_SETCLR | DMAF_MASTER | s_uwAceDmaCon; + // Everything that's supported by ACE to simplify things for now, + // but not audio channels since ptplayer relies on polling them, and I'm not + // currently being able to debug audio interrupt handler variant. + g_pCustom->intena = INTF_SETCLR | INTF_INTEN | s_uwAceIntEna; +} + void ciaIcrHandlerAdd(UBYTE ubCia, UBYTE ubIcrBit) { - memset(&s_pCiaIcrHandlers[ubCia][ubIcrBit], 0, sizeof(s_pCiaIcrHandlers[ubCia][ubIcrBit])); - s_pCiaIcrHandlers[ubCia][ubIcrBit].is_Code = (void(*)(void))ciaIcrHandler; - s_pCiaIcrHandlers[ubCia][ubIcrBit].is_Data = (void*)&s_pAceCiaInterrupts[ubCia][ubIcrBit]; - s_pCiaIcrHandlers[ubCia][ubIcrBit].is_Node.ln_Name = "ACE CIA ICR handler"; - s_pCiaIcrHandlers[ubCia][ubIcrBit].is_Node.ln_Pri = 127; - s_pCiaIcrHandlers[ubCia][ubIcrBit].is_Node.ln_Type = NT_INTERRUPT; - if(AddICRVector(s_pCiaResource[ubCia], ubIcrBit, &s_pCiaIcrHandlers[ubCia][ubIcrBit])) { + memset(&s_pOsCiaIcrHandlers[ubCia][ubIcrBit], 0, sizeof(s_pOsCiaIcrHandlers[ubCia][ubIcrBit])); + s_pOsCiaIcrHandlers[ubCia][ubIcrBit].is_Code = (void(*)(void))ciaIcrHandler; + s_pOsCiaIcrHandlers[ubCia][ubIcrBit].is_Data = (void*)&s_pAceCiaInterrupts[ubCia][ubIcrBit]; + s_pOsCiaIcrHandlers[ubCia][ubIcrBit].is_Node.ln_Name = "ACE CIA ICR handler"; + s_pOsCiaIcrHandlers[ubCia][ubIcrBit].is_Node.ln_Pri = 127; + s_pOsCiaIcrHandlers[ubCia][ubIcrBit].is_Node.ln_Type = NT_INTERRUPT; + if(AddICRVector(s_pCiaResource[ubCia], ubIcrBit, &s_pOsCiaIcrHandlers[ubCia][ubIcrBit])) { logWrite("CIA %c ICR %d add failed", CIA_A ? 'A' : 'B', ubIcrBit); } @@ -526,7 +677,7 @@ void ciaIcrHandlerAdd(UBYTE ubCia, UBYTE ubIcrBit) { } void ciaIcrHandlerRemove(UBYTE ubCia, UBYTE ubIcrBit) { - RemICRVector(s_pCiaResource[ubCia], ubIcrBit, &s_pCiaIcrHandlers[ubCia][ubIcrBit]); + RemICRVector(s_pCiaResource[ubCia], ubIcrBit, &s_pOsCiaIcrHandlers[ubCia][ubIcrBit]); } /** @@ -625,6 +776,12 @@ void systemCreate(void) { inputHandlerAdd(); + s_uwOsInitialIntEna = g_pCustom->intenar; + interruptHandlerAdd(INTB_AUD0); + interruptHandlerAdd(INTB_AUD1); + interruptHandlerAdd(INTB_AUD2); + interruptHandlerAdd(INTB_AUD3); + s_pCiaResource[CIA_A] = OpenResource((CONST_STRPTR)CIAANAME); s_pCiaResource[CIA_B] = OpenResource((CONST_STRPTR)CIABNAME); @@ -664,12 +821,11 @@ void systemCreate(void) { while (!(g_pCustom->intreqr & INTF_VERTB)) continue; g_pCustom->dmacon = 0x07FF; - // Unuse system so that it gets backed up once and then re-enable - // as little as needed - s_wSystemUses = 1; + // Disable system so that it gets backed up once, skip saving intena from systemUnuse() + s_wSystemUses = 0; s_wSystemBlitterUses = 1; - systemUnuse(); - systemUse(); + systemOsDisable(); + systemUse(); // Re-enable as little as needed systemGetBlitterFromOs(); } @@ -703,6 +859,11 @@ void systemDestroy(void) { inputHandlerRemove(); + interruptHandlerRemove(INTB_AUD0); + interruptHandlerRemove(INTB_AUD1); + interruptHandlerRemove(INTB_AUD2); + interruptHandlerRemove(INTB_AUD3); + // restore old view WaitTOF(); LoadView(s_pOsView); @@ -733,74 +894,10 @@ void systemUnuse(void) { systemFlushIo(); } - // Disable interrupts (this is the actual "kill system/OS" part) - g_pCustom->intena = 0x7FFF; - g_pCustom->intreq = 0x7FFF; - - // Query CIA ICR bits set by OS for later CIA takeover restore - s_pOsCiaIcr[CIA_A] = AbleICR(s_pCiaResource[CIA_A], 0); - s_pOsCiaIcr[CIA_B] = AbleICR(s_pCiaResource[CIA_B], 0); + // save the state of the hardware registers (INTENA) + s_uwOsIntEna = g_pCustom->intenar; - // Disable CIA interrupts - g_pCia[CIA_A]->icr = 0x7F; - g_pCia[CIA_B]->icr = 0x7F; - - // Save CRA bits - s_pOsCiaCra[CIA_A] = g_pCia[CIA_A]->cra; - s_pOsCiaCrb[CIA_A] = g_pCia[CIA_A]->crb; - s_pOsCiaCra[CIA_B] = g_pCia[CIA_B]->cra; - s_pOsCiaCrb[CIA_B] = g_pCia[CIA_B]->crb; - - // Disable timers and trigger reload of value to read preset val - g_pCia[CIA_A]->cra = CIACRA_LOAD; // CIACRA_START=0, timer is stopped - g_pCia[CIA_A]->crb = CIACRB_LOAD; - g_pCia[CIA_B]->cra = CIACRA_LOAD; // CIACRA_START=0, timer is stopped - g_pCia[CIA_B]->crb = CIACRB_LOAD; - - // Save OS CIA timer values - s_pOsCiaTimerA[CIA_A] = ciaGetTimerA(g_pCia[CIA_A]); - s_pOsCiaTimerB[CIA_A] = ciaGetTimerB(g_pCia[CIA_A]); - s_pOsCiaTimerA[CIA_B] = ciaGetTimerA(g_pCia[CIA_B]); - s_pOsCiaTimerB[CIA_B] = ciaGetTimerB(g_pCia[CIA_B]); - - // set ACE CIA timers - ciaSetTimerA(g_pCia[CIA_A], s_pAceCiaTimerA[CIA_A]); - ciaSetTimerB(g_pCia[CIA_A], s_pAceCiaTimerB[CIA_A]); - ciaSetTimerA(g_pCia[CIA_B], s_pAceCiaTimerA[CIA_B]); - ciaSetTimerB(g_pCia[CIA_B], s_pAceCiaTimerB[CIA_B]); - - // Enable ACE CIA interrupts - g_pCia[CIA_A]->icr = ( - CIAICRF_SETCLR | CIAICRF_SERIAL | CIAICRF_TIMER_A | CIAICRF_TIMER_B - ); - g_pCia[CIA_B]->icr = ( - CIAICRF_SETCLR | CIAICRF_SERIAL | CIAICRF_TIMER_A | CIAICRF_TIMER_B - ); - - // Restore ACE CIA CRA/CRB state - g_pCia[CIA_A]->cra = CIACRA_LOAD | s_pAceCiaCra[CIA_A]; - g_pCia[CIA_A]->crb = CIACRA_LOAD | s_pAceCiaCrb[CIA_A]; - g_pCia[CIA_B]->cra = CIACRA_LOAD | s_pAceCiaCra[CIA_B]; - g_pCia[CIA_B]->crb = CIACRA_LOAD | s_pAceCiaCrb[CIA_B]; - - // Game's bitplanes & copperlists are still used so don't disable them - // Wait for vbl before disabling sprite DMA - while (!(g_pCustom->intreqr & INTF_VERTB)) continue; - g_pCustom->dmacon = s_uwOsMinDma; - - // Save OS interrupt vectors and enable ACE's - g_pCustom->intreq = 0x7FFF; - for(UWORD i = 0; i < SYSTEM_INT_VECTOR_COUNT; ++i) { - s_pOsHwInterrupts[i] = s_pHwVectors[SYSTEM_INT_VECTOR_FIRST + i]; - s_pHwVectors[SYSTEM_INT_VECTOR_FIRST + i] = s_pAceHwInterrupts[i]; - } - - // Enable needed DMA (and interrupt) channels - g_pCustom->dmacon = DMAF_SETCLR | DMAF_MASTER | s_uwAceDmaCon; - // Everything that's supported by ACE to simplify things for now, - // but not audio channels since ptplayer relies on polling them, and I'm not - // currently being able to debug audio interrupt handler variant. - g_pCustom->intena = INTF_SETCLR | INTF_INTEN | s_uwAceIntEna; + systemOsDisable(); } #if defined(ACE_DEBUG) if(s_wSystemUses < 0) { @@ -902,9 +999,7 @@ void systemSetInt( UBYTE ubIntNumber, tAceIntHandler pHandler, void *pIntData ) { // Disable interrupt during data swap to not get stuck inside ACE's ISR - if(!s_wSystemUses) { - g_pCustom->intena = BV(ubIntNumber); - } + g_pCustom->intena = BV(ubIntNumber); // Disable handler or re-enable it if 0 was passed if(pHandler == 0) { @@ -915,9 +1010,7 @@ void systemSetInt( s_pAceInterrupts[ubIntNumber].pHandler = pHandler; s_pAceInterrupts[ubIntNumber].pData = pIntData; s_uwAceIntEna |= BV(ubIntNumber); - if(!s_wSystemUses) { - g_pCustom->intena = INTF_SETCLR | BV(ubIntNumber); - } + g_pCustom->intena = INTF_SETCLR | BV(ubIntNumber); } } From e21a7b2167ec9d6aeee99036349a8d74f12593f5 Mon Sep 17 00:00:00 2001 From: KaiN Date: Fri, 28 Jul 2023 18:49:29 +0200 Subject: [PATCH 08/33] tools: rename trimExt() to removeExt() --- tools/src/bitmap_conv.cpp | 8 ++++---- tools/src/common/fs.cpp | 2 +- tools/src/common/fs.h | 2 +- tools/src/common/palette.cpp | 2 +- tools/src/palette_conv.cpp | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/src/bitmap_conv.cpp b/tools/src/bitmap_conv.cpp index d104abad..587d335b 100644 --- a/tools/src/bitmap_conv.cpp +++ b/tools/src/bitmap_conv.cpp @@ -80,7 +80,7 @@ int main(int lArgCount, const char *pArgs[]) return EXIT_FAILURE; } if(szOutput.empty()) { - szOutput = nFs::trimExt(szInput); + szOutput = nFs::removeExt(szInput); if(szInExt == "png") { szOutput += ".bm"; } @@ -92,10 +92,10 @@ int main(int lArgCount, const char *pArgs[]) if(szMask == "" && isMaskColor) { if(szOutExt == "bm") { - szMask = nFs::trimExt(szOutput) + "_mask." + szOutExt; + szMask = nFs::removeExt(szOutput) + "_mask." + szOutExt; } else if(szInExt == "bm") { - szMask = nFs::trimExt(szInput) + "_mask." + szInExt; + szMask = nFs::removeExt(szInput) + "_mask." + szInExt; } } @@ -121,7 +121,7 @@ int main(int lArgCount, const char *pArgs[]) for(uint16_t i = 1; i < 256; ++i) { PaletteMask.m_vColors.push_back(MaskColor); } - auto szInMask = nFs::trimExt(szInput) + "_mask." + szInExt; + auto szInMask = nFs::removeExt(szInput) + "_mask." + szInExt; auto InMask = tChunkyBitmap(tPlanarBitmap::fromBm(szInMask), PaletteMask); if(!In.mergeWithMask(InMask)) { nLog::error("Mask incompatible with bitmap"); diff --git a/tools/src/common/fs.cpp b/tools/src/common/fs.cpp index 34fd6730..127a46a0 100644 --- a/tools/src/common/fs.cpp +++ b/tools/src/common/fs.cpp @@ -45,7 +45,7 @@ std::string getExt(const std::string &szPath) return szPath.substr(DotPos + 1); } -std::string trimExt(const std::string &szPath) +std::string removeExt(const std::string &szPath) { auto DotPos = szPath.find_last_of('.'); if(DotPos == std::string::npos) { diff --git a/tools/src/common/fs.h b/tools/src/common/fs.h index d0467e9e..8cc0086b 100644 --- a/tools/src/common/fs.h +++ b/tools/src/common/fs.h @@ -17,7 +17,7 @@ bool isDir(const std::string &szPath); std::string getExt(const std::string &szPath); -std::string trimExt(const std::string &szPath); +std::string removeExt(const std::string &szPath); std::string getBaseName(const std::string &szPath); diff --git a/tools/src/common/palette.cpp b/tools/src/common/palette.cpp index 9656a0cc..4929193e 100644 --- a/tools/src/common/palette.cpp +++ b/tools/src/common/palette.cpp @@ -196,7 +196,7 @@ bool tPalette::toGpl(const std::string &szPath) // Header Dest << "GIMP Palette\n"; - Dest << fmt::format("Name: {}\n", trimExt(getBaseName(szPath))); + Dest << fmt::format("Name: {}\n", removeExt(getBaseName(szPath))); Dest << "Columns: 4\n"; Dest << "#\n"; diff --git a/tools/src/palette_conv.cpp b/tools/src/palette_conv.cpp index b82fd352..3580f5c8 100644 --- a/tools/src/palette_conv.cpp +++ b/tools/src/palette_conv.cpp @@ -33,7 +33,7 @@ int main(int lArgCount, const char *pArgs[]) std::string szPathIn = pArgs[1]; // Optional args' default values - std::string szPathOut = nFs::trimExt(szPathIn) + ".gpl"; + std::string szPathOut = nFs::removeExt(szPathIn) + ".gpl"; // Search for optional args if(lArgCount - 1 > 1) { From f0b30ed383a5dde58cc221dcc8edcc3167fcb8d1 Mon Sep 17 00:00:00 2001 From: KaiN Date: Fri, 28 Jul 2023 18:50:06 +0200 Subject: [PATCH 09/33] audio_conv: add -fpt, -fpad and -sa options --- tools/src/audio_conv.cpp | 92 ++++++++++++++++++++++++++++++++++------ tools/src/common/sfx.cpp | 53 ++++++++++++++++------- tools/src/common/sfx.h | 20 ++++++++- 3 files changed, 135 insertions(+), 30 deletions(-) diff --git a/tools/src/audio_conv.cpp b/tools/src/audio_conv.cpp index 2150e9fd..1829be11 100644 --- a/tools/src/audio_conv.cpp +++ b/tools/src/audio_conv.cpp @@ -1,7 +1,9 @@ +#include #include "common/logging.h" #include "common/fs.h" #include "common/sfx.h" #include "common/wav.h" +#include "common/math.h" void printUsage(const std::string &szAppName) { using fmt::print; @@ -14,12 +16,17 @@ void printUsage(const std::string &szAppName) { print("\t-fd N Ensure that sound effect fits max amplitude divided by specified factor. Useful for some audio-mixing libraries\n"); print("\t-strict Treat warinings as errors (recommended)\n"); print("\t-n Normalize audio files\n"); + print("\t-fpt Enforce ptplayer-friendly mode: adds empty sample at the beginning, if missing\n"); + print("\t-fpad N Force given byte-padding\n"); + print("\t-sa N Split sample after every given number of bytes, or kbytes if value ends with k\n"); print("Default conversions:\n"); print("\t.wav -> .sfx\n"); print("\t.sfx -> .wav\n"); } int main(int lArgCount, const char *pArgs[]) { + using namespace std::string_view_literals; + uint8_t ubMandatoryArgCnt = 2; if(lArgCount < ubMandatoryArgCnt) { @@ -33,31 +40,55 @@ int main(int lArgCount, const char *pArgs[]) { uint8_t ubDivisor = 1; uint8_t ubFitDivisor = 1; std::string szInput(pArgs[1]); - std::string szOutput(""); + std::string szOutput; + bool isForcePt = false; + std::optional oForcePad; + std::optional oSplitAfter; for(auto ArgIndex = 2; ArgIndex < lArgCount; ++ArgIndex) { - if(pArgs[ArgIndex] == std::string("-o") && ArgIndex < lArgCount -1) { + std::string_view Arg = pArgs[ArgIndex]; + if(Arg == "-o"sv && ArgIndex < lArgCount -1) { szOutput = pArgs[++ArgIndex]; } - else if(pArgs[ArgIndex] == std::string("-d") && ArgIndex < lArgCount -1) { + else if(Arg == "-d"sv && ArgIndex < lArgCount -1) { ubDivisor = uint8_t(std::stoul(pArgs[++ArgIndex])); if(ubDivisor == 0) { nLog::error("Illegal -d value: '{}'", ubDivisor); return EXIT_FAILURE; } } - else if(pArgs[ArgIndex] == std::string("-fd") && ArgIndex < lArgCount -1) { + else if(Arg == "-fd"sv && ArgIndex < lArgCount -1) { ubFitDivisor = uint8_t(std::stoul(pArgs[++ArgIndex])); if(ubFitDivisor == 0) { nLog::error("Illegal -fd value: '{}'", ubFitDivisor); return EXIT_FAILURE; } } - else if(pArgs[ArgIndex] == std::string("-n")) { + else if(Arg == "-n"sv) { isNormalizing = true; } - else if(pArgs[ArgIndex] == std::string("-strict")) { + else if(Arg == "-strict"sv) { isStrict = true; } + else if(Arg == "-fpt"sv) { + isForcePt = true; + oForcePad = std::min(oForcePad.value_or(0), 2); + } + else if(Arg == "-fpad"sv && ArgIndex < lArgCount -1) { + oForcePad = uint8_t(std::stoul(pArgs[++ArgIndex])); + if(oForcePad.value() < 1 || oForcePad.value() < 4) { + nLog::error("Illegal -fpad value: '{}'", oForcePad.value()); + return EXIT_FAILURE; + } + } + else if(Arg == "-sa"sv && ArgIndex < lArgCount -1) { + std::string_view Value(pArgs[++ArgIndex]); + std::size_t CharsParsed = 0; + auto ValueEnd = Value.end(); + oSplitAfter = uint32_t(std::stoul(Value.data(), &CharsParsed)); + if(CharsParsed < Value.size() && Value[CharsParsed] == 'k') { + oSplitAfter = oSplitAfter.value() * 1024; + } + } else { nLog::error("Unknown arg or missing value: '{}'", pArgs[ArgIndex]); printUsage(pArgs[0]); @@ -74,7 +105,7 @@ int main(int lArgCount, const char *pArgs[]) { } if(szOutput.empty()) { - szOutput = nFs::trimExt(szInput); + szOutput = nFs::removeExt(szInput); if(szInExt == "wav") { szOutput += ".sfx"; } @@ -100,6 +131,12 @@ int main(int lArgCount, const char *pArgs[]) { return EXIT_FAILURE; } + // Ptplayer-like requirements + if(isForcePt) { + In.enforceEmptyFirstWord(); + } + + // Mixer-like requirements if(isNormalizing) { In.normalize(); } @@ -115,15 +152,44 @@ int main(int lArgCount, const char *pArgs[]) { ); } - // Save to output - fmt::print("Writing to {}...\n", szOutput); - if(szOutExt == "sfx") { - In.toSfx(szOutput); + if(oForcePad.has_value()) { + In.padContents(oForcePad.value()); + } + + if(oSplitAfter.has_value()) { + auto PartCount = (In.getLength() + oSplitAfter.value() - 1) / oSplitAfter.value(); + fmt::print("Splitting to {} parts, {} bytes each\n", PartCount, oSplitAfter.value()); + uint8_t ubPart = 0; + tSfx SfxRemaining; + auto BaseOutputPath = nFs::removeExt(szOutput); + do { + SfxRemaining = In.splitAfter(oSplitAfter.value()); + auto PartOutPath = fmt::format(FMT_STRING("{}_{}.{}"), BaseOutputPath, ubPart, szOutExt); + fmt::print("Writing to {}\n", PartOutPath); + if(szOutExt == "sfx") { + In.toSfx(PartOutPath); + } + else { + nLog::error("Output file type not supported: {}", szInExt); + return EXIT_FAILURE; + } + + In = SfxRemaining; + ++ubPart; + } while(!SfxRemaining.isEmpty()); } else { - nLog::error("Output file type not supported: {}", szInExt); - return EXIT_FAILURE; + // Save to output + fmt::print("Writing to {}...\n", szOutput); + if(szOutExt == "sfx") { + In.toSfx(szOutput); + } + else { + nLog::error("Output file type not supported: {}", szInExt); + return EXIT_FAILURE; + } } + fmt::print("All done!\n"); } diff --git a/tools/src/common/sfx.cpp b/tools/src/common/sfx.cpp index 72bae256..f1c0c2c9 100644 --- a/tools/src/common/sfx.cpp +++ b/tools/src/common/sfx.cpp @@ -8,12 +8,6 @@ #include "logging.h" #include "endian.h" -tSfx::tSfx(void): - m_ulFreq(0) -{ - -} - tSfx::tSfx(const tWav &Wav, bool isStrict): tSfx() { @@ -43,16 +37,6 @@ tSfx::tSfx(const tWav &Wav, bool isStrict): } } - // Ptplayer requires first sample word to be zero - if(m_vData[0] != 0) { - m_vData.push_back(0); - std::rotate(m_vData.rbegin(), m_vData.rbegin() + 1, m_vData.rend()); - } - if(m_vData[1] != 0) { - m_vData.push_back(0); - std::rotate(m_vData.rbegin(), m_vData.rbegin() + 1, m_vData.rend()); - } - // Needs even number of bytes - Amiga reads it as words if(m_vData.size() & 1) { m_vData.push_back(0); @@ -79,6 +63,11 @@ bool tSfx::isEmpty(void) const return m_vData.empty(); } +uint32_t tSfx::getLength(void) const +{ + return m_vData.size(); +} + void tSfx::normalize(void) { // Get the biggest amplitude - negative or positive @@ -112,3 +101,35 @@ bool tSfx::isFittingMaxAmplitude(int8_t bMaxAmplitude) const } return true; } + +bool tSfx::hasEmptyFirstWord(void) const { + return m_vData[0] == 0 && m_vData[1] == 0; +} + +void tSfx::enforceEmptyFirstWord(void) { + while(!hasEmptyFirstWord()) { + m_vData.push_back(0); + std::rotate(m_vData.rbegin(), m_vData.rbegin() + 1, m_vData.rend()); + } +} + +void tSfx::padContents(uint8_t ubAlignment) { + uint8_t ubAddCount = m_vData.size() % ubAlignment; + for(uint8_t i = ubAddCount; i--;) { + m_vData.push_back(0); + } +} + +tSfx tSfx::splitAfter(uint32_t ulSamples) { + tSfx Out; + if(m_vData.size() <= ulSamples) { + return Out; + } + + for(std::uint32_t ulPos = ulSamples; ulPos < m_vData.size(); ++ulPos) { + Out.m_vData.push_back(m_vData[ulPos]); + } + Out.m_ulFreq = m_ulFreq; + m_vData.resize(ulSamples); + return Out; +} diff --git a/tools/src/common/sfx.h b/tools/src/common/sfx.h index 4075e41a..789e4074 100644 --- a/tools/src/common/sfx.h +++ b/tools/src/common/sfx.h @@ -10,22 +10,40 @@ class tSfx { public: - tSfx(void); + constexpr tSfx(void); + tSfx(const tWav &Wav, bool isStrict); bool toSfx(const std::string &szPath) const; bool isEmpty(void) const; + uint32_t getLength(void) const; + void normalize(void); void divideAmplitude(uint8_t ubDivisor); bool isFittingMaxAmplitude(int8_t bMaxAmplitude) const; + bool hasEmptyFirstWord(void) const; + + void enforceEmptyFirstWord(void); + + void padContents(uint8_t ubAlignment); + + tSfx splitAfter(uint32_t ulSamples); + private: uint32_t m_ulFreq; std::vector m_vData; }; +//------------------------------------------------------------------------- IMPL + +constexpr tSfx::tSfx(void): + m_ulFreq(0) +{ +} + #endif // _ACE_TOOLS_COMMON_SFX_H_ From 90b5f23bf80a27dc287727ae8e9af4819def4cbb Mon Sep 17 00:00:00 2001 From: KaiN Date: Sun, 20 Aug 2023 12:53:16 +0200 Subject: [PATCH 10/33] add bobSetCurrentBuffer() --- include/ace/managers/bob.h | 10 ++++++++++ src/ace/managers/bob.c | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/include/ace/managers/bob.h b/include/ace/managers/bob.h index 23003338..7de9f097 100644 --- a/include/ace/managers/bob.h +++ b/include/ace/managers/bob.h @@ -228,4 +228,14 @@ void bobEnd(void); void bobDiscardUndraw(void); +/** + * @brief Sets the current buffer to given bitmap in case it loses sync. + * Usually used in tandem with bobDiscardUndraw() when bob system was disabled + * for some time. + * + * @param pCurrent Current buffer to use. Must be same as one of passed + * in bobManagerCreate(). + */ +void bobSetCurrentBuffer(tBitMap *pCurrent); + #endif // _ACE_MANAGERS_BOB_H_ diff --git a/src/ace/managers/bob.c b/src/ace/managers/bob.c index eebc182a..1f424fbc 100644 --- a/src/ace/managers/bob.c +++ b/src/ace/managers/bob.c @@ -456,3 +456,9 @@ void bobDiscardUndraw(void) { s_pQueues[0].ubUndrawCount = 0; s_pQueues[1].ubUndrawCount = 0; } + +void bobSetCurrentBuffer(tBitMap *pCurrent) { + if(s_pQueues[!s_ubBufferCurr].pDst == pCurrent) { + s_ubBufferCurr = !s_ubBufferCurr; + } +} From eb67b42a01cda60dc19a225ffd3cd2f89db75d4a Mon Sep 17 00:00:00 2001 From: KaiN Date: Sun, 24 Sep 2023 10:06:04 +0200 Subject: [PATCH 11/33] add os-friendly vblank handling --- src/ace/managers/system.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ace/managers/system.c b/src/ace/managers/system.c index 872755d6..92a879af 100644 --- a/src/ace/managers/system.c +++ b/src/ace/managers/system.c @@ -782,6 +782,7 @@ void systemCreate(void) { interruptHandlerAdd(INTB_AUD1); interruptHandlerAdd(INTB_AUD2); interruptHandlerAdd(INTB_AUD3); + interruptHandlerAdd(INTB_VERTB); s_pCiaResource[CIA_A] = OpenResource((CONST_STRPTR)CIAANAME); s_pCiaResource[CIA_B] = OpenResource((CONST_STRPTR)CIABNAME); @@ -864,6 +865,7 @@ void systemDestroy(void) { interruptHandlerRemove(INTB_AUD1); interruptHandlerRemove(INTB_AUD2); interruptHandlerRemove(INTB_AUD3); + interruptHandlerRemove(INTB_VERTB); // restore old view WaitTOF(); From de6a3c8f110688f582bfa87763de8ac194cb5cc7 Mon Sep 17 00:00:00 2001 From: KaiN Date: Sun, 24 Sep 2023 10:06:31 +0200 Subject: [PATCH 12/33] make file functions work without blitter, if possible allows animating stuff in vblank while loading files --- src/ace/utils/file.c | 107 ++++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 58 deletions(-) diff --git a/src/ace/utils/file.c b/src/ace/utils/file.c index c123b171..d3146f21 100644 --- a/src/ace/utils/file.c +++ b/src/ace/utils/file.c @@ -7,6 +7,26 @@ #include #include +// TODO: move to system to be able to use for dir functions? + +static void fileAccessEnable(void) { + systemUse(); + + // Needed only for KS1.3 + // TODO: do only when reading from floppy + if(systemGetVersion() < 36) { + systemReleaseBlitterToOs(); + } +} + +static void fileAccessDisable(void) { + if(systemGetVersion() < 36) { + systemGetBlitterFromOs(); + } + + systemUnuse(); +} + LONG fileGetSize(const char *szPath) { // One could use std library to seek to end of file and use ftell, // but SEEK_END is not guaranteed to work. @@ -15,15 +35,13 @@ LONG fileGetSize(const char *szPath) { // for doing Open() on same file after using it. // So I ultimately do it using fseek. - systemUse(); - systemReleaseBlitterToOs(); + fileAccessEnable(); logBlockBegin("fileGetSize(szPath: '%s')", szPath); FILE *pFile = fopen(szPath, "r"); if(!pFile) { logWrite("ERR: File doesn't exist"); logBlockEnd("fileGetSize()"); - systemGetBlitterFromOs(); - systemUnuse(); + fileAccessDisable(); return -1; } fseek(pFile, 0, SEEK_END); @@ -31,29 +49,24 @@ LONG fileGetSize(const char *szPath) { fclose(pFile); logBlockEnd("fileGetSize()"); - systemGetBlitterFromOs(); - systemUnuse(); + fileAccessDisable(); return lSize; } tFile *fileOpen(const char *szPath, const char *szMode) { // TODO check if disk is read protected when szMode has 'a'/'r'/'x' - systemUse(); - systemReleaseBlitterToOs(); + fileAccessEnable(); FILE *pFile = fopen(szPath, szMode); - systemGetBlitterFromOs(); - systemUnuse(); + fileAccessDisable(); return pFile; } void fileClose(tFile *pFile) { - systemUse(); - systemReleaseBlitterToOs(); + fileAccessEnable(); fclose(pFile); - systemGetBlitterFromOs(); - systemUnuse(); + fileAccessDisable(); } ULONG fileRead(tFile *pFile, void *pDest, ULONG ulSize) { @@ -62,64 +75,52 @@ ULONG fileRead(tFile *pFile, void *pDest, ULONG ulSize) { logWrite("ERR: File read size = 0!\n"); } #endif - systemUse(); - systemReleaseBlitterToOs(); + fileAccessEnable(); ULONG ulReadCount = fread(pDest, ulSize, 1, pFile); - systemGetBlitterFromOs(); - systemUnuse(); + fileAccessDisable(); return ulReadCount; } ULONG fileWrite(tFile *pFile, const void *pSrc, ULONG ulSize) { - systemUse(); - systemReleaseBlitterToOs(); + fileAccessEnable(); ULONG ulResult = fwrite(pSrc, ulSize, 1, pFile); fflush(pFile); - systemGetBlitterFromOs(); - systemUnuse(); + fileAccessDisable(); return ulResult; } ULONG fileSeek(tFile *pFile, ULONG ulPos, WORD wMode) { - systemUse(); - systemReleaseBlitterToOs(); + fileAccessEnable(); ULONG ulResult = fseek(pFile, ulPos, wMode); - systemGetBlitterFromOs(); - systemUnuse(); + fileAccessDisable(); return ulResult; } ULONG fileGetPos(tFile *pFile) { - systemUse(); - systemReleaseBlitterToOs(); + fileAccessEnable(); ULONG ulResult = ftell(pFile); - systemGetBlitterFromOs(); - systemUnuse(); + fileAccessDisable(); return ulResult; } UBYTE fileIsEof(tFile *pFile) { - systemUse(); - systemReleaseBlitterToOs(); + fileAccessEnable(); UBYTE ubResult = feof(pFile); - systemGetBlitterFromOs(); - systemUnuse(); + fileAccessDisable(); return ubResult; } #if !defined(BARTMAN_GCC) // Not implemented in mini_std for now, sorry! LONG fileVaPrintf(tFile *pFile, const char *szFmt, va_list vaArgs) { - systemUse(); - systemReleaseBlitterToOs(); + fileAccessEnable(); LONG lResult = vfprintf(pFile, szFmt, vaArgs); fflush(pFile); - systemGetBlitterFromOs(); - systemUnuse(); + fileAccessDisable(); return lResult; } @@ -132,11 +133,9 @@ LONG filePrintf(tFile *pFile, const char *szFmt, ...) { } LONG fileVaScanf(tFile *pFile, const char *szFmt, va_list vaArgs) { - systemUse(); - systemReleaseBlitterToOs(); + fileAccessEnable(); LONG lResult = vfscanf(pFile, szFmt, vaArgs); - systemGetBlitterFromOs(); - systemUnuse(); + fileAccessDisable(); return lResult; } @@ -150,11 +149,9 @@ LONG fileScanf(tFile *pFile, const char *szFmt, ...) { #endif void fileFlush(tFile *pFile) { - systemUse(); - systemReleaseBlitterToOs(); + fileAccessEnable(); fflush(pFile); - systemGetBlitterFromOs(); - systemUnuse(); + fileAccessDisable(); } void fileWriteStr(tFile *pFile, const char *szLine) { @@ -162,34 +159,28 @@ void fileWriteStr(tFile *pFile, const char *szLine) { } UBYTE fileExists(const char *szPath) { - systemUse(); - systemReleaseBlitterToOs(); + fileAccessEnable(); UBYTE isExisting = 0; tFile *pFile = fileOpen(szPath, "r"); if(pFile) { isExisting = 1; fileClose(pFile); } - systemGetBlitterFromOs(); - systemUnuse(); + fileAccessDisable(); return isExisting; } UBYTE fileDelete(const char *szFilePath) { - systemUse(); - systemReleaseBlitterToOs(); + fileAccessEnable(); UBYTE isSuccess = remove(szFilePath); - systemGetBlitterFromOs(); - systemUnuse(); + fileAccessDisable(); return isSuccess; } UBYTE fileMove(const char *szSource, const char *szDest) { - systemUse(); - systemReleaseBlitterToOs(); + fileAccessEnable(); UBYTE isSuccess = rename(szSource, szDest); - systemGetBlitterFromOs(); - systemUnuse(); + fileAccessDisable(); return isSuccess; } From 43d3cc6285608321b5dc7eece2d95a27ff80b419 Mon Sep 17 00:00:00 2001 From: KaiN Date: Tue, 26 Sep 2023 17:08:17 +0200 Subject: [PATCH 13/33] tilebuffer: add missing cbTileDraw call in tileBufferRedrawAll() --- src/ace/managers/viewport/tilebuffer.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/ace/managers/viewport/tilebuffer.c b/src/ace/managers/viewport/tilebuffer.c index 97d82de3..f6dac620 100644 --- a/src/ace/managers/viewport/tilebuffer.c +++ b/src/ace/managers/viewport/tilebuffer.c @@ -624,6 +624,24 @@ void tileBufferRedrawAll(tTileBufferManager *pManager) { } uwTileOffsY = (uwTileOffsY + ubTileSize) & (pManager->uwMarginedHeight - 1); } + + if (pManager->cbTileDraw) { + uwTileOffsY = (wStartY << ubTileShift) & (pManager->uwMarginedHeight - 1); + for (UWORD uwTileY = wStartY; uwTileY < uwEndY; ++uwTileY) { + uwTileOffsX = (wStartX << ubTileShift); + UWORD uwTileCurr = wStartX; + while (uwTileCurr < uwEndX) { + pManager->cbTileDraw( + uwTileCurr, uwTileY, pManager->pScroll->pBack, + uwTileOffsX, uwTileOffsY + ); + ++uwTileCurr; + uwTileOffsX += ubTileSize; + } + uwTileOffsY = (uwTileOffsY + ubTileSize) & (pManager->uwMarginedHeight - 1); + } + } + systemSetDmaBit(DMAB_BLITHOG, 0); // Copy from back buffer to front buffer. From ee3316f8fc176b7af0445d7d75bdf9daa95a5ccf Mon Sep 17 00:00:00 2001 From: KaiN Date: Thu, 28 Sep 2023 16:26:38 +0200 Subject: [PATCH 14/33] optimize blitter waiting a bit --- include/ace/managers/blit.h | 4 +++- src/ace/managers/blit.c | 20 ++++++++------------ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/include/ace/managers/blit.h b/include/ace/managers/blit.h index a9365c52..28a3305f 100644 --- a/include/ace/managers/blit.h +++ b/include/ace/managers/blit.h @@ -67,7 +67,7 @@ void blitManagerDestroy(void); /** * @brief Checks if blitter is idle. * - * Polls 2 times, taing A1000 Agnus bug workaround into account. + * Polls 2 times, taking A1000 Agnus bug workaround into account. * * @return 1 if blitter is idle, otherwise 0. * @@ -78,6 +78,8 @@ UBYTE blitIsIdle(void); /** * @brief Waits until blitter finishes its work. * + * Polls at least 2 times, taking A1000 Agnus bug workaround into account. + * * @todo Investigate if autosetting BLITHOG inside it is beneficial. * * @see blitIsIdle() diff --git a/src/ace/managers/blit.c b/src/ace/managers/blit.c index ca7431bb..e1861051 100644 --- a/src/ace/managers/blit.c +++ b/src/ace/managers/blit.c @@ -102,24 +102,20 @@ UBYTE _blitCheck( #endif // defined(ACE_DEBUG) void blitWait(void) { - while(!blitIsIdle()) continue; + // A1000 Blitter done bug: + // The solution is to read hardware register before testing the bit. + (void)g_pCustom->dmaconr; + while(!(g_pCustom->dmaconr & DMAF_BLTDONE)) continue; } -/** - * Checks if blitter is idle - * Polls 2 times - A1000 Agnus bug workaround - */ UBYTE blitIsIdle(void) { - #ifdef AMIGA + // A1000 Blitter done bug: + // The solution is to read hardware register before testing the bit. + (void)g_pCustom->dmaconr; if(!(g_pCustom->dmaconr & DMAF_BLTDONE)) { - if(!(g_pCustom->dmaconr & DMAF_BLTDONE)) { - return 1; - } + return 1; } return 0; - #else - return 1; - #endif // AMIGA } UBYTE blitUnsafeCopy( From 2e143b01ea5a0a9786478abd829c485cc3ccc470 Mon Sep 17 00:00:00 2001 From: KaiN Date: Thu, 28 Sep 2023 21:25:05 +0200 Subject: [PATCH 15/33] fix DMAF_BLTDONE check polarity --- src/ace/managers/blit.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ace/managers/blit.c b/src/ace/managers/blit.c index e1861051..e2519f24 100644 --- a/src/ace/managers/blit.c +++ b/src/ace/managers/blit.c @@ -105,17 +105,17 @@ void blitWait(void) { // A1000 Blitter done bug: // The solution is to read hardware register before testing the bit. (void)g_pCustom->dmaconr; - while(!(g_pCustom->dmaconr & DMAF_BLTDONE)) continue; + while(g_pCustom->dmaconr & DMAF_BLTDONE) continue; } UBYTE blitIsIdle(void) { // A1000 Blitter done bug: // The solution is to read hardware register before testing the bit. (void)g_pCustom->dmaconr; - if(!(g_pCustom->dmaconr & DMAF_BLTDONE)) { - return 1; + if(g_pCustom->dmaconr & DMAF_BLTDONE) { + return 0; } - return 0; + return 1; } UBYTE blitUnsafeCopy( From 2ca091cda8e23060621b4cc2b0156ec76c190f6a Mon Sep 17 00:00:00 2001 From: KaiN Date: Sun, 1 Oct 2023 23:18:00 +0200 Subject: [PATCH 16/33] add null check in bitmapLoadFromFile() --- src/ace/utils/bitmap.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ace/utils/bitmap.c b/src/ace/utils/bitmap.c index 85b35a26..2b93b7dc 100644 --- a/src/ace/utils/bitmap.c +++ b/src/ace/utils/bitmap.c @@ -131,6 +131,13 @@ void bitmapLoadFromFile( "bitmapLoadFromFile(pBitMap: %p, szFilePath: '%s', uwStartX: %u, uwStartY: %u)", pBitMap, szFilePath, uwStartX, uwStartY ); + + if(!pBitMap) { + logWrite("ERR: pBitMap is 0\n"); + systemUnuse(); + return; + } + // Open source bitmap tFile *pFile = fileOpen(szFilePath, "r"); if(!pFile) { From 11d864f0841d3b73c1411e2e5444255bc6e17868 Mon Sep 17 00:00:00 2001 From: KaiN Date: Mon, 9 Oct 2023 16:11:26 +0200 Subject: [PATCH 17/33] add checks for tile redraw queue overflow those kinds of checks desperately need assert() --- src/ace/managers/viewport/tilebuffer.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ace/managers/viewport/tilebuffer.c b/src/ace/managers/viewport/tilebuffer.c index f6dac620..886ecfdb 100644 --- a/src/ace/managers/viewport/tilebuffer.c +++ b/src/ace/managers/viewport/tilebuffer.c @@ -48,11 +48,17 @@ static void tileBufferQueueAdd( } #endif tRedrawState *pState = &pManager->pRedrawStates[0]; + if(pState->ubPendingCount >= pManager->ubQueueSize) { + logWrite("ERR: Pending tiles queue overflow!"); + } pState->pPendingQueue[pState->ubPendingCount].uwX = uwTileX; pState->pPendingQueue[pState->ubPendingCount].uwY = uwTileY; ++pState->ubPendingCount; pState = &pManager->pRedrawStates[1]; + if(pState->ubPendingCount >= pManager->ubQueueSize) { + logWrite("ERR: Pending tiles queue overflow!"); + } pState->pPendingQueue[pState->ubPendingCount].uwX = uwTileX; pState->pPendingQueue[pState->ubPendingCount].uwY = uwTileY; ++pState->ubPendingCount; From c0b79fc2e512ee9100a2ab43f37f42b4efcf2eee Mon Sep 17 00:00:00 2001 From: KaiN Date: Sat, 14 Oct 2023 17:58:01 +0200 Subject: [PATCH 18/33] add ptplayerSetE8Callback() --- include/ace/managers/ptplayer.h | 9 +++++++++ src/ace/managers/ptplayer.c | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/include/ace/managers/ptplayer.h b/include/ace/managers/ptplayer.h index 649140a6..f1f69db0 100644 --- a/include/ace/managers/ptplayer.h +++ b/include/ace/managers/ptplayer.h @@ -64,6 +64,7 @@ typedef struct tPtplayerSamplePack { } tPtplayerSamplePack; typedef void (*tPtplayerCbSongEnd)(void); +typedef void (*tPtplayerCbE8)(UBYTE ubE8); /** * @brief Install a CIA-B interrupt for calling _mt_music or mt_sfxonly. @@ -309,6 +310,14 @@ tPtplayerSamplePack *ptplayerSampleDataCreate(const char *szPath); */ void ptplayerSamplePackDestroy(tPtplayerSamplePack *pSamplePack); +/** + * @brief Sets the function to call on parsing the E8 command. + * + * @param cbOnE8 Function to be called. E8 argument nibble is passed + * as argument. Set to zero if not needed. + */ +void ptplayerSetE8Callback(tPtplayerCbE8 cbOnE8); + #ifdef __cplusplus } #endif diff --git a/src/ace/managers/ptplayer.c b/src/ace/managers/ptplayer.c index 5f17bab1..77e986fc 100644 --- a/src/ace/managers/ptplayer.c +++ b/src/ace/managers/ptplayer.c @@ -933,6 +933,7 @@ static volatile UBYTE s_isPendingPlay, s_isPendingSetRep, s_isPendingDmaOn; #endif static UBYTE s_isRepeat; static tPtplayerCbSongEnd s_cbSongEnd; +static tPtplayerCbE8 s_cbOnE8; static UBYTE s_isPal; #if defined(PTPLAYER_USE_AUDIO_INT_HANDLERS) @@ -1760,6 +1761,7 @@ void ptplayerDestroy(void) { void ptplayerCreate(UBYTE isPal) { s_isRepeat = 1; s_cbSongEnd = 0; + s_cbOnE8 = 0; s_pModCurr = 0; ptplayerEnableMusic(0); #if defined(PTPLAYER_USE_AUDIO_INT_HANDLERS) @@ -2456,6 +2458,9 @@ static void mt_e8( ) { // cmd 0x0E'8X (x = trigger value) mt_E8Trigger = ubArg; + if(s_cbOnE8) { + s_cbOnE8(ubArg); + } } static void ptDoRetrigger( @@ -3222,3 +3227,7 @@ void ptplayerSamplePackDestroy(tPtplayerSamplePack *pSamplePack) { memFree(pSamplePack, sizeof(*pSamplePack)); logBlockEnd("ptplayerSamplePackDestroy()"); } + +void ptplayerSetE8Callback(tPtplayerCbE8 cbOnE8) { + s_cbOnE8 = cbOnE8; +} From 6209f4af1712cfab9b15c7b460e60ca637feb259 Mon Sep 17 00:00:00 2001 From: KaiN Date: Tue, 16 Jan 2024 18:18:48 +0100 Subject: [PATCH 19/33] add paletteColorMix() --- include/ace/utils/palette.h | 14 ++++++++++++++ src/ace/utils/palette.c | 23 +++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/include/ace/utils/palette.h b/include/ace/utils/palette.h index b069f192..1e6059b9 100644 --- a/include/ace/utils/palette.h +++ b/include/ace/utils/palette.h @@ -50,9 +50,23 @@ void paletteDim( * @brief Dims a single input color to given brightness level. * @param uwFullColor Full color used as a base to calculate percentage. * @param ubLevel Brightness level - 15 for no dim, 0 for total blackness. + * + * @see paletteColorMix() */ UWORD paletteColorDim(UWORD uwFullColor, UBYTE ubLevel); +/** + * @brief Interpolates two colors at given level. + * @param uwColorPrimary Primary color in the mix. + * @param uwColorSecondary Secondary color in the mix. + * @param ubLevel Mix ratio - 15 results in primary color, 0 in secondary. + * @return Mixed color between uwColorPrimary and uwColorSecondary. + * + * @note This function is slower than paletteColorDim(). + * @see paletteColorDim() + */ +UWORD paletteColorMix(UWORD uwColorPrimary, UWORD uwColorSecondary, UBYTE ubLevel); + /** * @brief Writes given palette to debug .bmp file. * diff --git a/src/ace/utils/palette.c b/src/ace/utils/palette.c index 9ca500c7..db3b5d8d 100644 --- a/src/ace/utils/palette.c +++ b/src/ace/utils/palette.c @@ -6,6 +6,7 @@ #include #include #include +#include void paletteLoad(const char *szFileName, UWORD *pPalette, UBYTE ubMaxLength) { tFile *pFile; @@ -68,6 +69,28 @@ UWORD paletteColorDim(UWORD uwFullColor, UBYTE ubLevel) { return (r << 8) | (g << 4) | b; } +UWORD paletteColorMix( + UWORD uwColorPrimary, UWORD uwColorSecondary, UBYTE ubLevel +) { + UBYTE r1,g1,b1; + UBYTE r2,g2,b2; + + r1 = (uwColorPrimary >> 8) & 0xF; + g1 = (uwColorPrimary >> 4) & 0xF; + b1 = (uwColorPrimary) & 0xF; + r2 = (uwColorSecondary >> 8) & 0xF; + g2 = (uwColorSecondary >> 4) & 0xF; + b2 = (uwColorSecondary) & 0xF; + + // Dim color + r1 = ((r1 * ubLevel + (r2 * (0xF - ubLevel)))/15) & 0xF; + g1 = ((g1 * ubLevel + (g2 * (0xF - ubLevel)))/15) & 0xF; + b1 = ((b1 * ubLevel + (b2 * (0xF - ubLevel)))/15) & 0xF; + + // Output + return (r1 << 8) | (g1 << 4) | b1; +} + void paletteDump(UWORD *pPalette, UBYTE ubColorCnt, char *szPath) { UBYTE ubLastColor = ubColorCnt - 1; UBYTE ubBpp = 0; From c14598bf1de6c622ecaf3e277141c1eca1ea3cde Mon Sep 17 00:00:00 2001 From: KaiN Date: Sun, 4 Feb 2024 12:40:15 +0100 Subject: [PATCH 20/33] optimize bitmapLoadFromFile offset calcs --- src/ace/utils/bitmap.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/ace/utils/bitmap.c b/src/ace/utils/bitmap.c index 28b16291..465af20e 100644 --- a/src/ace/utils/bitmap.c +++ b/src/ace/utils/bitmap.c @@ -204,25 +204,30 @@ void bitmapLoadFromFile( // Read data uwWidth = bitmapGetByteWidth(pBitMap); + UWORD uwReadBytesPerRow = (uwSrcWidth + 7) / 8; if(bitmapIsInterleaved(pBitMap)) { - for(y = 0; y != uwSrcHeight; ++y) { + UWORD uwDestOffs = uwWidth * (uwStartY * pBitMap->Depth) + (uwStartX / 8); + for(y = 0; y < uwSrcHeight; ++y) { for(ubPlane = 0; ubPlane != pBitMap->Depth; ++ubPlane) { fileRead( pFile, - &pBitMap->Planes[0][uwWidth*(((uwStartY + y)*pBitMap->Depth)+ubPlane)+(uwStartX>>3)], - ((uwSrcWidth+7)>>3) + &pBitMap->Planes[0][uwDestOffs], + uwReadBytesPerRow ); + uwDestOffs += uwWidth; } } } else { for(ubPlane = 0; ubPlane != pBitMap->Depth; ++ubPlane) { for(y = 0; y != uwSrcHeight; ++y) { + UWORD uwDestOffs = uwWidth * uwStartY + (uwStartX / 8); fileRead( pFile, - &pBitMap->Planes[ubPlane][uwWidth*(uwStartY+y) + (uwStartX>>3)], - ((uwSrcWidth+7)>>3) + &pBitMap->Planes[ubPlane][uwDestOffs], + uwReadBytesPerRow ); + uwDestOffs += uwWidth; } } } From 1448fe02425446fe7df45eeee630b28b7c563b6f Mon Sep 17 00:00:00 2001 From: KaiN Date: Sun, 4 Feb 2024 12:51:25 +0100 Subject: [PATCH 21/33] optimize bitmapLoadFromFile() for full width interleaved reads makes significant difference for streamed assets scenario --- src/ace/utils/bitmap.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/ace/utils/bitmap.c b/src/ace/utils/bitmap.c index 465af20e..3b8b66c4 100644 --- a/src/ace/utils/bitmap.c +++ b/src/ace/utils/bitmap.c @@ -207,14 +207,23 @@ void bitmapLoadFromFile( UWORD uwReadBytesPerRow = (uwSrcWidth + 7) / 8; if(bitmapIsInterleaved(pBitMap)) { UWORD uwDestOffs = uwWidth * (uwStartY * pBitMap->Depth) + (uwStartX / 8); - for(y = 0; y < uwSrcHeight; ++y) { - for(ubPlane = 0; ubPlane != pBitMap->Depth; ++ubPlane) { - fileRead( - pFile, - &pBitMap->Planes[0][uwDestOffs], - uwReadBytesPerRow - ); - uwDestOffs += uwWidth; + if(uwStartX == 0 && uwSrcWidth == uwDstWidth) { + fileRead( + pFile, + &pBitMap->Planes[0][uwDestOffs], + pBitMap->BytesPerRow * uwSrcHeight + ); + } + else { + for(y = 0; y < uwSrcHeight; ++y) { + for(ubPlane = 0; ubPlane != pBitMap->Depth; ++ubPlane) { + fileRead( + pFile, + &pBitMap->Planes[0][uwDestOffs], + uwReadBytesPerRow + ); + uwDestOffs += uwWidth; + } } } } From 9b0d7c41df0cf1e3f28b9b4a62e2597aa30b8a70 Mon Sep 17 00:00:00 2001 From: KaiN Date: Sat, 10 Feb 2024 16:56:28 +0100 Subject: [PATCH 22/33] tools: use std namespace for cstdint types --- tools/src/audio_conv.cpp | 10 ++-- tools/src/bitmap_conv.cpp | 4 +- tools/src/bitmap_transform.cpp | 6 +- tools/src/common/bitmap.cpp | 104 ++++++++++++++++----------------- tools/src/common/bitmap.h | 26 ++++----- tools/src/common/endian.h | 8 +-- tools/src/common/glyph_set.cpp | 100 +++++++++++++++---------------- tools/src/common/glyph_set.h | 14 ++--- tools/src/common/math.h | 2 +- tools/src/common/mod.cpp | 44 +++++++------- tools/src/common/mod.h | 21 +++---- tools/src/common/palette.cpp | 44 +++++++------- tools/src/common/palette.h | 4 +- tools/src/common/parse.h | 2 +- tools/src/common/rgb.h | 6 +- tools/src/common/sfx.cpp | 30 +++++----- tools/src/common/sfx.h | 12 ++-- tools/src/common/wav.cpp | 14 ++--- tools/src/common/wav.h | 10 ++-- tools/src/font_conv.cpp | 14 ++--- tools/src/mod_tool.cpp | 4 +- tools/src/palette_conv.cpp | 4 +- tools/src/tileset_conv.cpp | 28 ++++----- 23 files changed, 256 insertions(+), 255 deletions(-) diff --git a/tools/src/audio_conv.cpp b/tools/src/audio_conv.cpp index 718b9015..5242d76d 100644 --- a/tools/src/audio_conv.cpp +++ b/tools/src/audio_conv.cpp @@ -27,7 +27,7 @@ void printUsage(const std::string &szAppName) { int main(int lArgCount, const char *pArgs[]) { using namespace std::string_view_literals; - uint8_t ubMandatoryArgCnt = 2; + std::uint8_t ubMandatoryArgCnt = 2; if(lArgCount < ubMandatoryArgCnt) { nLog::error("Too few arguments, expected {}", ubMandatoryArgCnt); @@ -37,8 +37,8 @@ int main(int lArgCount, const char *pArgs[]) { bool isStrict = false; bool isNormalizing = false; - uint8_t ubDivisor = 1; - uint8_t ubFitDivisor = 1; + std::uint8_t ubDivisor = 1; + std::uint8_t ubFitDivisor = 1; std::string szInput(pArgs[1]); std::string szOutput; bool isForcePt = false; @@ -144,7 +144,7 @@ int main(int lArgCount, const char *pArgs[]) { In.divideAmplitude(ubDivisor); } - int8_t bMaxAmplitude = std::numeric_limits::max() / ubFitDivisor; + std::int8_t bMaxAmplitude = std::numeric_limits::max() / ubFitDivisor; if(!In.isFittingMaxAmplitude(bMaxAmplitude)) { nLog::error( "Sound effect doesn't fit the amplitude divisor {}, max amplitude: {}", @@ -159,7 +159,7 @@ int main(int lArgCount, const char *pArgs[]) { if(oSplitAfter.has_value()) { auto PartCount = (In.getLength() + oSplitAfter.value() - 1) / oSplitAfter.value(); fmt::print("Splitting to {} parts, {} bytes each\n", PartCount, oSplitAfter.value()); - uint8_t ubPart = 0; + std::uint8_t ubPart = 0; tSfx SfxRemaining; auto BaseOutputPath = nFs::removeExt(szOutput); do { diff --git a/tools/src/bitmap_conv.cpp b/tools/src/bitmap_conv.cpp index 386242de..470813b9 100644 --- a/tools/src/bitmap_conv.cpp +++ b/tools/src/bitmap_conv.cpp @@ -28,7 +28,7 @@ void printUsage(const std::string &szAppName) int main(int lArgCount, const char *pArgs[]) { - const uint8_t ubMandatoryArgCnt = 2; + const std::uint8_t ubMandatoryArgCnt = 2; if(lArgCount - 1 < ubMandatoryArgCnt) { nLog::error("Too few arguments, expected {}", ubMandatoryArgCnt); printUsage(pArgs[0]); @@ -118,7 +118,7 @@ int main(int lArgCount, const char *pArgs[]) if(isMaskColor) { tPalette PaletteMask; PaletteMask.m_vColors.push_back(tRgb(0,0,0)); - for(uint16_t i = 1; i < 256; ++i) { + for(std::uint16_t i = 1; i < 256; ++i) { PaletteMask.m_vColors.push_back(MaskColor); } auto szInMask = nFs::removeExt(szInput) + "_mask." + szInExt; diff --git a/tools/src/bitmap_transform.cpp b/tools/src/bitmap_transform.cpp index 941510ad..3ee148f4 100644 --- a/tools/src/bitmap_transform.cpp +++ b/tools/src/bitmap_transform.cpp @@ -14,11 +14,11 @@ class tOp { class tOpExtract: public tOp { public: - tOpExtract(uint16_t uwX, uint16_t uwY, uint16_t uwW, uint16_t uwH); + tOpExtract(std::uint16_t uwX, std::uint16_t uwY, std::uint16_t uwW, std::uint16_t uwH); virtual tChunkyBitmap execute(const tChunkyBitmap &Src); virtual std::string toString(void); private: - uint16_t m_uwX, m_uwY, m_uwW, m_uwH; + std::uint16_t m_uwX, m_uwY, m_uwW, m_uwH; }; class tOpRotate: public tOp { @@ -160,7 +160,7 @@ int main(int lArgCount, char *pArgs[]) //--------------------------------------------------------------------OP EXTRACT -tOpExtract::tOpExtract(uint16_t uwX, uint16_t uwY, uint16_t uwW, uint16_t uwH): +tOpExtract::tOpExtract(std::uint16_t uwX, std::uint16_t uwY, std::uint16_t uwW, std::uint16_t uwH): m_uwX(uwX), m_uwY(uwY), m_uwW(uwW), m_uwH(uwH) { // Nothing here for now diff --git a/tools/src/common/bitmap.cpp b/tools/src/common/bitmap.cpp index b33a7523..354072a5 100644 --- a/tools/src/common/bitmap.cpp +++ b/tools/src/common/bitmap.cpp @@ -10,7 +10,7 @@ #include "../common/endian.h" #include "../common/flags/flags.hpp" -enum class tBmFlags: uint8_t { +enum class tBmFlags: std::uint8_t { NONE = 0, INTERLEAVED = 1 }; @@ -28,11 +28,11 @@ tChunkyBitmap::tChunkyBitmap( } m_vData.resize(m_uwWidth * m_uwHeight, Palette.m_vColors[0]); auto PxPerCell = sizeof(Planar.m_pPlanes[0][0]) * 8; - for(uint32_t ulY = 0; ulY < m_uwHeight; ++ulY) { - for(uint32_t ulX = 0; ulX < m_uwWidth; ++ulX) { - uint8_t ubColorIdx = 0; - uint32_t ulOffs = (ulY * m_uwWidth + ulX) / PxPerCell; - for(uint8_t ubPlane = Planar.m_ubDepth; ubPlane--;) { + for(std::uint32_t ulY = 0; ulY < m_uwHeight; ++ulY) { + for(std::uint32_t ulX = 0; ulX < m_uwWidth; ++ulX) { + std::uint8_t ubColorIdx = 0; + std::uint32_t ulOffs = (ulY * m_uwWidth + ulX) / PxPerCell; + for(std::uint8_t ubPlane = Planar.m_ubDepth; ubPlane--;) { auto &Plane = Planar.m_pPlanes[ubPlane]; ubColorIdx <<= 1; ubColorIdx |= (Plane.at(ulOffs) >> (15 - (ulX & 15))) & 1; @@ -52,14 +52,14 @@ tChunkyBitmap::tChunkyBitmap( } } -tChunkyBitmap::tChunkyBitmap(uint16_t uwWidth, uint16_t uwHeight, tRgb Bg): +tChunkyBitmap::tChunkyBitmap(std::uint16_t uwWidth, std::uint16_t uwHeight, tRgb Bg): m_uwWidth(uwWidth), m_uwHeight(uwHeight), m_vData(m_uwWidth * m_uwHeight, Bg) { } tChunkyBitmap::tChunkyBitmap( - uint16_t uwWidth, uint16_t uwHeight, const uint8_t *pData + std::uint16_t uwWidth, std::uint16_t uwHeight, const std::uint8_t *pData ): m_uwWidth(uwWidth), m_uwHeight(uwHeight) { @@ -71,7 +71,7 @@ tChunkyBitmap::tChunkyBitmap( tChunkyBitmap tChunkyBitmap::fromPng(const std::string &szPath) { unsigned uWidth, uHeight; - uint8_t *pData; + std::uint8_t *pData; auto LodeError = lodepng_decode24_file(&pData, &uWidth, &uHeight, szPath.c_str()); if(LodeError) { return tChunkyBitmap(); @@ -93,7 +93,7 @@ bool tChunkyBitmap::toPng(const std::string &szPngPath) const } tPlanarBitmap::tPlanarBitmap( - uint16_t uwWidth, uint16_t uwHeight, uint8_t ubDepth + std::uint16_t uwWidth, std::uint16_t uwHeight, std::uint8_t ubDepth ) { if(uwWidth & 0xF) { @@ -109,7 +109,7 @@ tPlanarBitmap::tPlanarBitmap( m_uwHeight = uwHeight; m_ubDepth = ubDepth; - for(uint8_t i = 0; i < ubDepth; ++i) { + for(std::uint8_t i = 0; i < ubDepth; ++i) { m_pPlanes[i].resize(uwWidth * uwHeight / sizeof(m_pPlanes[0][0])); } } @@ -128,23 +128,23 @@ tPlanarBitmap::tPlanarBitmap( } // Determine depth - uint8_t ubDepth = Palette.getBpp(); + std::uint8_t ubDepth = Palette.getBpp(); if(ubDepth > 8) { nLog::error("More than 8bpp not supported, got {}", ubDepth); return; } // Write bitplanes - from LSB to MSB - uint16_t uwPixelBuffer; - uint32_t ulPos; - for(uint8_t ubPlane = 0; ubPlane != ubDepth; ++ubPlane) { - for(uint16_t y = 0; y != Chunky.m_uwHeight; ++y) { + std::uint16_t uwPixelBuffer; + std::uint32_t ulPos; + for(std::uint8_t ubPlane = 0; ubPlane != ubDepth; ++ubPlane) { + for(std::uint16_t y = 0; y != Chunky.m_uwHeight; ++y) { uwPixelBuffer = 0; - for(uint16_t x = 0; x != Chunky.m_uwWidth; ++x) { + for(std::uint16_t x = 0; x != Chunky.m_uwWidth; ++x) { // Determine bit value for given color at specified bitplane's pos auto Color = Chunky.pixelAt(x, y); - int16_t wIdx = Palette.getColorIdx(Color); - uint8_t ubBit = 0; + std::int16_t wIdx = Palette.getColorIdx(Color); + std::uint8_t ubBit = 0; if(wIdx == -1) { if(PaletteIgnore.getColorIdx(Color) == -1) { nLog::error( @@ -186,25 +186,25 @@ bool tPlanarBitmap::toBm(const std::string &szPath, bool isInterleaved) } // Write .bm header - uint16_t uwOut = nEndian::toBig16(m_uwWidth); + std::uint16_t uwOut = nEndian::toBig16(m_uwWidth); OutFile.write(reinterpret_cast(&uwOut), 2); uwOut = nEndian::toBig16(m_uwHeight); OutFile.write(reinterpret_cast(&uwOut), 2); OutFile.write(reinterpret_cast(&m_ubDepth), 1); - uint8_t ubOut = 0; + std::uint8_t ubOut = 0; OutFile.write(reinterpret_cast(&ubOut), 1); // Version OutFile.write(reinterpret_cast(&eFlags), 1); // Flags OutFile.write(reinterpret_cast(&ubOut), 1); // Reserved 1 OutFile.write(reinterpret_cast(&ubOut), 1); // Reserved 2 // Write bitplanes - uint16_t uwRowWordCount = m_uwWidth / 16; + std::uint16_t uwRowWordCount = m_uwWidth / 16; if(isInterleaved) { - for(uint16_t y = 0; y < m_uwHeight; ++y) { - for(uint8_t ubPlane = 0; ubPlane < m_ubDepth; ++ubPlane) { - for(uint16_t x = 0; x < uwRowWordCount; ++x) { - uint16_t uwData = nEndian::toBig16( + for(std::uint16_t y = 0; y < m_uwHeight; ++y) { + for(std::uint8_t ubPlane = 0; ubPlane < m_ubDepth; ++ubPlane) { + for(std::uint16_t x = 0; x < uwRowWordCount; ++x) { + std::uint16_t uwData = nEndian::toBig16( m_pPlanes[ubPlane].at(y * uwRowWordCount + x) ); OutFile.write(reinterpret_cast(&uwData), sizeof(uint16_t)); @@ -213,10 +213,10 @@ bool tPlanarBitmap::toBm(const std::string &szPath, bool isInterleaved) } } else { - for(uint8_t ubPlane = 0; ubPlane < m_ubDepth; ++ubPlane) { - for(uint16_t y = 0; y < m_uwHeight; ++y) { - for(uint16_t x = 0; x < uwRowWordCount; ++x) { - uint16_t uwData = nEndian::toBig16( + for(std::uint8_t ubPlane = 0; ubPlane < m_ubDepth; ++ubPlane) { + for(std::uint16_t y = 0; y < m_uwHeight; ++y) { + for(std::uint16_t x = 0; x < uwRowWordCount; ++x) { + std::uint16_t uwData = nEndian::toBig16( m_pPlanes[ubPlane].at(y * uwRowWordCount + x) ); OutFile.write(reinterpret_cast(&uwData), sizeof(uint16_t)); @@ -235,8 +235,8 @@ tPlanarBitmap tPlanarBitmap::fromBm(const std::string &szPath) return tPlanarBitmap(0, 0, 0); } - uint16_t uwWidth, uwHeight; - uint8_t ubBpp, ubVersion, ubReserved1, ubReserved2; + std::uint16_t uwWidth, uwHeight; + std::uint8_t ubBpp, ubVersion, ubReserved1, ubReserved2; tBmFlags eFlags; File.read(reinterpret_cast(&uwWidth), sizeof(uwWidth)); File.read(reinterpret_cast(&uwHeight), sizeof(uwHeight)); @@ -251,12 +251,12 @@ tPlanarBitmap tPlanarBitmap::fromBm(const std::string &szPath) if(ubVersion == 0) { tPlanarBitmap Bm(uwWidth, uwHeight, ubBpp); - for(uint8_t i = 0; i < ubBpp; ++i) { + for(std::uint8_t i = 0; i < ubBpp; ++i) { Bm.m_pPlanes[i].resize(uwWidth * uwHeight / sizeof(Bm.m_pPlanes[0][0])); } if(eFlags & tBmFlags::INTERLEAVED) { - for(uint32_t y = 0; y < uwHeight; ++y) { - for(uint8_t i = 0; i < ubBpp; ++i) { + for(std::uint32_t y = 0; y < uwHeight; ++y) { + for(std::uint8_t i = 0; i < ubBpp; ++i) { File.read( &(reinterpret_cast(Bm.m_pPlanes[i].data())[y * uwWidth / 8]), uwWidth / 8 @@ -265,7 +265,7 @@ tPlanarBitmap tPlanarBitmap::fromBm(const std::string &szPath) } } else { - for(uint8_t i = 0; i < ubBpp; ++i) { + for(std::uint8_t i = 0; i < ubBpp; ++i) { File.read( reinterpret_cast(Bm.m_pPlanes[i].data()), (uwWidth / 8) * uwHeight @@ -274,7 +274,7 @@ tPlanarBitmap tPlanarBitmap::fromBm(const std::string &szPath) } // Convert endianness on data - for(uint8_t i = ubBpp; i--;) { + for(std::uint8_t i = ubBpp; i--;) { for(auto &Cell: Bm.m_pPlanes[i]) { Cell = nEndian::fromBig16(Cell); } @@ -291,21 +291,21 @@ tPlanarBitmap tPlanarBitmap::fromBm(const std::string &szPath) } } -tRgb &tChunkyBitmap::pixelAt(uint16_t uwX, uint16_t uwY) +tRgb &tChunkyBitmap::pixelAt(std::uint16_t uwX, std::uint16_t uwY) { - uint32_t ulPos = m_uwWidth * (uwY) + uwX; + std::uint32_t ulPos = m_uwWidth * (uwY) + uwX; return m_vData[ulPos]; } -const tRgb &tChunkyBitmap::pixelAt(uint16_t uwX, uint16_t uwY) const +const tRgb &tChunkyBitmap::pixelAt(std::uint16_t uwX, std::uint16_t uwY) const { - uint32_t ulPos = m_uwWidth * (uwY) + uwX; + std::uint32_t ulPos = m_uwWidth * (uwY) + uwX; return m_vData[ulPos]; } bool tChunkyBitmap::copyRect( - uint16_t uwSrcX, uint16_t uwSrcY, tChunkyBitmap &Dst, - uint16_t uwDstX, uint16_t uwDstY, uint16_t uwWidth, uint16_t uwHeight + std::uint16_t uwSrcX, std::uint16_t uwSrcY, tChunkyBitmap &Dst, + std::uint16_t uwDstX, std::uint16_t uwDstY, std::uint16_t uwWidth, std::uint16_t uwHeight ) const { if(uwSrcX + uwWidth > m_uwWidth || uwSrcY + uwHeight > m_uwHeight) { @@ -317,8 +317,8 @@ bool tChunkyBitmap::copyRect( return false; } - for(uint16_t uwY = 0; uwY < uwHeight; ++uwY) { - for(uint16_t uwX = 0; uwX < uwWidth; ++uwX) { + for(std::uint16_t uwY = 0; uwY < uwHeight; ++uwY) { + for(std::uint16_t uwX = 0; uwX < uwWidth; ++uwX) { Dst.pixelAt(uwDstX + uwX, uwDstY + uwY) = pixelAt(uwSrcX + uwX, uwSrcY + uwY); } } @@ -327,7 +327,7 @@ bool tChunkyBitmap::copyRect( } bool tChunkyBitmap::fillRect( - uint16_t uwDstX, uint16_t uwDstY, uint16_t uwWidth, uint16_t uwHeight, + std::uint16_t uwDstX, std::uint16_t uwDstY, std::uint16_t uwWidth, std::uint16_t uwHeight, const tRgb &Color ) { if(uwDstX + uwWidth > m_uwWidth || uwDstY + uwHeight > m_uwHeight) { @@ -335,8 +335,8 @@ bool tChunkyBitmap::fillRect( return false; } - for(uint16_t uwY = 0; uwY < uwHeight; ++uwY) { - for(uint16_t uwX = 0; uwX < uwWidth; ++uwX) { + for(std::uint16_t uwY = 0; uwY < uwHeight; ++uwY) { + for(std::uint16_t uwX = 0; uwX < uwWidth; ++uwX) { pixelAt(uwDstX + uwX, uwDstY + uwY) = Color; } } @@ -350,8 +350,8 @@ bool tChunkyBitmap::mergeWithMask(const tChunkyBitmap &Mask) return false; } - for(uint16_t uwY = 0; uwY < m_uwHeight; ++uwY) { - for(uint16_t uwX = 0; uwX < m_uwWidth; ++uwX) { + for(std::uint16_t uwY = 0; uwY < m_uwHeight; ++uwY) { + for(std::uint16_t uwX = 0; uwX < m_uwWidth; ++uwX) { auto & MaskPixel = Mask.pixelAt(uwX, uwY); if(MaskPixel != tRgb(0)) { pixelAt(uwX, uwY) = MaskPixel; @@ -367,8 +367,8 @@ tChunkyBitmap tChunkyBitmap::filterColors( { const auto &Colors = Palette.m_vColors; tChunkyBitmap Out(m_uwWidth, m_uwHeight); - for(uint16_t uwY = 0; uwY < m_uwHeight; ++uwY) { - for(uint16_t uwX = 0; uwX < m_uwWidth; ++uwX) { + for(std::uint16_t uwY = 0; uwY < m_uwHeight; ++uwY) { + for(std::uint16_t uwX = 0; uwX < m_uwWidth; ++uwX) { const auto &Ref = pixelAt(uwX, uwY); if(std::find(Colors.begin(), Colors.end(), Ref) != Colors.end()) { Out.pixelAt(uwX, uwY) = Ref; diff --git a/tools/src/common/bitmap.h b/tools/src/common/bitmap.h index e07f4b76..100092dd 100644 --- a/tools/src/common/bitmap.h +++ b/tools/src/common/bitmap.h @@ -15,15 +15,15 @@ class tPlanarBitmap; class tChunkyBitmap { public: - uint16_t m_uwWidth = 0; - uint16_t m_uwHeight = 0; + std::uint16_t m_uwWidth = 0; + std::uint16_t m_uwHeight = 0; std::vector m_vData; tChunkyBitmap(const tPlanarBitmap &Planar, const tPalette &Palette); - tChunkyBitmap(uint16_t uwWidth, uint16_t uwHeight, tRgb Bg = tRgb(0)); + tChunkyBitmap(std::uint16_t uwWidth, std::uint16_t uwHeight, tRgb Bg = tRgb(0)); - tChunkyBitmap(uint16_t uwWidth, uint16_t uwHeight, const uint8_t *pData); + tChunkyBitmap(std::uint16_t uwWidth, std::uint16_t uwHeight, const std::uint8_t *pData); tChunkyBitmap(void) { }; @@ -31,16 +31,16 @@ class tChunkyBitmap { static tChunkyBitmap fromPng(const std::string &szPath); - tRgb &pixelAt(uint16_t uwX, uint16_t uwY); - const tRgb &pixelAt(uint16_t uwX, uint16_t uwY) const; + tRgb &pixelAt(std::uint16_t uwX, std::uint16_t uwY); + const tRgb &pixelAt(std::uint16_t uwX, std::uint16_t uwY) const; bool copyRect( - uint16_t uwSrcX, uint16_t uwSrcY, tChunkyBitmap &Dst, - uint16_t uwDstX, uint16_t uwDstY, uint16_t uwWidth, uint16_t uwHeight + std::uint16_t uwSrcX, std::uint16_t uwSrcY, tChunkyBitmap &Dst, + std::uint16_t uwDstX, std::uint16_t uwDstY, std::uint16_t uwWidth, std::uint16_t uwHeight ) const; bool fillRect( - uint16_t uwDstX, uint16_t uwDstY, uint16_t uwWidth, uint16_t uwHeight, + std::uint16_t uwDstX, std::uint16_t uwDstY, std::uint16_t uwWidth, std::uint16_t uwHeight, const tRgb &Color ); @@ -51,9 +51,9 @@ class tChunkyBitmap { class tPlanarBitmap { public: - uint16_t m_uwWidth; - uint16_t m_uwHeight; - uint8_t m_ubDepth; + std::uint16_t m_uwWidth; + std::uint16_t m_uwHeight; + std::uint8_t m_ubDepth; std::vector m_pPlanes[8]; tPlanarBitmap( @@ -61,7 +61,7 @@ class tPlanarBitmap { const tPalette &PaletteIgnore = tPalette() ); - tPlanarBitmap(uint16_t uwWidth, uint16_t uwHeight, uint8_t ubDepth); + tPlanarBitmap(std::uint16_t uwWidth, std::uint16_t uwHeight, std::uint8_t ubDepth); bool toBm(const std::string &szPath, bool isInterleaved); diff --git a/tools/src/common/endian.h b/tools/src/common/endian.h index 08178ef7..c9ce8cd1 100644 --- a/tools/src/common/endian.h +++ b/tools/src/common/endian.h @@ -14,7 +14,7 @@ namespace nEndian { return std::endian::native == std::endian::big; } - constexpr uint16_t toBig16(uint16_t uwIn) + constexpr std::uint16_t toBig16(std::uint16_t uwIn) { if(isBig()) { return uwIn; @@ -25,12 +25,12 @@ namespace nEndian { ); } - constexpr uint16_t fromBig16(uint16_t uwIn) + constexpr std::uint16_t fromBig16(std::uint16_t uwIn) { return toBig16(uwIn); } - constexpr uint32_t toBig32(uint32_t ulIn) + constexpr std::uint32_t toBig32(std::uint32_t ulIn) { if(isBig()) { return ulIn; @@ -43,7 +43,7 @@ namespace nEndian { ); } - constexpr uint32_t fromBig32(uint32_t uwIn) + constexpr std::uint32_t fromBig32(std::uint32_t uwIn) { return toBig32(uwIn); } diff --git a/tools/src/common/glyph_set.cpp b/tools/src/common/glyph_set.cpp index cd206f3c..e6d2f39b 100644 --- a/tools/src/common/glyph_set.cpp +++ b/tools/src/common/glyph_set.cpp @@ -14,7 +14,7 @@ #include "../common/logging.h" #include "utf8.h" -tGlyphSet tGlyphSet::fromPmng(const std::string &szPngPath, uint8_t ubStartIdx) +tGlyphSet tGlyphSet::fromPmng(const std::string &szPngPath, std::uint8_t ubStartIdx) { tGlyphSet GlyphSet; @@ -26,12 +26,12 @@ tGlyphSet tGlyphSet::fromPmng(const std::string &szPngPath, uint8_t ubStartIdx) const auto &Delimiter = Bitmap.pixelAt(0, 0); const auto &Bg = Bitmap.pixelAt(0, 1); - uint16_t uwStart = 0; - uint16_t uwCurrChar = ubStartIdx; + std::uint16_t uwStart = 0; + std::uint16_t uwCurrChar = ubStartIdx; - for(uint16_t i = 1; i < Bitmap.m_uwWidth; ++i) { + for(std::uint16_t i = 1; i < Bitmap.m_uwWidth; ++i) { if(Bitmap.pixelAt(i, 0) == Delimiter) { - uint16_t uwStop = i; + std::uint16_t uwStop = i; tGlyphSet::tBitmapGlyph Glyph; Glyph.m_ubWidth = (uwStop - uwStart) - 1; @@ -39,8 +39,8 @@ tGlyphSet tGlyphSet::fromPmng(const std::string &szPngPath, uint8_t ubStartIdx) Glyph.m_ubBearing = 0; Glyph.m_vData.reserve(Glyph.m_ubWidth * Glyph.m_ubHeight); - for(uint16_t y = 0; y < Bitmap.m_uwHeight; ++y) { - for(uint16_t x = uwStart + 1; x < uwStop; ++x) { + for(std::uint16_t y = 0; y < Bitmap.m_uwHeight; ++y) { + for(std::uint16_t x = uwStart + 1; x < uwStop; ++x) { const auto &Pixel = Bitmap.pixelAt(x, y); Glyph.m_vData.push_back((Pixel == Bg ? 0 : 0xFF)); } @@ -64,8 +64,8 @@ tGlyphSet tGlyphSet::fromAceFont(const std::string &szFntPath) } // Read header - uint8_t ubCharCount; - uint16_t uwBitmapWidth, uwBitmapHeight; + std::uint8_t ubCharCount; + std::uint16_t uwBitmapWidth, uwBitmapHeight; FileFnt.read(reinterpret_cast(&uwBitmapWidth), sizeof(uwBitmapWidth)); FileFnt.read(reinterpret_cast(&uwBitmapHeight), sizeof(uwBitmapHeight)); FileFnt.read(reinterpret_cast(&ubCharCount), sizeof(ubCharCount)); @@ -75,18 +75,18 @@ tGlyphSet tGlyphSet::fromAceFont(const std::string &szFntPath) // Read char offsets - read offset of one more to get last char's width std::vector vCharOffsets; vCharOffsets.reserve(ubCharCount); - for(uint16_t c = 0; c < ubCharCount; ++c) { - uint16_t uwOffs; + for(std::uint16_t c = 0; c < ubCharCount; ++c) { + std::uint16_t uwOffs; FileFnt.read(reinterpret_cast(&uwOffs), sizeof(uwOffs)); uwOffs = nEndian::fromBig16(uwOffs); vCharOffsets.push_back(uwOffs); } tPlanarBitmap GlyphBitmapPlanar(uwBitmapWidth, uwBitmapHeight, 1); - uint32_t ulOffs = 0; - for(uint16_t uwY = 0; uwY < uwBitmapHeight; ++uwY) { - for(uint16_t uwX = 0; uwX < uwBitmapWidth / 16; ++uwX) { - uint16_t uwData; + std::uint32_t ulOffs = 0; + for(std::uint16_t uwY = 0; uwY < uwBitmapHeight; ++uwY) { + for(std::uint16_t uwX = 0; uwX < uwBitmapWidth / 16; ++uwX) { + std::uint16_t uwData; FileFnt.read(reinterpret_cast(&uwData), sizeof(uwData)); uwData = nEndian::fromBig16(uwData); GlyphBitmapPlanar.m_pPlanes[0][ulOffs++] = uwData; @@ -98,13 +98,13 @@ tGlyphSet tGlyphSet::fromAceFont(const std::string &szFntPath) Palette.m_vColors.push_back(tRgb(0)); Palette.m_vColors.push_back(tRgb(0xFF)); tChunkyBitmap Chunky(GlyphBitmapPlanar, Palette); - for(uint16_t c = 0; c < ubCharCount - 1; ++c) { - uint8_t ubGlyphWidth = vCharOffsets[c + 1] - vCharOffsets[c]; + for(std::uint16_t c = 0; c < ubCharCount - 1; ++c) { + std::uint8_t ubGlyphWidth = vCharOffsets[c + 1] - vCharOffsets[c]; if(ubGlyphWidth) { tBitmapGlyph Glyph; Glyph.m_vData.resize(uwBitmapHeight * ubGlyphWidth); - for(uint8_t ubY = 0; ubY < uwBitmapHeight; ++ubY) { - for(uint8_t ubX = 0; ubX < ubGlyphWidth; ++ubX) { + for(std::uint8_t ubY = 0; ubY < uwBitmapHeight; ++ubY) { + for(std::uint8_t ubX = 0; ubX < ubGlyphWidth; ++ubX) { // Since filled in Chunky is (FF,FF,FF), use data from any channel. Glyph.m_vData[ubY * ubGlyphWidth + ubX] = Chunky.pixelAt(vCharOffsets[c] + ubX, ubY).ubR; } @@ -119,8 +119,8 @@ tGlyphSet tGlyphSet::fromAceFont(const std::string &szFntPath) } tGlyphSet tGlyphSet::fromTtf( - const std::string &szTtfPath, uint8_t ubSize, const std::string &szCharSet, - uint8_t ubThreshold + const std::string &szTtfPath, std::uint8_t ubSize, const std::string &szCharSet, + std::uint8_t ubThreshold ) { tGlyphSet GlyphSet; @@ -141,8 +141,8 @@ tGlyphSet tGlyphSet::fromTtf( FT_Set_Pixel_Sizes(Face, 0, ubSize); - uint8_t ubMaxBearing = 0, ubMaxAddHeight = 0; - uint32_t ulCodepoint, ulState = 0; + std::uint8_t ubMaxBearing = 0, ubMaxAddHeight = 0; + std::uint32_t ulCodepoint, ulState = 0; for(const auto &c: szCharSet) { auto CharCode = *reinterpret_cast(&c); if ( @@ -154,8 +154,8 @@ tGlyphSet tGlyphSet::fromTtf( FT_Load_Char(Face, ulCodepoint, FT_LOAD_RENDER); - uint8_t ubWidth = Face->glyph->bitmap.width; - uint8_t ubHeight = Face->glyph->bitmap.rows; + std::uint8_t ubWidth = Face->glyph->bitmap.width; + std::uint8_t ubHeight = Face->glyph->bitmap.rows; GlyphSet.m_mGlyphs[ulCodepoint] = { static_cast(Face->glyph->metrics.horiBearingY / 64), @@ -164,8 +164,8 @@ tGlyphSet tGlyphSet::fromTtf( auto &Glyph = GlyphSet.m_mGlyphs[ulCodepoint]; // Copy bitmap graphics with threshold - for(uint32_t ulPos = 0; ulPos < Glyph.m_vData.size(); ++ulPos) { - uint8_t ubVal = (Face->glyph->bitmap.buffer[ulPos] >= ubThreshold) ? 0xFF : 0; + for(std::uint32_t ulPos = 0; ulPos < Glyph.m_vData.size(); ++ulPos) { + std::uint8_t ubVal = (Face->glyph->bitmap.buffer[ulPos] >= ubThreshold) ? 0xFF : 0; Glyph.m_vData[ulPos] = ubVal; } @@ -188,7 +188,7 @@ tGlyphSet tGlyphSet::fromTtf( FT_Done_Face(Face); FT_Done_FreeType(FreeType); - uint8_t ubBmHeight = ubMaxBearing + ubMaxAddHeight; + std::uint8_t ubBmHeight = ubMaxBearing + ubMaxAddHeight; // Normalize Glyph height for(auto &GlyphPair: GlyphSet.m_mGlyphs) { @@ -208,7 +208,7 @@ tGlyphSet tGlyphSet::fromTtf( tGlyphSet tGlyphSet::fromDir(const std::string &szDirPath) { tGlyphSet GlyphSet; - for(uint16_t c = 0; c <= 255; ++c) { + for(std::uint16_t c = 0; c <= 255; ++c) { auto Chunky = tChunkyBitmap::fromPng(fmt::format("{}/{}.png", szDirPath, c)); if(Chunky.m_uwHeight) { tGlyphSet::tBitmapGlyph Glyph; @@ -256,17 +256,17 @@ bool tGlyphSet::toDir(const std::string &szDirPath) tChunkyBitmap tGlyphSet::toPackedBitmap(bool isPmng) { - uint8_t ubHeight = m_mGlyphs.begin()->second.m_ubHeight; + std::uint8_t ubHeight = m_mGlyphs.begin()->second.m_ubHeight; // Calculate total width & round up to multiple of 16 - uint16_t uwWidth = 0; + std::uint16_t uwWidth = 0; for(const auto &[Key, Glyph]: m_mGlyphs) { uwWidth += Glyph.m_ubWidth + (isPmng ? 1 : 0); } uwWidth = ((uwWidth + 15) / 16) * 16; tChunkyBitmap Chunky(uwWidth, ubHeight, tRgb(0)); - uint16_t uwOffsX = 0; + std::uint16_t uwOffsX = 0; for(const auto &[Key, Glyph]: m_mGlyphs) { if(isPmng) { // Add start marker @@ -284,15 +284,15 @@ tChunkyBitmap tGlyphSet::toPackedBitmap(bool isPmng) return Chunky; } -uint8_t tGlyphSet::tBitmapGlyph::getValueAt(uint8_t ubX, uint8_t ubY) +std::uint8_t tGlyphSet::tBitmapGlyph::getValueAt(std::uint8_t ubX, std::uint8_t ubY) { - uint8_t ubValue = this->m_vData[ubY * this->m_ubWidth + ubY]; + std::uint8_t ubValue = this->m_vData[ubY * this->m_ubWidth + ubY]; return ubValue; } -bool tGlyphSet::tBitmapGlyph::hasEmptyColumn(uint8_t ubX) +bool tGlyphSet::tBitmapGlyph::hasEmptyColumn(std::uint8_t ubX) { - for(uint8_t ubY = 0; ubY < this->m_ubHeight; ++ubY) { + for(std::uint8_t ubY = 0; ubY < this->m_ubHeight; ++ubY) { if(getValueAt(ubX, ubY) != 0) { return false; } @@ -302,7 +302,7 @@ bool tGlyphSet::tBitmapGlyph::hasEmptyColumn(uint8_t ubX) bool tGlyphSet::tBitmapGlyph::isEmpty(void) { - for(uint8_t ubX = 0; ubX < this->m_ubWidth; ++ubX) { + for(std::uint8_t ubX = 0; ubX < this->m_ubWidth; ++ubX) { if(!hasEmptyColumn(ubX)) { return false; } @@ -316,8 +316,8 @@ void tGlyphSet::tBitmapGlyph::trimHorz(bool isRight) return; } - uint8_t ubNewWidth; - uint8_t ubNewStart; + std::uint8_t ubNewWidth; + std::uint8_t ubNewStart; if(isRight) { ubNewStart = 0; for(ubNewWidth = m_ubWidth; ubNewWidth > 0; --ubNewWidth) { @@ -336,8 +336,8 @@ void tGlyphSet::tBitmapGlyph::trimHorz(bool isRight) } std::vector vNew(ubNewWidth * m_ubHeight); - for(uint8_t ubNewX = 0; ubNewX < ubNewWidth; ++ubNewX) { - for(uint8_t ubNewY = 0; ubNewY < m_ubHeight; ++ubNewY) { + for(std::uint8_t ubNewX = 0; ubNewX < ubNewWidth; ++ubNewX) { + for(std::uint8_t ubNewY = 0; ubNewY < m_ubHeight; ++ubNewY) { vNew[ubNewY * ubNewWidth + ubNewX] = this->m_vData[ubNewY * m_ubWidth + ubNewStart + ubNewX]; } } @@ -347,8 +347,8 @@ void tGlyphSet::tBitmapGlyph::trimHorz(bool isRight) void tGlyphSet::toAceFont(const std::string &szFontPath) { - uint16_t uwOffs = 0; - uint8_t ubCharCount = 0; + std::uint16_t uwOffs = 0; + std::uint8_t ubCharCount = 0; for(const auto &GlyphPair: m_mGlyphs) { if(GlyphPair.first > ubCharCount) { ubCharCount = GlyphPair.first; @@ -357,7 +357,7 @@ void tGlyphSet::toAceFont(const std::string &szFontPath) ++ubCharCount; // Generate char offsets std::vector vCharOffsets(256); - for(uint16_t c = 0; c < ubCharCount; ++c) { + for(std::uint16_t c = 0; c < ubCharCount; ++c) { vCharOffsets[c] = nEndian::toBig16(uwOffs); if(m_mGlyphs.count(c) != 0) { const auto &Glyph = m_mGlyphs.at(c); @@ -374,9 +374,9 @@ void tGlyphSet::toAceFont(const std::string &szFontPath) std::ofstream Out(szFontPath, std::ofstream::out | std::ofstream::binary); // Write header - uint16_t uwBitmapWidth = nEndian::toBig16(Planar.m_uwWidth); + std::uint16_t uwBitmapWidth = nEndian::toBig16(Planar.m_uwWidth); Out.write(reinterpret_cast(&uwBitmapWidth), sizeof(uint16_t)); - uint16_t uwBitmapHeight = nEndian::toBig16(m_mGlyphs.begin()->second.m_ubHeight); + std::uint16_t uwBitmapHeight = nEndian::toBig16(m_mGlyphs.begin()->second.m_ubHeight); Out.write(reinterpret_cast(&uwBitmapHeight), sizeof(uint16_t)); Out.write(reinterpret_cast(&ubCharCount), sizeof(uint8_t)); @@ -386,10 +386,10 @@ void tGlyphSet::toAceFont(const std::string &szFontPath) ); // Write font bitplane - uint16_t uwRowWords = Planar.m_uwWidth / 16; - for(uint16_t y = 0; y < Planar.m_uwHeight; ++y) { - for(uint16_t x = 0; x < uwRowWords; ++x) { - uint16_t uwData = nEndian::toBig16(Planar.m_pPlanes[0][y * uwRowWords + x]); + std::uint16_t uwRowWords = Planar.m_uwWidth / 16; + for(std::uint16_t y = 0; y < Planar.m_uwHeight; ++y) { + for(std::uint16_t x = 0; x < uwRowWords; ++x) { + std::uint16_t uwData = nEndian::toBig16(Planar.m_pPlanes[0][y * uwRowWords + x]); Out.write(reinterpret_cast(&uwData), sizeof(uint16_t)); } } diff --git a/tools/src/common/glyph_set.h b/tools/src/common/glyph_set.h index 544b829a..7ac25cae 100644 --- a/tools/src/common/glyph_set.h +++ b/tools/src/common/glyph_set.h @@ -13,8 +13,8 @@ class tGlyphSet { public: static tGlyphSet fromTtf( - const std::string &szTtfPath, uint8_t ubSize, const std::string &szCharSet, - uint8_t ubThreshold + const std::string &szTtfPath, std::uint8_t ubSize, const std::string &szCharSet, + std::uint8_t ubThreshold ); /** @@ -24,7 +24,7 @@ class tGlyphSet { * @param ubStartIdx ASCII index of first glyph in PMNG file. * @return Glyph set filled with characters from file. */ - static tGlyphSet fromPmng(const std::string &szPngPath, uint8_t ubStartIdx = 33); + static tGlyphSet fromPmng(const std::string &szPngPath, std::uint8_t ubStartIdx = 33); /** * @brief Creates glyph set based on ACE font (.fnt) file. @@ -48,15 +48,15 @@ class tGlyphSet { private: struct tBitmapGlyph { - uint8_t m_ubBearing; - uint8_t m_ubWidth, m_ubHeight; + std::uint8_t m_ubBearing; + std::uint8_t m_ubWidth, m_ubHeight; std::vector m_vData; ///< One byte per pixel, 0 for bg, 0xFF otherwise. void trimHorz(bool isRight); - uint8_t getValueAt(uint8_t ubX, uint8_t ubY); + std::uint8_t getValueAt(std::uint8_t ubX, std::uint8_t ubY); bool isEmpty(void); - bool hasEmptyColumn(uint8_t ubX); + bool hasEmptyColumn(std::uint8_t ubX); }; std::map m_mGlyphs; diff --git a/tools/src/common/math.h b/tools/src/common/math.h index fe3640d0..8e20b81d 100644 --- a/tools/src/common/math.h +++ b/tools/src/common/math.h @@ -6,7 +6,7 @@ #define _ACE_TOOLS_COMMON_MATH_H_ #if defined(_MSC_VER) && _MSC_VER < 1930 -auto ceilToFactor(uint64_t Value, int64_t Multiple) { +auto ceilToFactor(std::uint64_t Value, std::int64_t Multiple) { #else auto ceilToFactor(auto Value, auto Multiple) { #endif diff --git a/tools/src/common/mod.cpp b/tools/src/common/mod.cpp index 830bacff..684b889e 100644 --- a/tools/src/common/mod.cpp +++ b/tools/src/common/mod.cpp @@ -16,7 +16,7 @@ tMod::tMod(const std::string &szFileName) FileIn.open(szFileName, std::ios::binary); FileIn.seekg(0, std::ios::end); - uint32_t ulFileSize = FileIn.tellg(); // For pattern count calc + std::uint32_t ulFileSize = FileIn.tellg(); // For pattern count calc FileIn.seekg(0, std::ios::beg); @@ -26,11 +26,11 @@ tMod::tMod(const std::string &szFileName) m_szSongName = szSongNameRaw; // Read sample info - uint32_t ulTotalSampleSize = 0; - for(uint8_t i = 0; i < 31; ++i) { + std::uint32_t ulTotalSampleSize = 0; + for(std::uint8_t i = 0; i < 31; ++i) { char szSampleNameRaw[SAMPLE_NAME_SIZE]; - uint16_t uwSampleLen, uwSampleRepeatOffs, uwSampleRepeatLength; - uint8_t ubSampleFineTune, ubSampleLinearVolume; + std::uint16_t uwSampleLen, uwSampleRepeatOffs, uwSampleRepeatLength; + std::uint8_t ubSampleFineTune, ubSampleLinearVolume; FileIn.read(szSampleNameRaw, sizeof(szSampleNameRaw)); FileIn.read( @@ -57,10 +57,10 @@ tMod::tMod(const std::string &szFileName) // Data read successfully, fill sample info tSample Sample; - for (uint8_t ubCharIndex = 0; ubCharIndex < SAMPLE_NAME_SIZE; ++ubCharIndex){ + for (std::uint8_t ubCharIndex = 0; ubCharIndex < SAMPLE_NAME_SIZE; ++ubCharIndex){ // sample name to uppercase, to avoid duplicates // will be reworked to: comparison between samples on temporarily uppercased copies - szSampleNameRaw[ubCharIndex] = std::toupper(szSampleNameRaw[ubCharIndex]); + szSampleNameRaw[ubCharIndex] = std::toupper(szSampleNameRaw[ubCharIndex]); } Sample.m_szName = szSampleNameRaw; Sample.m_ubFineTune = ubSampleFineTune; @@ -93,21 +93,21 @@ tMod::tMod(const std::string &szFileName) } // Determine pattern count - uint32_t ulCurrPos = FileIn.tellg(); - uint32_t ulPatternDataSize = (ulFileSize - ulCurrPos - ulTotalSampleSize); + std::uint32_t ulCurrPos = FileIn.tellg(); + std::uint32_t ulPatternDataSize = (ulFileSize - ulCurrPos - ulTotalSampleSize); if((ulPatternDataSize / 1024) * 1024 != ulPatternDataSize) { fmt::print("ERR: unexpected size of pattern data!"); throw std::exception(); } - uint8_t ubPatternCount = (ulFileSize - ulCurrPos - ulTotalSampleSize) / 1024; + std::uint8_t ubPatternCount = (ulFileSize - ulCurrPos - ulTotalSampleSize) / 1024; // Read pattern data m_vPatterns.resize(ubPatternCount); - for(uint8_t ubPattern = 0; ubPattern < ubPatternCount; ++ubPattern) { - for(uint8_t ubRow = 0; ubRow < 64; ++ubRow) { + for(std::uint8_t ubPattern = 0; ubPattern < ubPatternCount; ++ubPattern) { + for(std::uint8_t ubRow = 0; ubRow < 64; ++ubRow) { std::array NotesInRow; - for(uint8_t i = 0; i < 4; ++i) { - uint32_t ulRawNote; // [instrumentHi:4] [period:12] [instrumentLo:4] [cmdNo:4] [cmdArg:8] + for(std::uint8_t i = 0; i < 4; ++i) { + std::uint32_t ulRawNote; // [instrumentHi:4] [period:12] [instrumentLo:4] [cmdNo:4] [cmdArg:8] FileIn.read(reinterpret_cast(&ulRawNote), sizeof(ulRawNote)); ulRawNote = nEndian::fromBig32(ulRawNote); tNote Note = { @@ -144,9 +144,9 @@ void tMod::toMod(const std::string &szFileName, bool isSkipSampleData) // Samples for(const auto &Sample: m_vSamples) { - uint16_t uwSampleLen = nEndian::toBig16(Sample.m_vData.size()); - uint16_t uwSampleRepeatOffs = nEndian::toBig16(Sample.m_uwRepeatOffs); - uint16_t uwSampleRepeatLength = nEndian::toBig16(Sample.m_uwRepeatLength); + std::uint16_t uwSampleLen = nEndian::toBig16(Sample.m_vData.size()); + std::uint16_t uwSampleRepeatOffs = nEndian::toBig16(Sample.m_uwRepeatOffs); + std::uint16_t uwSampleRepeatLength = nEndian::toBig16(Sample.m_uwRepeatLength); // Ensure that garbage after null terminator doesn't get copied char szSampleNameRaw[22] = {'\0'}; @@ -182,11 +182,11 @@ void tMod::toMod(const std::string &szFileName, bool isSkipSampleData) // Pattern data for(const auto &Pattern: m_vPatterns) { - for(uint8_t ubRow = 0; ubRow < 64; ++ubRow) { - for(uint8_t ubChan = 0; ubChan < 4; ++ubChan) { + for(std::uint8_t ubRow = 0; ubRow < 64; ++ubRow) { + for(std::uint8_t ubChan = 0; ubChan < 4; ++ubChan) { const auto Note = &Pattern[ubRow][ubChan]; // [instrumentHi:4] [period:12] [instrumentLo:4] [cmdNo:4] [cmdArg:8] - uint32_t ulNoteRaw = nEndian::toBig32( + std::uint32_t ulNoteRaw = nEndian::toBig32( ((Note->ubInstrument & 0xF0 ) << 24) | ((Note->uwPeriod & 0x0FFF) << 16) | ((Note->ubInstrument & 0x0F ) << 12) | @@ -223,9 +223,9 @@ void tMod::reorderSamples(const std::vector vNewOrder) { // Generate reordered sample defs - do it on copy because of X->Y & Y->X std::vector vSamplesNew(m_vSamples.size()); - for(uint8_t ubOldIdx = 0; ubOldIdx < vNewOrder.size(); ++ubOldIdx) { + for(std::uint8_t ubOldIdx = 0; ubOldIdx < vNewOrder.size(); ++ubOldIdx) { if(!m_vSamples[ubOldIdx].m_szName.empty()) { - uint8_t ubNewIdx = vNewOrder[ubOldIdx]; + std::uint8_t ubNewIdx = vNewOrder[ubOldIdx]; vSamplesNew[ubNewIdx] = m_vSamples[ubOldIdx]; } } diff --git a/tools/src/common/mod.h b/tools/src/common/mod.h index abe04f37..30bbd7bd 100644 --- a/tools/src/common/mod.h +++ b/tools/src/common/mod.h @@ -8,13 +8,14 @@ #include #include #include +#include struct tSample { std::string m_szName; - uint8_t m_ubFineTune; ///< Finetune. Only lower nibble is used. Values translate to finetune: {0..7, -8..-1} - uint8_t m_ubVolume; ///< Sample volume. 0..64 - uint16_t m_uwRepeatOffs; ///< In words. - uint16_t m_uwRepeatLength; ///< In words. + std::uint8_t m_ubFineTune; ///< Finetune. Only lower nibble is used. Values translate to finetune: {0..7, -8..-1} + std::uint8_t m_ubVolume; ///< Sample volume. 0..64 + std::uint16_t m_uwRepeatOffs; ///< In words. + std::uint16_t m_uwRepeatLength; ///< In words. std::vector m_vData; @@ -26,10 +27,10 @@ struct tSample { }; struct tNote { - uint8_t ubInstrument; - uint16_t uwPeriod; - uint8_t ubCmd; - uint8_t ubCmdArg; + std::uint8_t ubInstrument; + std::uint16_t uwPeriod; + std::uint8_t ubCmd; + std::uint8_t ubCmdArg; }; class tMod { @@ -56,8 +57,8 @@ class tMod { private: std::string m_szSongName; - uint8_t m_ubArrangementLength; ///< End pattern idx? Jumps are possible. - uint8_t m_ubSongEndPos; + std::uint8_t m_ubArrangementLength; ///< End pattern idx? Jumps are possible. + std::uint8_t m_ubSongEndPos; std::string m_szFileFormatTag; ///< Should be "M.K." for 31-sample format. std::vector m_vSamples; diff --git a/tools/src/common/palette.cpp b/tools/src/common/palette.cpp index 4929193e..d2be9ec7 100644 --- a/tools/src/common/palette.cpp +++ b/tools/src/common/palette.cpp @@ -64,12 +64,12 @@ tPalette tPalette::fromPlt(const std::string &szPath) std::ifstream Source(szPath, std::ios::in | std::ios::binary); - uint8_t ubPaletteCount; + std::uint8_t ubPaletteCount; Source.read(reinterpret_cast(&ubPaletteCount), 1); fmt::print("Palette color count: {}\n", ubPaletteCount); - for(uint8_t i = 0; i != ubPaletteCount; ++i) { - uint8_t ubXR, ubGB; + for(std::uint8_t i = 0; i != ubPaletteCount; ++i) { + std::uint8_t ubXR, ubGB; Source.read(reinterpret_cast(&ubXR), 1); Source.read(reinterpret_cast(&ubGB), 1); Palette.m_vColors.push_back(tRgb( @@ -86,9 +86,9 @@ tPalette tPalette::fromPromotionPal(const std::string &szPath) tPalette Palette; std::ifstream Source(szPath, std::ios::in | std::ios::binary); - uint16_t uwLastNonZero = 0; - for(uint16_t i = 0; i < 256; ++i) { - uint8_t ubR, ubG, ubB; + std::uint16_t uwLastNonZero = 0; + for(std::uint16_t i = 0; i < 256; ++i) { + std::uint8_t ubR, ubG, ubB; Source.read(reinterpret_cast(&ubR), 1); Source.read(reinterpret_cast(&ubG), 1); Source.read(reinterpret_cast(&ubB), 1); @@ -112,8 +112,8 @@ tPalette tPalette::fromAct(const std::string &szPath) tPalette Palette; std::ifstream Source(szPath, std::ios::in | std::ios::binary); - for(uint16_t i = 0; i < 256; ++i) { - uint8_t ubR, ubG, ubB; + for(std::uint16_t i = 0; i < 256; ++i) { + std::uint8_t ubR, ubG, ubB; Source.read(reinterpret_cast(&ubR), 1); Source.read(reinterpret_cast(&ubG), 1); Source.read(reinterpret_cast(&ubB), 1); @@ -121,8 +121,8 @@ tPalette tPalette::fromAct(const std::string &szPath) } // Read color count - uint8_t ubSizeHi, ubSizeLo; - uint16_t uwSize; + std::uint8_t ubSizeHi, ubSizeLo; + std::uint16_t uwSize; Source.read(reinterpret_cast(&ubSizeHi), 1); Source.read(reinterpret_cast(&ubSizeLo), 1); uwSize = (ubSizeHi << 8) | ubSizeLo; @@ -163,7 +163,7 @@ bool tPalette::toPlt(const std::string &szPath, bool isForceOcs) } auto PaletteSize = m_vColors.size(); Dest.write(reinterpret_cast(&PaletteSize), 1); - for(uint16_t uwColorIdx = 0; uwColorIdx < PaletteSize; ++uwColorIdx) { + for(std::uint16_t uwColorIdx = 0; uwColorIdx < PaletteSize; ++uwColorIdx) { const auto &Color = m_vColors[uwColorIdx]; if(isForceOcs) { const auto &ColorOcs = Color.to12Bit(); @@ -178,8 +178,8 @@ bool tPalette::toPlt(const std::string &szPath, bool isForceOcs) } } - uint8_t ubXR = Color.ubR >> 4; - uint8_t ubGB = ((Color.ubG >> 4) << 4) | (Color.ubB >> 4); + std::uint8_t ubXR = Color.ubR >> 4; + std::uint8_t ubGB = ((Color.ubG >> 4) << 4) | (Color.ubB >> 4); Dest.write(reinterpret_cast(&ubXR), 1); Dest.write(reinterpret_cast(&ubGB), 1); } @@ -218,7 +218,7 @@ bool tPalette::toPromotionPal(const std::string &szPath) return false; } - uint32_t i; + std::uint32_t i; for(i = 0; i < m_vColors.size(); ++i) { const auto &Color = m_vColors.at(i); Dest.write(reinterpret_cast(&Color.ubR), 1); @@ -241,7 +241,7 @@ bool tPalette::toAct(const std::string &szPath) return false; } - uint32_t i; + std::uint32_t i; for(i = 0; i < m_vColors.size(); ++i) { const auto &Color = m_vColors.at(i); Dest.write(reinterpret_cast(&Color.ubR), 1); @@ -253,8 +253,8 @@ bool tPalette::toAct(const std::string &szPath) Dest.write(pBlank, 3); ++i; } - uint8_t ubSizeHi = uint16_t(m_vColors.size()) >> 8; - uint8_t ubSizeLo = m_vColors.size() & 0xFF; + std::uint8_t ubSizeHi = uint16_t(m_vColors.size()) >> 8; + std::uint8_t ubSizeLo = m_vColors.size() & 0xFF; Dest.write(reinterpret_cast(&ubSizeHi), 1); Dest.write(reinterpret_cast(&ubSizeLo), 1); @@ -262,9 +262,9 @@ bool tPalette::toAct(const std::string &szPath) return true; } -int16_t tPalette::getColorIdx(const tRgb &Ref) const +std::int16_t tPalette::getColorIdx(const tRgb &Ref) const { - uint8_t i = 0; + std::uint8_t i = 0; for(const auto &Color: m_vColors) { if(Color == Ref) { return i; @@ -278,9 +278,9 @@ bool tPalette::isValid(void) const { return m_vColors.size() != 0; } -uint8_t tPalette::getBpp(void) const { - uint8_t ubBpp = 1; - for(size_t i = 2; i < m_vColors.size(); i <<= 1) { +std::uint8_t tPalette::getBpp(void) const { + std::uint8_t ubBpp = 1; + for(std::size_t i = 2; i < m_vColors.size(); i <<= 1) { ++ubBpp; } return ubBpp; diff --git a/tools/src/common/palette.h b/tools/src/common/palette.h index 80e6c85b..e4cdf456 100644 --- a/tools/src/common/palette.h +++ b/tools/src/common/palette.h @@ -32,7 +32,7 @@ class tPalette { bool isValid(void) const; - uint8_t getBpp(void) const; + std::uint8_t getBpp(void) const; std::vector m_vColors; @@ -42,7 +42,7 @@ class tPalette { m_vColors(vColors) {} - int16_t getColorIdx(const tRgb &Ref) const; + std::int16_t getColorIdx(const tRgb &Ref) const; }; #endif // _ACE_TOOLS_COMMON_PALETTE_H_ diff --git a/tools/src/common/parse.h b/tools/src/common/parse.h index d642851c..1dc26f24 100644 --- a/tools/src/common/parse.h +++ b/tools/src/common/parse.h @@ -11,7 +11,7 @@ namespace nParse { static inline bool toInt32( - const std::string &szVal, const std::string &szValName, int32_t &lOut + const std::string &szVal, const std::string &szValName, std::int32_t &lOut ) { try { diff --git a/tools/src/common/rgb.h b/tools/src/common/rgb.h index c9b06eac..b33d85ff 100644 --- a/tools/src/common/rgb.h +++ b/tools/src/common/rgb.h @@ -9,12 +9,12 @@ #include struct tRgb { - uint8_t ubR, ubG, ubB; + std::uint8_t ubR, ubG, ubB; - tRgb(uint8_t ubNewR, uint8_t ubNewG, uint8_t ubNewB): + tRgb(std::uint8_t ubNewR, std::uint8_t ubNewG, std::uint8_t ubNewB): ubR(ubNewR), ubG(ubNewG), ubB(ubNewB) { } - tRgb(uint8_t ubGrayscale): + tRgb(std::uint8_t ubGrayscale): ubR(ubGrayscale), ubG(ubGrayscale), ubB(ubGrayscale) { } tRgb(): diff --git a/tools/src/common/sfx.cpp b/tools/src/common/sfx.cpp index 7f57b859..b3aa0f92 100644 --- a/tools/src/common/sfx.cpp +++ b/tools/src/common/sfx.cpp @@ -23,7 +23,7 @@ tSfx::tSfx(const tWav &Wav, bool isStrict): if(BitsPerSample == 8) { // Convert 8-bit unsigned to signed - https://wiki.multimedia.cx/index.php/PCM#Sign for(const auto &UnsignedSample: vWavData) { - int8_t bSample = UnsignedSample - 128; + std::int8_t bSample = UnsignedSample - 128; m_vData.push_back(bSample); } } @@ -35,9 +35,9 @@ tSfx::tSfx(const tWav &Wav, bool isStrict): } nLog::warn("Resampling data - may result in poor results!"); auto DataSize = vWavData.size(); - for(uint32_t i = 0; i < DataSize; i += 2) { - uint16_t uwRawSample = vWavData[i + 0] | (vWavData[i + 1] << 8); - auto *pAsSigned = reinterpret_cast(&uwRawSample); + for(std::uint32_t i = 0; i < DataSize; i += 2) { + std::uint16_t uwRawSample = vWavData[i + 0] | (vWavData[i + 1] << 8); + auto *pAsSigned = reinterpret_cast(&uwRawSample); m_vData.push_back(*pAsSigned / 256); } } @@ -51,9 +51,9 @@ tSfx::tSfx(const tWav &Wav, bool isStrict): bool tSfx::toSfx(const std::string &szPath) const { std::ofstream FileOut(szPath, std::ios::binary); - const uint8_t ubVersion = 1; - const uint16_t uwWordLength = nEndian::toBig16(uint16_t(m_vData.size() / 2)); - const uint16_t uwSampleReateHz = nEndian::toBig16(m_ulFreq); + const std::uint8_t ubVersion = 1; + const std::uint16_t uwWordLength = nEndian::toBig16(uint16_t(m_vData.size() / 2)); + const std::uint16_t uwSampleReateHz = nEndian::toBig16(m_ulFreq); FileOut.write(reinterpret_cast(&ubVersion), sizeof(ubVersion)); FileOut.write(reinterpret_cast(&uwWordLength), sizeof(uwWordLength)); @@ -68,7 +68,7 @@ bool tSfx::isEmpty(void) const return m_vData.empty(); } -uint32_t tSfx::getLength(void) const +std::uint32_t tSfx::getLength(void) const { return m_vData.size(); } @@ -76,7 +76,7 @@ uint32_t tSfx::getLength(void) const void tSfx::normalize(void) { // Get the biggest amplitude - negative or positive - int8_t bMaxAmplitude = 0; + std::int8_t bMaxAmplitude = 0; for(const auto &Sample: m_vData) { auto Amplitude = abs(Sample); if(Amplitude > bMaxAmplitude) { @@ -90,14 +90,14 @@ void tSfx::normalize(void) } } -void tSfx::divideAmplitude(uint8_t ubDivisor) +void tSfx::divideAmplitude(std::uint8_t ubDivisor) { for(auto &Sample: m_vData) { Sample /= ubDivisor; } } -bool tSfx::isFittingMaxAmplitude(int8_t bMaxAmplitude) const +bool tSfx::isFittingMaxAmplitude(std::int8_t bMaxAmplitude) const { for(auto &Sample: m_vData) { if(Sample > bMaxAmplitude) { @@ -118,14 +118,14 @@ void tSfx::enforceEmptyFirstWord(void) { } } -void tSfx::padContents(uint8_t ubAlignment) { - uint8_t ubAddCount = m_vData.size() % ubAlignment; - for(uint8_t i = ubAddCount; i--;) { +void tSfx::padContents(std::uint8_t ubAlignment) { + std::uint8_t ubAddCount = m_vData.size() % ubAlignment; + for(std::uint8_t i = ubAddCount; i--;) { m_vData.push_back(0); } } -tSfx tSfx::splitAfter(uint32_t ulSamples) { +tSfx tSfx::splitAfter(std::uint32_t ulSamples) { tSfx Out; if(m_vData.size() <= ulSamples) { return Out; diff --git a/tools/src/common/sfx.h b/tools/src/common/sfx.h index 1df28407..7e816de9 100644 --- a/tools/src/common/sfx.h +++ b/tools/src/common/sfx.h @@ -18,24 +18,24 @@ class tSfx { bool isEmpty(void) const; - uint32_t getLength(void) const; + std::uint32_t getLength(void) const; void normalize(void); - void divideAmplitude(uint8_t ubDivisor); + void divideAmplitude(std::uint8_t ubDivisor); - bool isFittingMaxAmplitude(int8_t bMaxAmplitude) const; + bool isFittingMaxAmplitude(std::int8_t bMaxAmplitude) const; bool hasEmptyFirstWord(void) const; void enforceEmptyFirstWord(void); - void padContents(uint8_t ubAlignment); + void padContents(std::uint8_t ubAlignment); - tSfx splitAfter(uint32_t ulSamples); + tSfx splitAfter(std::uint32_t ulSamples); private: - uint32_t m_ulFreq; + std::uint32_t m_ulFreq; std::vector m_vData; }; diff --git a/tools/src/common/wav.cpp b/tools/src/common/wav.cpp index 88e608c9..8dece44f 100644 --- a/tools/src/common/wav.cpp +++ b/tools/src/common/wav.cpp @@ -8,11 +8,11 @@ #include #include "logging.h" -enum class tAudioFormat: uint16_t { +enum class tAudioFormat: std::uint16_t { PCM = 1 }; -bool tryRead(std::ifstream &Stream, char *Buffer, uint32_t ulSize) +bool tryRead(std::ifstream &Stream, char *Buffer, std::uint32_t ulSize) { // ifstream::read doesn't return meaningful return value // so here's a helper fn for it @@ -35,7 +35,7 @@ tWav::tWav(const std::string &szPath) return; } - uint32_t ulChunkSize; + std::uint32_t ulChunkSize; tryRead(StreamFile, reinterpret_cast(&ulChunkSize), sizeof(ulChunkSize)); std::string szFormat(4, '\0'); @@ -66,8 +66,8 @@ tWav::tWav(const std::string &szPath) } std::stringstream StreamSubchunk(pSubchunkFmt->m_szContents); tAudioFormat eAudioFormat; - uint16_t uwNumChannels, uwBlockAlign, uwBitsPerSample; - uint32_t ulSampleRate, ulByteRate; + std::uint16_t uwNumChannels, uwBlockAlign, uwBitsPerSample; + std::uint32_t ulSampleRate, ulByteRate; StreamSubchunk.read(reinterpret_cast(&eAudioFormat), sizeof(eAudioFormat)); StreamSubchunk.read(reinterpret_cast(&uwNumChannels), sizeof(uwNumChannels)); StreamSubchunk.read(reinterpret_cast(&ulSampleRate), sizeof(ulSampleRate)); @@ -118,12 +118,12 @@ const std::vector &tWav::getData(void) const return m_vData; } -uint32_t tWav::getSampleRate(void) const +std::uint32_t tWav::getSampleRate(void) const { return m_ulSampleRate; } -uint8_t tWav::getBitsPerSample(void) const +std::uint8_t tWav::getBitsPerSample(void) const { return m_ubBitsPerSample; } diff --git a/tools/src/common/wav.h b/tools/src/common/wav.h index 8af84976..abfa8a82 100644 --- a/tools/src/common/wav.h +++ b/tools/src/common/wav.h @@ -14,13 +14,13 @@ class tWav { tWav(const std::string &szPath); const std::vector &getData(void) const; - uint32_t getSampleRate(void) const; - uint8_t getBitsPerSample(void) const; + std::uint32_t getSampleRate(void) const; + std::uint8_t getBitsPerSample(void) const; private: struct tSubchunk { std::string m_szId = std::string(4, '\0'); - uint32_t m_ulSize; + std::uint32_t m_ulSize; std::string m_szContents; }; @@ -28,8 +28,8 @@ class tWav { std::vector m_vSubchunks; std::vector m_vData; - uint32_t m_ulSampleRate; - uint8_t m_ubBitsPerSample; + std::uint32_t m_ulSampleRate; + std::uint8_t m_ubBitsPerSample; }; #endif // _ACE_TOOLS_COMMON_WAV_H_ diff --git a/tools/src/font_conv.cpp b/tools/src/font_conv.cpp index 4fc5f68e..2dd19069 100644 --- a/tools/src/font_conv.cpp +++ b/tools/src/font_conv.cpp @@ -14,7 +14,7 @@ static const std::string s_szDefaultCharset = ( " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" ); -enum class tFontFormat: uint8_t { +enum class tFontFormat: std::uint8_t { INVALID, TTF, DIR, @@ -59,12 +59,12 @@ void printUsage(const std::string &szAppName) { print("\t-fc firstchar\tSpecify first ASCII character idx in ProMotion NG font. Default: 33."); } -static uint32_t getCharCodeFromTok(const tJson *pJson, uint16_t uwTok) { - uint32_t ulVal = 0; +static std::uint32_t getCharCodeFromTok(const tJson *pJson, std::uint16_t uwTok) { + std::uint32_t ulVal = 0; const auto &Token = pJson->pTokens[uwTok]; if(Token.type == JSMN_STRING) { // read unicode char and return its codepoint - uint32_t ulCodepoint, ulState = 0; + std::uint32_t ulCodepoint, ulState = 0; for(auto i = Token.start; i <= Token.end; ++i) { auto CharCode = *reinterpret_cast(&pJson->szData[i]); @@ -87,7 +87,7 @@ static uint32_t getCharCodeFromTok(const tJson *pJson, uint16_t uwTok) { int main(int lArgCount, const char *pArgs[]) { - const uint8_t ubMandatoryArgCnt = 2; + const std::uint8_t ubMandatoryArgCnt = 2; // Mandatory args if(lArgCount - 1 < ubMandatoryArgCnt) { nLog::error("Too few arguments, expected {}", ubMandatoryArgCnt); @@ -101,9 +101,9 @@ int main(int lArgCount, const char *pArgs[]) // Optional args' default values std::string szCharset = ""; std::string szOutPath = ""; - uint8_t ubFirstChar = 33; + std::uint8_t ubFirstChar = 33; std::string szRemapPath = ""; - int32_t lSize = -1; + std::int32_t lSize = -1; // Search for optional args for(auto ArgIndex = ubMandatoryArgCnt+1; ArgIndex < lArgCount; ++ArgIndex) { diff --git a/tools/src/mod_tool.cpp b/tools/src/mod_tool.cpp index 6d5364ea..6ccc896f 100644 --- a/tools/src/mod_tool.cpp +++ b/tools/src/mod_tool.cpp @@ -98,7 +98,7 @@ int main(int lArgCount, const char *pArgs[]) // Scan the samples to get the reorder table std::vector vReorder; // [idxOld] = idxNew for(const auto ModSample: pMod->getSamples()) { - uint8_t ubIdxNew = 0; + std::uint8_t ubIdxNew = 0; if(!ModSample.m_szName.empty()) { // Find the sample index in new samplepack auto SampleNew = std::find_if( @@ -132,7 +132,7 @@ int main(int lArgCount, const char *pArgs[]) } } - uint32_t ulIdx = 0; + std::uint32_t ulIdx = 0; for(const auto &pMod: vModsIn) { fmt::print("Writing {} to {}...\n", pMod->getSongName(), vOutNames[ulIdx]); pMod->toMod(vOutNames[ulIdx], isStripSamples); diff --git a/tools/src/palette_conv.cpp b/tools/src/palette_conv.cpp index 3580f5c8..26397c5d 100644 --- a/tools/src/palette_conv.cpp +++ b/tools/src/palette_conv.cpp @@ -22,7 +22,7 @@ void printUsage(const std::string &szAppName) { int main(int lArgCount, const char *pArgs[]) { - const uint8_t ubMandatoryArgCnt = 1; + const std::uint8_t ubMandatoryArgCnt = 1; // Mandatory args if(lArgCount - 1 < ubMandatoryArgCnt) { nLog::error("Too few arguments, expected {}", ubMandatoryArgCnt); @@ -72,7 +72,7 @@ int main(int lArgCount, const char *pArgs[]) else if(szExtOut == "png") { auto ColorCount = Palette.m_vColors.size(); tChunkyBitmap PltPreview(ColorCount * 32, 16); - for(uint8_t i = 0; i < ColorCount; ++i) { + for(std::uint8_t i = 0; i < ColorCount; ++i) { const auto &Color = Palette.m_vColors[i]; PltPreview.fillRect(i * 32, 0, 32, 16, Color); isOk = PltPreview.toPng(szPathOut); diff --git a/tools/src/tileset_conv.cpp b/tools/src/tileset_conv.cpp index c7f96150..4c3f99ee 100644 --- a/tools/src/tileset_conv.cpp +++ b/tools/src/tileset_conv.cpp @@ -11,13 +11,13 @@ #include "common/exception.h" struct tConfig { - int32_t m_lTileSize; - int32_t m_lTileHeight; + std::int32_t m_lTileSize; + std::int32_t m_lTileHeight; std::string m_szInPath; std::string m_szOutPath; std::string m_szPalettePath; bool m_isInterleaved; - int32_t m_lColumns; + std::int32_t m_lColumns; std::optional m_lColumnWidth; bool m_isVaryingHeight; bool m_isHeightOverride; @@ -67,7 +67,7 @@ tConfig::tConfig(const std::vector &vArgs) } else if(vArgs[ArgIndex] == std::string("-cw") && ArgIndex < ArgCount - 1) { ++ArgIndex; - int32_t lColumnWidth; + std::int32_t lColumnWidth; if(!nParse::toInt32(vArgs[ArgIndex], "-cw", lColumnWidth)) { throw std::runtime_error(nullptr); // error message inside parsing fn } @@ -158,12 +158,12 @@ static std::vector readTiles( throw std::runtime_error(fmt::format("Input bitmap width is not divisible by {}", Config.m_lTileSize)); } - uint16_t TileCountHoriz = In.m_uwWidth / ColumnWidth; - uint16_t TileCountVert = In.m_uwHeight / Config.m_lTileHeight; + std::uint16_t TileCountHoriz = In.m_uwWidth / ColumnWidth; + std::uint16_t TileCountVert = In.m_uwHeight / Config.m_lTileHeight; vTiles.reserve(TileCountHoriz * TileCountVert); - for(uint16_t y = 0; y < TileCountVert; ++y) { - for(uint16_t x = 0; x < TileCountHoriz; ++x) { + for(std::uint16_t y = 0; y < TileCountVert; ++y) { + for(std::uint16_t x = 0; x < TileCountHoriz; ++x) { tChunkyBitmap Tile(Config.m_lTileSize, Config.m_lTileHeight); In.copyRect( x * ColumnWidth, y * Config.m_lTileHeight, Tile, 0, 0, @@ -174,8 +174,8 @@ static std::vector readTiles( } } else if(nFs::isDir(Config.m_szInPath)) { - int16_t wLastFull = -1; - for(uint16_t i = 0; i < 256; ++i) { + std::int16_t wLastFull = -1; + for(std::uint16_t i = 0; i < 256; ++i) { auto Tile = tChunkyBitmap::fromPng(fmt::format("{}/{}.png", Config.m_szInPath, i)); if(Tile.m_uwHeight != 0) { wLastFull = i; @@ -219,7 +219,7 @@ static void saveTiles( Bg ); - for(uint16_t i = 0; i < TileCount; ++i) { + for(std::uint16_t i = 0; i < TileCount; ++i) { auto &Tile = vTiles.at(i); if(Tile.m_uwHeight != 0) { Tile.copyRect( @@ -232,7 +232,7 @@ static void saveTiles( } } else { - uint16_t uwTilesetHeight = 0; + std::uint16_t uwTilesetHeight = 0; if(Config.m_isVaryingHeight) { bool hasEmptyTile = false; for(const auto &Tile: vTiles) { @@ -250,7 +250,7 @@ static void saveTiles( ColumnWidth, uwTilesetHeight, Bg ); - uint16_t uwOffsY = 0; + std::uint16_t uwOffsY = 0; for(const auto &Tile: vTiles) { Tile.copyRect( 0, 0, Out.value(), 0, uwOffsY, Tile.m_uwWidth, Tile.m_uwHeight @@ -278,7 +278,7 @@ static void saveTiles( else if(szOutExt == "") { // Tile directory nFs::dirCreate(Config.m_szOutPath); - for(uint16_t i = 0; i < TileCount; ++i) { + for(std::uint16_t i = 0; i < TileCount; ++i) { auto &Tile = vTiles.at(i); if(Tile.m_uwHeight != 0) { std::string szTilePath = fmt::format("{}/{}.png", Config.m_szOutPath, i); From 3f07d757c790d3eb195686cc04253b40932e1d1f Mon Sep 17 00:00:00 2001 From: KaiN Date: Sun, 11 Feb 2024 19:26:14 +0100 Subject: [PATCH 23/33] ptplayer: fix duplicate pointer for current mod, cleanups --- src/ace/managers/ptplayer.c | 65 +++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/src/ace/managers/ptplayer.c b/src/ace/managers/ptplayer.c index 77e986fc..8bc389e5 100644 --- a/src/ace/managers/ptplayer.c +++ b/src/ace/managers/ptplayer.c @@ -61,7 +61,7 @@ #define MOD_NOTES_PER_ROW 4 #define MOD_BYTES_PER_NOTE 4 // Length of single pattern. -#define MOD_PATTERN_LENGTH (MOD_ROWS_IN_PATTERN * MOD_NOTES_PER_ROW * MOD_BYTES_PER_NOTE) +#define MOD_PATTERN_BYTE_SIZE (MOD_ROWS_IN_PATTERN * MOD_NOTES_PER_ROW * MOD_BYTES_PER_NOTE) // Size of period table. #define MOD_PERIOD_TABLE_LENGTH 36 @@ -974,7 +974,7 @@ static volatile UBYTE s_isNextTimerBSetRep; static tChannelStatus mt_chan[4]; static UWORD *mt_SampleStarts[31]; ///< Start address of each sample -static tPtplayerMod *mt_mod; ///< Currently played MOD. +static tPtplayerMod *s_pCurrentMod; ///< Currently played MOD. static ULONG mt_timerval; ///< Base interrupt frequency of CIA-B timer A used to advance the song. Equals 125*50Hz. static const UBYTE * mt_MasterVolTab; static UWORD mt_PatternPos; @@ -999,8 +999,6 @@ static UBYTE mt_SilCntValid; */ static UWORD mt_dmaon = 0; -static tPtplayerMod *s_pModCurr; - static void clearAudioDone(void) { #if defined(PTPLAYER_USE_AUDIO_INT_HANDLERS) // When channel is idle, original ptplayer loops playback of the first word @@ -1132,7 +1130,7 @@ static void ptSongStep(void) { UBYTE ubNextPos = (mt_SongPos + 1) & 0x7F; // End of song reached? - if(ubNextPos >= mt_mod->ubArrangementLength) { + if(ubNextPos >= s_pCurrentMod->ubArrangementLength) { ubNextPos = 0; if(!s_isRepeat) { ptplayerEnableMusic(0); @@ -1275,7 +1273,7 @@ static void mt_playvoice( --uwSampleIdx; // Read length, volume and repeat from sample info table UWORD *pSampleStart = mt_SampleStarts[uwSampleIdx]; - tPtplayerSampleHeader *pSampleDef = &mt_mod->pSampleHeaders[uwSampleIdx]; + tPtplayerSampleHeader *pSampleDef = &s_pCurrentMod->pSampleHeaders[uwSampleIdx]; UWORD uwSampleLength = pSampleDef->uwLength; if(!uwSampleLength) { // Use the first two bytes from the first sample for empty samples @@ -1571,8 +1569,8 @@ static void mt_music(void) { mt_Counter = 0; if(mt_PattDelTime2 <= 0) { // determine pointer to current pattern line - UBYTE *pPatternData = mt_mod->pPatterns; - UBYTE *pArrangement = mt_mod->pArrangement; + UBYTE *pPatternData = s_pCurrentMod->pPatterns; + UBYTE *pArrangement = s_pCurrentMod->pArrangement; UBYTE ubPatternIdx = pArrangement[mt_SongPos]; UBYTE *pCurrentPattern = &pPatternData[ubPatternIdx * 1024]; tModVoice *pLineVoices = (tModVoice*)&pCurrentPattern[mt_PatternPos]; @@ -1660,7 +1658,7 @@ void ptplayerStop(void) { } resetChannel(&mt_chan[i]); } - s_pModCurr = 0; + s_pCurrentMod = 0; // Free the channels taken by SFX. // Typically they would release themselves but turning off DMA prevents this. @@ -1694,6 +1692,7 @@ static void mt_reset(void) { mt_Speed = 6; mt_Counter = 0; mt_PatternPos = 0; + mt_SongPos = 0; mt_PattDelTime = 0; mt_PattDelTime2 = 0; mt_PBreakPos = 0; @@ -1762,7 +1761,7 @@ void ptplayerCreate(UBYTE isPal) { s_isRepeat = 1; s_cbSongEnd = 0; s_cbOnE8 = 0; - s_pModCurr = 0; + s_pCurrentMod = 0; ptplayerEnableMusic(0); #if defined(PTPLAYER_USE_AUDIO_INT_HANDLERS) for(UBYTE i = sizeof(s_pAudioChannelPendingDisable); i--;) { @@ -1814,24 +1813,23 @@ void ptplayerLoadMod( tPtplayerMod *pMod, tPtplayerSamplePack *pSamples, UWORD uwInitialSongPos ) { logBlockBegin( - "ptplayerInit(pMod: %p, pSamples: %p, uwInitialSongPos: %hu)", + "ptplayerLoadMod(pMod: %p, pSamples: %p, uwInitialSongPos: %hu)", pMod, pSamples, uwInitialSongPos ); // Initialize new module. // Reset speed to 6, tempo to 125 and start at given song position. // Master volume is at 64 (maximum). - mt_mod = pMod; + s_pCurrentMod = pMod; logWrite( "Song name: '%s', arrangement length: %hhu, end pos: %hhu\n", - mt_mod->szSongName, mt_mod->ubArrangementLength, mt_mod->ubSongEndPos + s_pCurrentMod->szSongName, s_pCurrentMod->ubArrangementLength, s_pCurrentMod->ubSongEndPos ); // set initial song position if(uwInitialSongPos >= 950) { uwInitialSongPos = 0; } - mt_SongPos = uwInitialSongPos; // sample data location is given? UWORD *pSampleData = pSamples ? pSamples->pData : pMod->pSamples; @@ -1841,11 +1839,11 @@ void ptplayerLoadMod( ULONG ulOffs = 0; for(UBYTE i = 0; i < 31; ++i) { mt_SampleStarts[i] = &pSampleData[ulOffs]; - if(mt_mod->pSampleHeaders[i].uwLength > 0) { + if(s_pCurrentMod->pSampleHeaders[i].uwLength > 0) { logWrite( "Sample %hhu name: '%.*s', word length: %hu, start: %p, repeat offs: %hu, repeat len:%hu\n", - i, 22, mt_mod->pSampleHeaders[i].szName, mt_mod->pSampleHeaders[i].uwLength, - mt_SampleStarts[i], mt_mod->pSampleHeaders[i].uwRepeatOffs, mt_mod->pSampleHeaders[i].uwRepeatLength + i, 22, s_pCurrentMod->pSampleHeaders[i].szName, s_pCurrentMod->pSampleHeaders[i].uwLength, + mt_SampleStarts[i], s_pCurrentMod->pSampleHeaders[i].uwRepeatOffs, s_pCurrentMod->pSampleHeaders[i].uwRepeatLength ); // Make sure each sample starts with two 0-bytes @@ -1853,12 +1851,15 @@ void ptplayerLoadMod( } // Go to next sample - ulOffs += mt_mod->pSampleHeaders[i].uwLength; + ulOffs += s_pCurrentMod->pSampleHeaders[i].uwLength; }; mt_reset(); - s_pModCurr = pMod; - logBlockEnd("ptplayerInit()"); + // Fix what mt_reset has broken + s_pCurrentMod = pMod; + mt_SongPos = uwInitialSongPos; + + logBlockEnd("ptplayerLoadMod()"); } void ptplayerSetMusicChannelMask(UBYTE ChannelMask) { @@ -2733,8 +2734,8 @@ void ptplayerProcess(void) { } const tModVoice *ptplayerGetCurrentVoices(void) { - UBYTE *pPatternData = mt_mod->pPatterns; - UBYTE *pArrangement = mt_mod->pArrangement; + UBYTE *pPatternData = s_pCurrentMod->pPatterns; + UBYTE *pArrangement = s_pCurrentMod->pArrangement; UBYTE ubPatternIdx = pArrangement[mt_SongPos]; UBYTE *pCurrentPattern = &pPatternData[ubPatternIdx * 1024]; tModVoice *pLineVoices = (tModVoice*)&pCurrentPattern[mt_PatternPos]; @@ -2760,7 +2761,7 @@ void ptplayerReserveChannelsForMusic(UBYTE ubChannelCount) { } void ptplayerSetSampleVolume(UBYTE ubSampleIndex, UBYTE ubVolume) { - mt_mod->pSampleHeaders[ubSampleIndex].ubVolume = ubVolume; + s_pCurrentMod->pSampleHeaders[ubSampleIndex].ubVolume = ubVolume; } tPtplayerMod *ptplayerModCreate(const char *szPath) { @@ -2799,7 +2800,7 @@ tPtplayerMod *ptplayerModCreate(const char *szPath) { logWrite("Pattern count: %hhu\n", ubPatternCount); // Read pattern data - pMod->ulPatternsSize = (ubPatternCount * MOD_PATTERN_LENGTH); + pMod->ulPatternsSize = (ubPatternCount * MOD_PATTERN_BYTE_SIZE); pMod->pPatterns = memAllocFast(pMod->ulPatternsSize); if(!pMod->pPatterns) { logWrite("ERR: Couldn't allocate memory for pattern data!"); @@ -2838,7 +2839,7 @@ tPtplayerMod *ptplayerModCreate(const char *szPath) { } void ptplayerModDestroy(tPtplayerMod *pMod) { - if(s_pModCurr == pMod) { + if(s_pCurrentMod == pMod) { ptplayerStop(); } memFree(pMod->pPatterns, pMod->ulPatternsSize); @@ -3005,7 +3006,7 @@ void ptplayerSfxPlay( } // Did we already calculate the n_freecnt values for all channels? - if(!mt_SilCntValid && mt_mod) { + if(!mt_SilCntValid && s_pCurrentMod) { // Look at the next 8 pattern steps to find the longest sequence // of silence (no new note or instrument). UBYTE ubSteps = 8; @@ -3023,15 +3024,15 @@ void ptplayerSfxPlay( mt_chan[3].n_freecnt = 0; // get pattern pointer - UBYTE *pPatterns = mt_mod->pPatterns; + UBYTE *pPatterns = s_pCurrentMod->pPatterns; UBYTE ubSongPos = mt_SongPos; UWORD uwPatternPos = mt_PatternPos; UBYTE isEnd = 0; UBYTE *pPatternStart = &pPatterns[ - mt_mod->pArrangement[ubSongPos] * MOD_PATTERN_LENGTH + s_pCurrentMod->pArrangement[ubSongPos] * MOD_PATTERN_BYTE_SIZE ]; - tModVoice *pPatternEnd = (tModVoice*)(pPatternStart + MOD_PATTERN_LENGTH); + tModVoice *pPatternEnd = (tModVoice*)(pPatternStart + MOD_PATTERN_BYTE_SIZE); tModVoice *pPatternPos = (tModVoice*)(pPatternStart + uwPatternPos); do { UBYTE ubFreeChannelCnt = 4; @@ -3057,13 +3058,13 @@ void ptplayerSfxPlay( if(!isEnd && pPatternPos >= pPatternEnd) { uwPatternPos = 0; ubSongPos = (mt_SongPos + 1) & 127; - if(ubSongPos >= mt_mod->ubArrangementLength) { + if(ubSongPos >= s_pCurrentMod->ubArrangementLength) { ubSongPos = 0; } pPatternStart = &pPatterns[ - mt_mod->pArrangement[ubSongPos] * MOD_PATTERN_LENGTH + s_pCurrentMod->pArrangement[ubSongPos] * MOD_PATTERN_BYTE_SIZE ]; - pPatternEnd = (tModVoice*)(pPatternStart + MOD_PATTERN_LENGTH); + pPatternEnd = (tModVoice*)(pPatternStart + MOD_PATTERN_BYTE_SIZE); pPatternPos = (tModVoice*)pPatternStart; } } while(!isEnd); From 7b7d47f778a6703efb934c758adfe6ddf8a32057 Mon Sep 17 00:00:00 2001 From: KaiN Date: Tue, 16 Apr 2024 15:34:57 +0200 Subject: [PATCH 24/33] simplebuffer: calc bpl offs/shift only when they're actually used --- src/ace/managers/viewport/simplebuffer.c | 38 ++++++++++++++---------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/ace/managers/viewport/simplebuffer.c b/src/ace/managers/viewport/simplebuffer.c index d7efe9a2..d057552e 100644 --- a/src/ace/managers/viewport/simplebuffer.c +++ b/src/ace/managers/viewport/simplebuffer.c @@ -118,6 +118,24 @@ static void simpleBufferSetBack(tSimpleBufferManager *pManager, tBitMap *pBack) pManager->pBack = pBack; } +static UWORD simpleBufferCalcBplOffsAndShift(tSimpleBufferManager *pManager, ULONG *pBplOffs) { + // Calculate X movement: bitplane shift, starting word to fetch + UWORD uwShift; + if(pManager->ubFlags & SIMPLEBUFFER_FLAG_X_SCROLLABLE) { + uwShift = (16 - (pManager->pCamera->uPos.uwX & 0xF)) & 0xF; // Bitplane shift - single + uwShift = (uwShift << 4) | uwShift; // Bitplane shift - PF1 | PF2 + *pBplOffs = ((pManager->pCamera->uPos.uwX - 1) >> 4) << 1; // Must be ULONG! + } + else { + uwShift = 0; + *pBplOffs = (pManager->pCamera->uPos.uwX >> 4) << 1; + } + + // Calculate Y movement + *pBplOffs += pManager->pBack->BytesPerRow * pManager->pCamera->uPos.uwY; + return uwShift; +} + void simpleBufferSetFront(tSimpleBufferManager *pManager, tBitMap *pFront) { logBlockBegin( "simpleBufferSetFront(pManager: %p, pFront: %p)", @@ -274,22 +292,6 @@ void simpleBufferProcess(tSimpleBufferManager *pManager) { const tCameraManager *pCamera = pManager->pCamera; tCopList *pCopList = pManager->sCommon.pVPort->pView->pCopList; - // Calculate X movement: bitplane shift, starting word to fetch - UWORD uwShift; - ULONG ulBplOffs; - if(pManager->ubFlags & SIMPLEBUFFER_FLAG_X_SCROLLABLE) { - uwShift = (16 - (pCamera->uPos.uwX & 0xF)) & 0xF; // Bitplane shift - single - uwShift = (uwShift << 4) | uwShift; // Bitplane shift - PF1 | PF2 - ulBplOffs = ((pCamera->uPos.uwX - 1) >> 4) << 1; // Must be ULONG! - } - else { - uwShift = 0; - ulBplOffs = (pCamera->uPos.uwX >> 4) << 1; - } - - // Calculate Y movement - ulBplOffs += pManager->pBack->BytesPerRow * pCamera->uPos.uwY; - // Copperlist - regen bitplane ptrs, update shift // TODO could be unified by using copSetMove in copBlock if((pManager->ubFlags & SIMPLEBUFFER_FLAG_COPLIST_RAW)) { @@ -299,6 +301,8 @@ void simpleBufferProcess(tSimpleBufferManager *pManager) { pManager->ubDirtyCounter = 2; } if(pManager->ubDirtyCounter) { + ULONG ulBplOffs; + UWORD uwShift = simpleBufferCalcBplOffsAndShift(pManager, &ulBplOffs); tCopCmd *pCmdList = &pCopList->pBackBfr->pList[pManager->uwCopperOffset]; copSetMoveVal(&pCmdList[5].sMove, uwShift); updateBitplanePtrs(&pCmdList[6], pManager->pBack, ulBplOffs); @@ -309,6 +313,8 @@ void simpleBufferProcess(tSimpleBufferManager *pManager) { // In double buffering, we can't really check for camera being moved, since // copBlock needs to change its bitplane pointers value each frame and // copperlist needs refreshing. + ULONG ulBplOffs; + UWORD uwShift = simpleBufferCalcBplOffsAndShift(pManager, &ulBplOffs); pManager->pCopBlock->uwCurrCount = 4; // Rewind to shift cmd pos copMove(pCopList, pManager->pCopBlock, &g_pCustom->bplcon1, uwShift); for(UBYTE i = 0; i < pManager->pBack->Depth; ++i) { From f30b8fe9caaebce6c5642d35aa9643cc3c520d43 Mon Sep 17 00:00:00 2001 From: KaiN Date: Tue, 16 Apr 2024 17:39:42 +0200 Subject: [PATCH 25/33] add paletteSave() --- include/ace/utils/palette.h | 8 ++++++++ src/ace/utils/palette.c | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/include/ace/utils/palette.h b/include/ace/utils/palette.h index 1e6059b9..1690c968 100644 --- a/include/ace/utils/palette.h +++ b/include/ace/utils/palette.h @@ -24,6 +24,14 @@ extern "C" { */ void paletteLoad(const char *szFileName, UWORD *pPalette, UBYTE ubMaxLength); +/** + * @brief Saves given palette into .plt file. + * @param pPalette Palette to save. + * @param ubColorCnt Number of colors in palette. + * @param szPath Destination path. + */ +void paletteSave(UWORD *pPalette, UBYTE ubColorCnt, char *szPath); + /** * @brief Loads palette from supplied .plt stored in memory to given address. * @param pData Palette source pointer. diff --git a/src/ace/utils/palette.c b/src/ace/utils/palette.c index db3b5d8d..3f2fb4b9 100644 --- a/src/ace/utils/palette.c +++ b/src/ace/utils/palette.c @@ -107,3 +107,27 @@ void paletteDump(UWORD *pPalette, UBYTE ubColorCnt, char *szPath) { bitmapSaveBmp(pBm, pPalette, szPath); bitmapDestroy(pBm); } + +void paletteSave(UWORD *pPalette, UBYTE ubColorCnt, char *szPath) { + tFile *pFile; + UBYTE ubPaletteLength; + + logBlockBegin( + "paletteSave(pPalette: %p, ubColorCnt: %hu, szPath: '%s')", + pPalette, ubColorCnt, szPath + ); + + pFile = fileOpen(szPath, "wb"); + if(!pFile) { + logWrite("ERR: Can't write file!\n"); + logBlockEnd("paletteSave()"); + return; + } + else { + fileWrite(pFile, &ubColorCnt, sizeof(UBYTE)); + fileWrite(pFile, pPalette, sizeof(UWORD) * ubColorCnt); + fileClose(pFile); + } + + logBlockEnd("paletteSave()"); +} From f60f6f8ca4339493d064070d511ff5804b9fba45 Mon Sep 17 00:00:00 2001 From: KaiN Date: Sun, 21 Apr 2024 10:51:41 +0200 Subject: [PATCH 26/33] bitmap_transform: specify rotation center point --- tools/src/bitmap_transform.cpp | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/tools/src/bitmap_transform.cpp b/tools/src/bitmap_transform.cpp index 3ee148f4..0867ba0a 100644 --- a/tools/src/bitmap_transform.cpp +++ b/tools/src/bitmap_transform.cpp @@ -23,12 +23,17 @@ class tOpExtract: public tOp { class tOpRotate: public tOp { public: - tOpRotate(double dDeg, tRgb Bg); + tOpRotate( + double dDeg, tRgb Bg, + double dCenterX, double dCenterY + ); virtual tChunkyBitmap execute(const tChunkyBitmap &Src); virtual std::string toString(void); private: double m_dDeg; tRgb m_Bg; + double m_dCenterX; + double m_dCenterY; }; class tOpMirror: public tOp { @@ -50,7 +55,7 @@ void printUsage(const std::string &szAppName) print("Usage:\n\t{} in.png out.png [transforms]\n", szAppName); print("\nAvailable transforms, done in passed order:\n"); print("\t-extract x y width height\tExtract rectangle at x,y of size width*height.\n"); - print("\t-rotate deg bgcolor \tRotate clockwise by given number of degrees. Can be negative.\n"); + print("\t-rotate deg bgcolor cx cy\tRotate clockwise by given number of degrees around cx,cy. Values can be floats/negative.\n"); print("\t-mirror x|y \tMirror image along x or y axis.\n"); print("\nCurrently only PNG is supported, sorry!\n"); } @@ -102,7 +107,7 @@ int main(int lArgCount, char *pArgs[]) } } else if(szOp == "-rotate") { - if(ArgIndex + 2 >= lArgCount) { + if(ArgIndex + 4 >= lArgCount) { nLog::error( "Too few args for {} - first arg at pos {}, arg count: {}", szOp, ArgIndex + 1, lArgCount @@ -112,10 +117,12 @@ int main(int lArgCount, char *pArgs[]) try { auto Deg = std::stod(pArgs[++ArgIndex]); auto Bg = tRgb(pArgs[++ArgIndex]); - vOps.push_back(std::make_unique(Deg, Bg)); + auto CenterX = std::stod(pArgs[++ArgIndex]); + auto CenterY = std::stod(pArgs[++ArgIndex]); + vOps.push_back(std::make_unique(Deg, Bg, CenterX, CenterY)); } catch(std::exception Ex) { - nLog::error("Couldn't parse rotate degrees: '{}'", pArgs[ArgIndex]); + nLog::error("Couldn't parse arg: '{}'", pArgs[ArgIndex]); return EXIT_FAILURE; } } @@ -222,16 +229,17 @@ std::string tOpMirror::toString(void) //---------------------------------------------------------------------OP ROTATE -tOpRotate::tOpRotate(double dDeg, tRgb Bg): - m_dDeg(dDeg), m_Bg(Bg) +tOpRotate::tOpRotate( + double dDeg, tRgb Bg, + double dCenterX, double dCenterY +): + m_dDeg(dDeg), m_Bg(Bg), m_dCenterX(dCenterX), m_dCenterY(dCenterY) { // Nothing here for now } tChunkyBitmap tOpRotate::execute(const tChunkyBitmap &Source) { tChunkyBitmap Dst(Source.m_uwWidth, Source.m_uwHeight); - auto CenterX = (Source.m_uwWidth - 1) / 2.0; - auto CenterY = (Source.m_uwHeight - 1) / 2.0; auto Rad = (m_dDeg * 2 * M_PI) / 360; auto CalcCos = cos(Rad); @@ -239,11 +247,11 @@ tChunkyBitmap tOpRotate::execute(const tChunkyBitmap &Source) { // For each of new bitmap's pixel sample color from rotated source x,y for(auto Y = 0; Y < Dst.m_uwHeight; ++Y) { - auto Dy = Y - CenterY; + auto Dy = Y - m_dCenterY; for(auto X = 0; X < Dst.m_uwWidth; ++X) { - auto Dx = X - CenterX; - auto U = uint16_t(round(CalcCos * Dx + CalcSin * Dy + (CenterX))); - auto V = uint16_t(round(-CalcSin * Dx + CalcCos * Dy + (CenterY))); + auto Dx = X - m_dCenterX; + auto U = uint16_t(round(CalcCos * Dx + CalcSin * Dy + (m_dCenterX))); + auto V = uint16_t(round(-CalcSin * Dx + CalcCos * Dy + (m_dCenterY))); if(U < 0 || V < 0 || U >= Dst.m_uwWidth || V >= Dst.m_uwHeight) { // fmt::print("can't sample for {:2d},{:2d} from {:.1f},{:.1f}\n", X, Y, U, V); From 9080ed1f8e4b3c8e88d102d00b4bf17eb30389a9 Mon Sep 17 00:00:00 2001 From: KaiN Date: Tue, 14 Jan 2025 17:53:54 +0100 Subject: [PATCH 27/33] remove debug print --- tools/src/tileset_conv.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/src/tileset_conv.cpp b/tools/src/tileset_conv.cpp index 4c3f99ee..9a705cdc 100644 --- a/tools/src/tileset_conv.cpp +++ b/tools/src/tileset_conv.cpp @@ -49,7 +49,6 @@ tConfig::tConfig(const std::vector &vArgs) m_isInterleaved = true; } else if(vArgs[ArgIndex] == std::string("-vh")) { - fmt::print("VARIABLE HEIGHT ON\n\n\n\n"); m_isVaryingHeight = true; } else if(vArgs[ArgIndex] == std::string("-plt") && ArgIndex < ArgCount - 1) { From 1198cbbb109e993009fdfd3f690ad6e61e179b8c Mon Sep 17 00:00:00 2001 From: KaiN Date: Sat, 18 Jan 2025 19:15:11 +0100 Subject: [PATCH 28/33] add debug print for bobCalcFrameAddress() going out of bounds --- src/ace/managers/bob.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ace/managers/bob.c b/src/ace/managers/bob.c index 1f424fbc..8c6f6891 100644 --- a/src/ace/managers/bob.c +++ b/src/ace/managers/bob.c @@ -223,6 +223,9 @@ void bobSetHeight(tBob *pBob, UWORD uwHeight) } UBYTE *bobCalcFrameAddress(tBitMap *pBitmap, UWORD uwOffsetY) { + if(uwOffsetY >= pBitmap->Rows) { + logWrite("ERR: bobCalcFrameAddress() OffsY %hu > bitmap height: %hu", uwOffsetY, pBitmap->Rows); + } return &pBitmap->Planes[0][pBitmap->BytesPerRow * uwOffsetY]; } From cfb5c8f5d3e0d3772186981ea5a275d91c32549b Mon Sep 17 00:00:00 2001 From: KaiN Date: Sun, 19 Jan 2025 21:20:03 +0100 Subject: [PATCH 29/33] add logs for bobInit() to make catching non-intentional bob inits after allocing buffers easier --- src/ace/managers/bob.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/ace/managers/bob.c b/src/ace/managers/bob.c index 59ce70df..f46435a6 100644 --- a/src/ace/managers/bob.c +++ b/src/ace/managers/bob.c @@ -208,6 +208,10 @@ void bobInit( tBob *pBob, UWORD uwWidth, UWORD uwHeight, UBYTE isUndrawRequired, UBYTE *pFrameData, UBYTE *pMaskData, UWORD uwX, UWORD uwY ) { + logBlockBegin( + "bobInit(pBob: %p, uwWidth: %hu, uwHeight: %hu, isUndrawRequired: %hhu, pFrameData: %p, pMaskData: %p, uwX: %hu, uwY: %hu)", + pBob, uwWidth, uwHeight, isUndrawRequired, pFrameData, pMaskData, uwX, uwY + ); #if defined(ACE_DEBUG) pBob->_uwOriginalWidth = uwWidth; pBob->_uwOriginalHeight = uwHeight; @@ -238,7 +242,7 @@ void bobInit( } #endif ++s_ubMaxBobCount; - // logWrite("Added bob, now max: %hhu\n", s_ubMaxBobCount); + logBlockEnd("bobInit()"); } void bobSetFrame(tBob *pBob, UBYTE *pFrameData, UBYTE *pMaskData) { From 82fcd276d4d54eaa4cd1afa2bcf7d081f17646d6 Mon Sep 17 00:00:00 2001 From: KaiN Date: Sun, 19 Jan 2025 21:20:33 +0100 Subject: [PATCH 30/33] make diskFileExists() not print the error if file doesn't exist --- src/ace/utils/disk_file.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ace/utils/disk_file.c b/src/ace/utils/disk_file.c index 81de2b89..fb1de5ab 100644 --- a/src/ace/utils/disk_file.c +++ b/src/ace/utils/disk_file.c @@ -156,10 +156,10 @@ UBYTE diskFileExists(const char *szPath) { systemUse(); fileAccessEnable(); UBYTE isExisting = 0; - tFile *pFile = diskFileOpen(szPath, "r"); - if(pFile) { + FILE *pFileHandle = fopen(szPath, "r"); + if(pFileHandle) { isExisting = 1; - fileClose(pFile); + fclose(pFileHandle); } fileAccessDisable(); systemUnuse(); From 51a1ecbdd9b2f9c694f15279a9d6b071d478d2a8 Mon Sep 17 00:00:00 2001 From: KaiN Date: Mon, 20 Jan 2025 19:25:50 +0100 Subject: [PATCH 31/33] change order of DisownBlitter() in systemReleaseBlitterToOs() to something that makes more sense, I think --- src/ace/managers/system.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ace/managers/system.c b/src/ace/managers/system.c index 59b3ab00..01ae8f97 100644 --- a/src/ace/managers/system.c +++ b/src/ace/managers/system.c @@ -1073,8 +1073,8 @@ void systemGetBlitterFromOs(void) { void systemReleaseBlitterToOs(void) { if (!s_wSystemBlitterUses){ - DisownBlitter(); WaitBlit(); + DisownBlitter(); } ++s_wSystemBlitterUses; } From 736ca93e6edaf45ad9f23e8eb4599b45691335b9 Mon Sep 17 00:00:00 2001 From: KaiN Date: Mon, 20 Jan 2025 19:26:13 +0100 Subject: [PATCH 32/33] fix systemGetBlitterFromOs() updating s_wSystemBlitterUses too early --- src/ace/managers/system.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ace/managers/system.c b/src/ace/managers/system.c index 01ae8f97..4585a98a 100644 --- a/src/ace/managers/system.c +++ b/src/ace/managers/system.c @@ -1055,13 +1055,15 @@ UBYTE systemIsUsed(void) { } void systemGetBlitterFromOs(void) { - --s_wSystemBlitterUses; - if(!s_wSystemBlitterUses) { + if(s_wSystemBlitterUses == 1) { // Make OS finish its pending operations before it loses blitter! systemFlushIo(); OwnBlitter(); WaitBlit(); } + // This must be decremented after OwnBlitter() so that systemBlitterIsUsed() + // checked in interrupt won't return 0 during OS blitter op still in progress. + --s_wSystemBlitterUses; #if defined(ACE_DEBUG) if(s_wSystemBlitterUses < 0) { From a9fdc159a2def3ca6f0a8291432accfa0fa64461 Mon Sep 17 00:00:00 2001 From: KaiN Date: Sun, 26 Jan 2025 18:41:04 +0100 Subject: [PATCH 33/33] tileBufferResetRedrawState() - set better x/y positions in margin state --- src/ace/managers/viewport/tilebuffer.c | 45 +++++++++++++++++--------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/src/ace/managers/viewport/tilebuffer.c b/src/ace/managers/viewport/tilebuffer.c index 1b3336b3..cff07be5 100644 --- a/src/ace/managers/viewport/tilebuffer.c +++ b/src/ace/managers/viewport/tilebuffer.c @@ -24,19 +24,31 @@ static UBYTE shiftFromPowerOfTwo(UWORD uwPot) { #define BLIT_WORDS_NON_INTERLEAVED_BIT (0b1 << 5) // tileSize is UBYTE, top bit of width is definitely free -static void tileBufferResetRedrawState(tRedrawState *pState) { +static void tileBufferResetRedrawState( + tRedrawState *pState, WORD wStartX, WORD wEndX, WORD wStartY, WORD wEndY +) { #if defined(ACE_SCROLLBUFFER_ENABLE_SCROLL_X) memset(&pState->sMarginL, 0, sizeof(tMarginState)); memset(&pState->sMarginR, 0, sizeof(tMarginState)); + pState->sMarginL.wTilePos = wStartX; + pState->sMarginR.wTilePos = wEndX; pState->pMarginX = &pState->sMarginR; pState->pMarginOppositeX = &pState->sMarginL; +#else + (void)wStartX; + (void)wEndX; #endif #if defined(ACE_SCROLLBUFFER_ENABLE_SCROLL_Y) memset(&pState->sMarginU, 0, sizeof(tMarginState)); memset(&pState->sMarginD, 0, sizeof(tMarginState)); + pState->sMarginU.wTilePos = wStartY; + pState->sMarginD.wTilePos = wEndY; pState->pMarginY = &pState->sMarginD; pState->pMarginOppositeY = &pState->sMarginU; +#else + (void)wStartY; + (void)wEndY; #endif pState->ubPendingCount = 0; @@ -295,9 +307,10 @@ void tileBufferReset( pManager->ubMarginXLength, pManager->ubMarginYLength ); - // Reset margin redraw structs - tileBufferResetRedrawState(&pManager->pRedrawStates[0]); - tileBufferResetRedrawState(&pManager->pRedrawStates[1]); + // Reset margin redraw structs - margin positions will be set correctly + // by tileBufferRedrawAll() + tileBufferResetRedrawState(&pManager->pRedrawStates[0], 0, 0, 0, 0); + tileBufferResetRedrawState(&pManager->pRedrawStates[1], 0, 0, 0, 0); logBlockEnd("tileBufferReset()"); } @@ -400,16 +413,14 @@ static inline void tileBufferContinueTileDraw( FN_HOTSPOT void tileBufferProcess(tTileBufferManager *pManager) { #if defined(ACE_SCROLLBUFFER_ENABLE_SCROLL_X) || defined(ACE_SCROLLBUFFER_ENABLE_SCROLL_Y) - WORD wMarginXPos, wMarginYPos; - UWORD uwTileOffsX, uwTileOffsY; tRedrawState *pState = &pManager->pRedrawStates[pManager->ubStateIdx]; - UBYTE ubTileSize = pManager->ubTileSize; UBYTE ubTileShift = pManager->ubTileShift; #endif #if defined(ACE_SCROLLBUFFER_ENABLE_SCROLL_X) // X movement + WORD wMarginXPos; WORD wDeltaX = cameraGetDeltaX(pManager->pCamera); if (wDeltaX) { // determine movement direction - right or left @@ -429,10 +440,10 @@ void tileBufferProcess(tTileBufferManager *pManager) { if (wMarginXPos != pState->pMarginX->wTilePos) { // Not finished redrawing all column tiles? if(pState->pMarginX->wTileCurr < pState->pMarginX->wTileEnd) { - uwTileOffsY = SCROLLBUFFER_HEIGHT_MODULO( + UWORD uwTileOffsY = SCROLLBUFFER_HEIGHT_MODULO( pState->pMarginX->wTileCurr << ubTileShift, pManager->uwMarginedHeight ); - uwTileOffsX = (pState->pMarginX->wTilePos << ubTileShift); + UWORD uwTileOffsX = (pState->pMarginX->wTilePos << ubTileShift); // Redraw remaining tiles UWORD uwBltsize = tileBufferSetupTileDraw(pManager); UWORD uwTileCurr = pState->pMarginX->wTileCurr; @@ -523,6 +534,7 @@ void tileBufferProcess(tTileBufferManager *pManager) { #if defined(ACE_SCROLLBUFFER_ENABLE_SCROLL_Y) // Y movement + WORD wMarginYPos; WORD wDeltaY = cameraGetDeltaY(pManager->pCamera); if (wDeltaY) { // determine redraw row - down or up @@ -542,10 +554,10 @@ void tileBufferProcess(tTileBufferManager *pManager) { if (wMarginYPos != pState->pMarginY->wTilePos) { // Not finished redrawing all row tiles? if(pState->pMarginY->wTileCurr < pState->pMarginY->wTileEnd) { - uwTileOffsY = SCROLLBUFFER_HEIGHT_MODULO( + UWORD uwTileOffsY = SCROLLBUFFER_HEIGHT_MODULO( pState->pMarginY->wTilePos << ubTileShift, pManager->uwMarginedHeight ); - uwTileOffsX = (pState->pMarginY->wTileCurr << ubTileShift); + UWORD uwTileOffsX = (pState->pMarginY->wTileCurr << ubTileShift); // Redraw remaining tiles UWORD uwBltsize = tileBufferSetupTileDraw(pManager); UWORD uwTileCurr = pState->pMarginY->wTileCurr; @@ -617,10 +629,6 @@ void tileBufferProcess(tTileBufferManager *pManager) { void tileBufferRedrawAll(tTileBufferManager *pManager) { logBlockBegin("tileBufferRedrawAll(pManager: %p)", pManager); - // Reset margin redraw structs as we're redrawing everything anyway - tileBufferResetRedrawState(&pManager->pRedrawStates[0]); - tileBufferResetRedrawState(&pManager->pRedrawStates[1]); - UBYTE ubTileSize = pManager->ubTileSize; UBYTE ubTileShift = pManager->ubTileShift; @@ -635,6 +643,13 @@ void tileBufferRedrawAll(tTileBufferManager *pManager) { pManager->uTileBounds.uwY, wStartY + (pManager->uwMarginedHeight >> ubTileShift) ); + // Reset margin redraw structs as we're redrawing everything anyway + tileBufferResetRedrawState( + &pManager->pRedrawStates[0], wStartX, uwEndX, wStartY, uwEndY + ); + tileBufferResetRedrawState( + &pManager->pRedrawStates[1], wStartX, uwEndX, wStartY, uwEndY + ); UWORD uwTileOffsY = SCROLLBUFFER_HEIGHT_MODULO( wStartY << ubTileShift, pManager->uwMarginedHeight