Merge branch 'master' into fixedblock2

This commit is contained in:
tildearrow 2025-01-27 16:33:45 -05:00
commit 24cffc562a
18 changed files with 81 additions and 46 deletions

View file

@ -7,7 +7,6 @@ these demo songs are not under the GPL. all rights are reserved to the original
# contributors # contributors
- 0x5066 - 0x5066
- aarchMoth
- Abstract 64 - Abstract 64
- Aburtos - Aburtos
- ActualNK358 - ActualNK358
@ -16,12 +15,14 @@ these demo songs are not under the GPL. all rights are reserved to the original
- aloelucidity - aloelucidity
- AmigaX - AmigaX
- AquaDoesStuff - AquaDoesStuff
- asikwus
- AstralBlue - AstralBlue
- Background2982 - Background2982
- battybeats - battybeats
- bbqzzd - bbqzzd
- Bernie - Bernie
- billimanmcjonnson - billimanmcjonnson
- biolizardshadow
- BlastBrothers - BlastBrothers
- Blaze Weednix - Blaze Weednix
- BlueElectric05 - BlueElectric05
@ -134,6 +135,7 @@ these demo songs are not under the GPL. all rights are reserved to the original
- Xan - Xan
- Yuzu4K - Yuzu4K
- Zabir - Zabir
- Zaxinoth Digital
- Zaxolotl - Zaxolotl
- ZoomTen (Zumi) - ZoomTen (Zumi)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
demos/multichip/steak.fur Normal file

Binary file not shown.

Binary file not shown.

View file

@ -200,13 +200,16 @@ bool DivCSPlayer::tick() {
case DIV_CMD_HINT_PITCH: case DIV_CMD_HINT_PITCH:
arg0=(signed char)stream.readC(); arg0=(signed char)stream.readC();
break; break;
case DIV_CMD_PANNING:
case DIV_CMD_HINT_VIBRATO: case DIV_CMD_HINT_VIBRATO:
case DIV_CMD_HINT_ARPEGGIO: case DIV_CMD_HINT_ARPEGGIO:
case DIV_CMD_HINT_PORTA: case DIV_CMD_HINT_PORTA:
arg0=(signed char)stream.readC(); arg0=(signed char)stream.readC();
arg1=(unsigned char)stream.readC(); arg1=(unsigned char)stream.readC();
break; break;
case DIV_CMD_PANNING:
arg0=(unsigned char)stream.readC();
arg1=(unsigned char)stream.readC();
break;
case DIV_CMD_PRE_PORTA: case DIV_CMD_PRE_PORTA:
arg0=(unsigned char)stream.readC(); arg0=(unsigned char)stream.readC();
arg1=(arg0&0x40)?1:0; arg1=(arg0&0x40)?1:0;

View file

@ -67,9 +67,9 @@ enum DivDispatchCmds {
DIV_CMD_HINT_ARPEGGIO, // (note1, note2) DIV_CMD_HINT_ARPEGGIO, // (note1, note2)
DIV_CMD_HINT_VOLUME, // (vol) DIV_CMD_HINT_VOLUME, // (vol)
DIV_CMD_HINT_VOL_SLIDE, // (amount, oneTick) DIV_CMD_HINT_VOL_SLIDE, // (amount, oneTick)
DIV_CMD_HINT_VOL_SLIDE_TARGET, // (amount, target)
DIV_CMD_HINT_PORTA, // (target, speed) DIV_CMD_HINT_PORTA, // (target, speed)
DIV_CMD_HINT_LEGATO, // (note) DIV_CMD_HINT_LEGATO, // (note)
DIV_CMD_HINT_VOL_SLIDE_TARGET, // (amount, target)
DIV_CMD_SAMPLE_MODE, // (enabled) DIV_CMD_SAMPLE_MODE, // (enabled)
DIV_CMD_SAMPLE_FREQ, // (frequency) DIV_CMD_SAMPLE_FREQ, // (frequency)

View file

@ -910,7 +910,8 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
int vol=50; int vol=50;
short* data; short* data;
unsigned char* adpcmData; unsigned char* adpcmData;
if (length<0) { // I don't think a sample can be that big
if (length<0 || length>(1<<29L)) {
logE("invalid sample length %d. are we doing something wrong?",length); logE("invalid sample length %d. are we doing something wrong?",length);
lastError="file is corrupt or unreadable at samples"; lastError="file is corrupt or unreadable at samples";
delete[] file; delete[] file;
@ -928,6 +929,11 @@ bool DivEngine::loadDMF(unsigned char* file, size_t len) {
sample->centerRate=sample->rate; sample->centerRate=sample->rate;
pitch=reader.readC(); pitch=reader.readC();
vol=reader.readC(); vol=reader.readC();
if (pitch<0 || pitch>10) {
logW("%d: sample pitch is wrong! (%d)",i,pitch);
pitch=5;
}
} }
if (ds.version<=0x08) { if (ds.version<=0x08) {
sample->rate=ymuSampleRate*400; sample->rate=ymuSampleRate*400;

View file

@ -198,7 +198,7 @@ bool DivEngine::loadMod(unsigned char* file, size_t len) {
int period=data[1]+((data[0]&0x0f)<<8); int period=data[1]+((data[0]&0x0f)<<8);
if (period>0 && period<0x0fff) { if (period>0 && period<0x0fff) {
short note=(short)round(log2(3424.0/period)*12); short note=(short)round(log2(3424.0/period)*12);
dstrow[0]=((note-1)%12)+1; dstrow[0]=((note+11)%12)+1;
dstrow[1]=(note-1)/12+1; dstrow[1]=(note-1)/12+1;
if (period<114) { if (period<114) {
bypassLimits=true; bypassLimits=true;

View file

@ -67,9 +67,9 @@ const char* cmdName[]={
"HINT_ARPEGGIO", "HINT_ARPEGGIO",
"HINT_VOLUME", "HINT_VOLUME",
"HINT_VOL_SLIDE", "HINT_VOL_SLIDE",
"HINT_VOL_SLIDE_TARGET",
"HINT_PORTA", "HINT_PORTA",
"HINT_LEGATO", "HINT_LEGATO",
"HINT_VOL_SLIDE_TARGET",
"SAMPLE_MODE", "SAMPLE_MODE",
"SAMPLE_FREQ", "SAMPLE_FREQ",

View file

@ -61,6 +61,7 @@ int SafeReader::read(void* where, size_t count) {
#endif #endif
if (count==0) return 0; if (count==0) return 0;
if (curSeek+count>len) throw EndOfFileException(this,len); if (curSeek+count>len) throw EndOfFileException(this,len);
if (curSeek+count<curSeek) throw EndOfFileException(this,len);
memcpy(where,&buf[curSeek],count); memcpy(where,&buf[curSeek],count);
curSeek+=count; curSeek+=count;
return count; return count;
@ -71,6 +72,7 @@ signed char SafeReader::readC() {
logD("SR: reading char %x:",curSeek); logD("SR: reading char %x:",curSeek);
#endif #endif
if (curSeek+1>len) throw EndOfFileException(this,len); if (curSeek+1>len) throw EndOfFileException(this,len);
if (curSeek+1<curSeek) throw EndOfFileException(this,len);
#ifdef READ_DEBUG #ifdef READ_DEBUG
logD("SR: %.2x",buf[curSeek]); logD("SR: %.2x",buf[curSeek]);
#endif #endif
@ -83,6 +85,7 @@ short SafeReader::readS_BE() {
logD("SR: reading short %x:",curSeek); logD("SR: reading short %x:",curSeek);
#endif #endif
if (curSeek+2>len) throw EndOfFileException(this,len); if (curSeek+2>len) throw EndOfFileException(this,len);
if (curSeek+2<curSeek) throw EndOfFileException(this,len);
short ret; short ret;
memcpy(&ret,&buf[curSeek],2); memcpy(&ret,&buf[curSeek],2);
#ifdef READ_DEBUG #ifdef READ_DEBUG
@ -94,6 +97,7 @@ short SafeReader::readS_BE() {
short SafeReader::readS() { short SafeReader::readS() {
if (curSeek+2>len) throw EndOfFileException(this,len); if (curSeek+2>len) throw EndOfFileException(this,len);
if (curSeek+2<curSeek) throw EndOfFileException(this,len);
short ret; short ret;
memcpy(&ret,&buf[curSeek],2); memcpy(&ret,&buf[curSeek],2);
curSeek+=2; curSeek+=2;
@ -105,6 +109,7 @@ int SafeReader::readI_BE() {
logD("SR: reading int %x:",curSeek); logD("SR: reading int %x:",curSeek);
#endif #endif
if (curSeek+4>len) throw EndOfFileException(this,len); if (curSeek+4>len) throw EndOfFileException(this,len);
if (curSeek+4<curSeek) throw EndOfFileException(this,len);
int ret; int ret;
memcpy(&ret,&buf[curSeek],4); memcpy(&ret,&buf[curSeek],4);
curSeek+=4; curSeek+=4;
@ -116,6 +121,7 @@ int SafeReader::readI_BE() {
int SafeReader::readI() { int SafeReader::readI() {
if (curSeek+4>len) throw EndOfFileException(this,len); if (curSeek+4>len) throw EndOfFileException(this,len);
if (curSeek+4<curSeek) throw EndOfFileException(this,len);
unsigned int ret; unsigned int ret;
memcpy(&ret,&buf[curSeek],4); memcpy(&ret,&buf[curSeek],4);
curSeek+=4; curSeek+=4;
@ -124,6 +130,7 @@ int SafeReader::readI() {
int64_t SafeReader::readL() { int64_t SafeReader::readL() {
if (curSeek+8>len) throw EndOfFileException(this,len); if (curSeek+8>len) throw EndOfFileException(this,len);
if (curSeek+8<curSeek) throw EndOfFileException(this,len);
unsigned char ret[8]; unsigned char ret[8];
memcpy(ret,&buf[curSeek],8); memcpy(ret,&buf[curSeek],8);
curSeek+=8; curSeek+=8;
@ -132,6 +139,7 @@ int64_t SafeReader::readL() {
float SafeReader::readF() { float SafeReader::readF() {
if (curSeek+4>len) throw EndOfFileException(this,len); if (curSeek+4>len) throw EndOfFileException(this,len);
if (curSeek+4<curSeek) throw EndOfFileException(this,len);
unsigned int ret; unsigned int ret;
memcpy(&ret,&buf[curSeek],4); memcpy(&ret,&buf[curSeek],4);
curSeek+=4; curSeek+=4;
@ -143,6 +151,7 @@ float SafeReader::readF() {
double SafeReader::readD() { double SafeReader::readD() {
if (curSeek+8>len) throw EndOfFileException(this,len); if (curSeek+8>len) throw EndOfFileException(this,len);
if (curSeek+8<curSeek) throw EndOfFileException(this,len);
unsigned char ret[8]; unsigned char ret[8];
unsigned char retB[8]; unsigned char retB[8];
memcpy(ret,&buf[curSeek],8); memcpy(ret,&buf[curSeek],8);
@ -165,6 +174,7 @@ short SafeReader::readS() {
logD("SR: reading short %x:",curSeek); logD("SR: reading short %x:",curSeek);
#endif #endif
if (curSeek+2>len) throw EndOfFileException(this,len); if (curSeek+2>len) throw EndOfFileException(this,len);
if (curSeek+2<curSeek) throw EndOfFileException(this,len);
short ret; short ret;
memcpy(&ret,&buf[curSeek],2); memcpy(&ret,&buf[curSeek],2);
#ifdef READ_DEBUG #ifdef READ_DEBUG
@ -176,6 +186,7 @@ short SafeReader::readS() {
short SafeReader::readS_BE() { short SafeReader::readS_BE() {
if (curSeek+2>len) throw EndOfFileException(this,len); if (curSeek+2>len) throw EndOfFileException(this,len);
if (curSeek+2<curSeek) throw EndOfFileException(this,len);
short ret; short ret;
memcpy(&ret,&buf[curSeek],2); memcpy(&ret,&buf[curSeek],2);
curSeek+=2; curSeek+=2;
@ -187,6 +198,7 @@ int SafeReader::readI() {
logD("SR: reading int %x:",curSeek); logD("SR: reading int %x:",curSeek);
#endif #endif
if (curSeek+4>len) throw EndOfFileException(this,len); if (curSeek+4>len) throw EndOfFileException(this,len);
if (curSeek+4<curSeek) throw EndOfFileException(this,len);
int ret; int ret;
memcpy(&ret,&buf[curSeek],4); memcpy(&ret,&buf[curSeek],4);
curSeek+=4; curSeek+=4;
@ -198,6 +210,7 @@ int SafeReader::readI() {
int SafeReader::readI_BE() { int SafeReader::readI_BE() {
if (curSeek+4>len) throw EndOfFileException(this,len); if (curSeek+4>len) throw EndOfFileException(this,len);
if (curSeek+4<curSeek) throw EndOfFileException(this,len);
unsigned int ret; unsigned int ret;
memcpy(&ret,&buf[curSeek],4); memcpy(&ret,&buf[curSeek],4);
curSeek+=4; curSeek+=4;
@ -206,6 +219,7 @@ int SafeReader::readI_BE() {
int64_t SafeReader::readL() { int64_t SafeReader::readL() {
if (curSeek+8>len) throw EndOfFileException(this,len); if (curSeek+8>len) throw EndOfFileException(this,len);
if (curSeek+8<curSeek) throw EndOfFileException(this,len);
int64_t ret; int64_t ret;
memcpy(&ret,&buf[curSeek],8); memcpy(&ret,&buf[curSeek],8);
curSeek+=8; curSeek+=8;
@ -214,6 +228,7 @@ int64_t SafeReader::readL() {
float SafeReader::readF() { float SafeReader::readF() {
if (curSeek+4>len) throw EndOfFileException(this,len); if (curSeek+4>len) throw EndOfFileException(this,len);
if (curSeek+4<curSeek) throw EndOfFileException(this,len);
float ret; float ret;
memcpy(&ret,&buf[curSeek],4); memcpy(&ret,&buf[curSeek],4);
curSeek+=4; curSeek+=4;
@ -222,6 +237,7 @@ float SafeReader::readF() {
double SafeReader::readD() { double SafeReader::readD() {
if (curSeek+8>len) throw EndOfFileException(this,len); if (curSeek+8>len) throw EndOfFileException(this,len);
if (curSeek+8<curSeek) throw EndOfFileException(this,len);
double ret; double ret;
memcpy(&ret,&buf[curSeek],8); memcpy(&ret,&buf[curSeek],8);
curSeek+=8; curSeek+=8;

View file

@ -139,7 +139,7 @@ void FurnaceGUI::drawCSPlayer() {
if (ImGui::BeginTabBar("CSOptions")) { if (ImGui::BeginTabBar("CSOptions")) {
int chans=e->getTotalChannelCount(); int chans=e->getTotalChannelCount();
if (ImGui::BeginTabItem(_("Status"))) { if (ImGui::BeginTabItem(_("Status"))) {
if (ImGui::BeginTable("CSStat",12,ImGuiTableFlags_SizingFixedSame|ImGuiTableFlags_ScrollX|ImGuiTableFlags_Borders)) { if (ImGui::BeginTable("CSStat",13,ImGuiTableFlags_SizingStretchSame|ImGuiTableFlags_ScrollX|ImGuiTableFlags_Borders)) {
ImGui::TableSetupScrollFreeze(1,1); ImGui::TableSetupScrollFreeze(1,1);
ImGui::TableNextRow(ImGuiTableRowFlags_Headers); ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
ImGui::TableNextColumn(); ImGui::TableNextColumn();

View file

@ -71,47 +71,51 @@ const char* sampleNote[12]={
} }
#define SIMPLE_DRAG_SOURCE(_c,_toMoveVar) \ #define SIMPLE_DRAG_SOURCE(_c,_toMoveVar) \
if (settings.draggableDataView && ImGui::BeginDragDropSource()) { \ if (settings.draggableDataView) { \
_toMoveVar=i; \ if (ImGui::BeginDragDropSource()) { \
ImGui::SetDragDropPayload(_c,NULL,0,ImGuiCond_Once); \ _toMoveVar=i; \
ImGui::Button(ICON_FA_ARROWS "##AssetDrag"); \ ImGui::SetDragDropPayload(_c,NULL,0,ImGuiCond_Once); \
ImGui::EndDragDropSource(); \ ImGui::Button(ICON_FA_ARROWS "##AssetDrag"); \
ImGui::EndDragDropSource(); \
} \
} }
#define SIMPLE_DRAG_TARGET(_c,_toMoveVar,_curVar,_swapFn,_moveUpFn,_moveDownFn) \ #define SIMPLE_DRAG_TARGET(_c,_toMoveVar,_curVar,_swapFn,_moveUpFn,_moveDownFn) \
if (settings.draggableDataView && ImGui::BeginDragDropTarget()) { \ if (settings.draggableDataView) { \
const ImGuiPayload* payload=ImGui::AcceptDragDropPayload(_c); \ if (ImGui::BeginDragDropTarget()) { \
if (payload!=NULL) { \ const ImGuiPayload* payload=ImGui::AcceptDragDropPayload(_c); \
int target=i; \ if (payload!=NULL) { \
bool markModified=false; \ int target=i; \
if (_toMoveVar!=target) { \ bool markModified=false; \
if (ImGui::IsKeyDown(ImGuiKey_ModCtrl)) { \ if (_toMoveVar!=target) { \
markModified=_swapFn(_toMoveVar,target); \ if (ImGui::IsKeyDown(ImGuiKey_ModCtrl)) { \
} else { \ markModified=_swapFn(_toMoveVar,target); \
while (_toMoveVar>target) { \ } else { \
if (_moveUpFn(_toMoveVar)) { \ while (_toMoveVar>target) { \
_toMoveVar--; \ if (_moveUpFn(_toMoveVar)) { \
markModified=true; \ _toMoveVar--; \
} else { \ markModified=true; \
break; \ } else { \
} \ break; \
} \ } \
while (_toMoveVar<target) { \ } \
if (_moveDownFn(_toMoveVar)) { \ while (_toMoveVar<target) { \
_toMoveVar++; \ if (_moveDownFn(_toMoveVar)) { \
markModified=true; \ _toMoveVar++; \
} else { \ markModified=true; \
break; \ } else { \
break; \
} \
} \ } \
} \ } \
_curVar=target; \
} \ } \
_curVar=target; \ if (markModified) { \
MARK_MODIFIED; \
} \
_toMoveVar=-1; \
ImGui::EndDragDropTarget(); \
} \ } \
if (markModified) { \
MARK_MODIFIED; \
} \
_toMoveVar=-1; \
ImGui::EndDragDropTarget(); \
} \ } \
} }

View file

@ -676,6 +676,10 @@ void FurnaceGUI::doPasteFurnace(PasteMode mode, int arg, bool readClipboard, Str
} }
} }
if (mode==GUI_PASTE_MODE_OVERFLOW && !e->isPlaying()) {
setOrder(curOrder);
}
if (readClipboard) { if (readClipboard) {
if (settings.cursorPastePos) { if (settings.cursorPastePos) {
makeCursorUndo(); makeCursorUndo();

View file

@ -371,7 +371,7 @@ void FurnaceGUI::doReplace() {
switch (queryReplaceEffectPos) { switch (queryReplaceEffectPos) {
case 0: // clear case 0: // clear
for (int j=0; j<e->song.subsong[i.subsong]->pat[i.x].effectCols; j++) { for (int j=0; j<e->song.subsong[i.subsong]->pat[i.x].effectCols && j<8; j++) {
effectOrder[j]=j; effectOrder[j]=j;
} }
break; break;
@ -380,7 +380,7 @@ void FurnaceGUI::doReplace() {
for (int j=0; j<8 && placementIndex<8 && i.effectPos[j]>=0; j++) { for (int j=0; j<8 && placementIndex<8 && i.effectPos[j]>=0; j++) {
effectOrder[placementIndex++]=i.effectPos[j]; effectOrder[placementIndex++]=i.effectPos[j];
} }
for (int j=0; j<e->song.subsong[i.subsong]->pat[i.x].effectCols; j++) { for (int j=0; j<e->song.subsong[i.subsong]->pat[i.x].effectCols && placementIndex<8 && j<8; j++) {
if (p->data[i.y][4+j*2]!=-1 || p->data[i.y][5+j*2]!=-1) { if (p->data[i.y][4+j*2]!=-1 || p->data[i.y][5+j*2]!=-1) {
effectOrder[placementIndex++]=j; effectOrder[placementIndex++]=j;
} }
@ -392,7 +392,7 @@ void FurnaceGUI::doReplace() {
for (int j=0; j<8 && placementIndex<8 && i.effectPos[j]>=0; j++) { for (int j=0; j<8 && placementIndex<8 && i.effectPos[j]>=0; j++) {
effectOrder[placementIndex++]=i.effectPos[j]; effectOrder[placementIndex++]=i.effectPos[j];
} }
for (int j=0; j<e->song.subsong[i.subsong]->pat[i.x].effectCols; j++) { for (int j=0; j<e->song.subsong[i.subsong]->pat[i.x].effectCols && placementIndex<8 && j<8; j++) {
if (p->data[i.y][4+j*2]!=-1 || p->data[i.y][5+j*2]!=-1) { if (p->data[i.y][4+j*2]!=-1 || p->data[i.y][5+j*2]!=-1) {
effectOrder[placementIndex++]=j; effectOrder[placementIndex++]=j;
} }
@ -406,7 +406,7 @@ void FurnaceGUI::doReplace() {
} }
case 3: { // insert in free spaces case 3: { // insert in free spaces
int placementIndex=0; int placementIndex=0;
for (int j=0; j<e->song.subsong[i.subsong]->pat[i.x].effectCols; j++) { for (int j=0; j<e->song.subsong[i.subsong]->pat[i.x].effectCols && j<8; j++) {
if (p->data[i.y][4+j*2]==-1 && p->data[i.y][5+j*2]==-1) { if (p->data[i.y][4+j*2]==-1 && p->data[i.y][5+j*2]==-1) {
effectOrder[placementIndex++]=j; effectOrder[placementIndex++]=j;
} }
@ -415,7 +415,7 @@ void FurnaceGUI::doReplace() {
} }
} }
for (int j=0; j<queryReplaceEffectCount; j++) { for (int j=0; j<queryReplaceEffectCount && j<8; j++) {
signed char pos=effectOrder[j]; signed char pos=effectOrder[j];
if (pos==-1) continue; if (pos==-1) continue;
if (queryReplaceEffectDo[j]) { if (queryReplaceEffectDo[j]) {