From 0638d88ff91d95a7d7657ab8d696cab2ed9fe2db Mon Sep 17 00:00:00 2001 From: ansstuff Date: Fri, 9 Mar 2012 15:20:51 +0000 Subject: [PATCH] * Taseditor: Config->Deselect on doubleclick * Taseditor: checking ROM checksum when saving/loading projects * more correct way to launch TAS Editor when trying to rerecord a fm3 * TAS Editor can have mouse wheel input even when keyboard focus is on FCEUX window * disabled FCEUX context menu when TAS Editor is engaged * added SoundDisplay2.lua --- output/luaScripts/SoundDisplay2.lua | 312 ++++++++++++++++++ src/drivers/win/config.cpp | 1 + src/drivers/win/res.rc | 4 +- src/drivers/win/resource.h | 3 +- src/drivers/win/taseditor.cpp | 23 +- src/drivers/win/taseditor/bookmarks.cpp | 10 +- src/drivers/win/taseditor/greenzone.h | 2 +- src/drivers/win/taseditor/piano_roll.cpp | 24 +- src/drivers/win/taseditor/recorder.cpp | 16 +- src/drivers/win/taseditor/selection.cpp | 15 +- src/drivers/win/taseditor/splicer.cpp | 6 + .../win/taseditor/taseditor_config.cpp | 1 + src/drivers/win/taseditor/taseditor_config.h | 1 + src/drivers/win/taseditor/taseditor_lua.cpp | 2 +- .../win/taseditor/taseditor_project.cpp | 165 ++++++--- src/drivers/win/taseditor/taseditor_project.h | 4 +- .../win/taseditor/taseditor_window.cpp | 6 +- src/drivers/win/window.cpp | 73 ++-- src/emufile.h | 3 +- src/movie.cpp | 17 +- src/state.cpp | 10 +- 21 files changed, 554 insertions(+), 144 deletions(-) create mode 100644 output/luaScripts/SoundDisplay2.lua diff --git a/output/luaScripts/SoundDisplay2.lua b/output/luaScripts/SoundDisplay2.lua new file mode 100644 index 00000000..55a0582f --- /dev/null +++ b/output/luaScripts/SoundDisplay2.lua @@ -0,0 +1,312 @@ +-- feos, 2012 +-- gui.box frame simulates transparency + +print("Hi-hat and keys may glitch if you produce sound effects.") +print("Leftclick over the displays: channel names to hide the volumes, notes to hide the keyboard.") +print(" ") +print("And praise Gocha!") + +iterator = 15 +kb = {x=9, y=154, on=true} +prev_keys = input.get() +semitones = {"A", "A#", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"} + +volumes = { + S1V = {0}, S1C = {}, + S2V = {0}, S2C = {}, + TV = {0}, + NV = {0}, + DPCMV = {0} +} + +function Draw() + snd = sound.get() + keys = input.get() + + -- do only at the first frame + if #volumes.S1V == 1 then + channels = { + Square1 = {x=1, y=9, vol=volumes.S1V, color=volumes.S1C, duty=0, midi=0, semitone=0, octave=0, prev_semitone=0, float = {}}, + Square2 = {x=1+45*1, y=9, vol=volumes.S2V, color=volumes.S2C, duty=0, midi=0, semitone=0, octave=0, prev_semitone=0, float = {}}, + Triangle = {x=1+45*2, y=9, vol=volumes.TV, midi=0, semitone=0, octave=0, prev_semitone=0, float = {}}, + Noise = {x=1+45*3, y=9, vol=volumes.NV, midi=0, semitone=0, octave=0}, + DPCM = {x=1+45*4, y=9, vol=volumes.DPCMV} + } + end + + -- update the first indices for volume tables + -- shift the previous ones farther + table.insert(channels.Square1.vol, 1, snd.rp2a03.square1.volume*15) + table.insert(channels.Square2.vol, 1, snd.rp2a03.square2.volume*15) + table.insert(channels.Triangle.vol, 1, snd.rp2a03.triangle.volume*15) + table.insert(channels.Noise.vol, 1, snd.rp2a03.noise.volume*15) + table.insert(channels.DPCM.vol, 1, snd.rp2a03.dpcm.volume*15) + + -- get duty and midikey for proper channels + channels.Square1.duty = snd.rp2a03.square1.duty + channels.Square2.duty = snd.rp2a03.square2.duty + + channels.Square1.midi = snd.rp2a03.square1.midikey + channels.Square2.midi = snd.rp2a03.square2.midikey + channels.Triangle.midi = snd.rp2a03.triangle.midikey + channels.Noise.midi = snd.rp2a03.noise.midikey + + -- guess notes + for name, chan in pairs(channels) do + if name == "Square1" or name == "Square2" or name == "Triangle" or name == "Noise" then + if chan.vol[1] > 0 then + chan.octave = math.floor((chan.midi - 12) / 12) + chan.semitone = tostring(semitones[math.floor((chan.midi - 21) % 12) + 1]) + else chan.semitone = "--"; chan.octave = "-" + end + end + end + + -- notes display + gui.text(kb.x+203, kb.y, "S1: "..channels.Square1.semitone..channels.Square1.octave, "#ff0000ff", "#000000ff") + gui.text(kb.x+203, kb.y+9, "S2: "..channels.Square2.semitone..channels.Square2.octave, "#aa00ccff", "#000000ff") + gui.text(kb.x+204, kb.y+18, "Tr: "..channels.Triangle.semitone..channels.Triangle.octave, "#00aaffff", "#000000ff") + gui.text(kb.x+204, kb.y+27, "Ns: "..channels.Noise.semitone..channels.Noise.octave, "#ffffffff", "#000000ff") + +----------------- +-- Draw hi-hat -- +----------------- + + xhh1 = 227 + yhh1 = 18 + xhh2 = 227 + yhh2 = 18 + + if channels.Noise.vol[1] > 0 then + if channels.Noise.octave >= 8 and channels.Noise.octave <= 13 then + colorhh = "#ffaa00" + if channels.Noise.vol[2] - channels.Noise.vol[1] < 4 + and channels.Noise.vol[2] > 0 + then yhh1 = 15 + end + end + else colorhh = "#00000000" + end + + gui.line(xhh1-1, yhh1, xhh1+28, yhh1, "#00000088") + gui.line(xhh1-1, yhh1-1, xhh1+28, yhh1-1, "#00000088") + gui.line(xhh1-1, yhh1-2, xhh1+28, yhh1-2, "#00000088") + gui.line(xhh1+3, yhh1-3, xhh1+24, yhh1-3, "#00000088") + gui.line(xhh1+8, yhh1-4, xhh1+19, yhh1-4, "#00000088") + gui.line(xhh1+11, yhh1-5, xhh1+16, yhh1-5, "#00000088") + gui.line(xhh1+12, yhh1-6, xhh1+15, yhh1-6, "#00000088") + gui.line(xhh2-1, yhh2, xhh2+28, yhh2, "#00000088") + gui.line(xhh2-1, yhh2+1, xhh2+28, yhh2+1, "#00000088") + gui.line(xhh2-1, yhh2+2, xhh2+28, yhh2+2, "#00000088") + gui.line(xhh2+3, yhh2+3, xhh2+24, yhh2+3, "#00000088") + gui.line(xhh2+8, yhh2+4, xhh2+19, yhh2+4, "#00000088") + gui.line(xhh2+11, yhh2+5, xhh2+16, yhh2+5, "#00000088") + gui.line(xhh2+12, yhh2+6, xhh2+15, yhh2+6, "#00000088") + + gui.line(xhh1, yhh1-1, xhh1+27, yhh1-1, colorhh) + gui.line(xhh1+4, yhh1-2, xhh1+23, yhh1-2, colorhh) + gui.line(xhh1+9, yhh1-3, xhh1+18, yhh1-3, colorhh) + gui.line(xhh1+12, yhh1-4, xhh1+15, yhh1-4, colorhh) + gui.line(xhh1+13, yhh1-5, xhh1+14, yhh1-5, colorhh) + gui.line(xhh2, yhh2+1, xhh2+27, yhh2+1, colorhh) + gui.line(xhh2+4, yhh2+2, xhh2+23, yhh2+2, colorhh) + gui.line(xhh2+9, yhh2+3, xhh2+18, yhh2+3, colorhh) + gui.line(xhh2+12, yhh2+4, xhh2+15, yhh2+4, colorhh) + gui.line(xhh2+13, yhh2+5, xhh2+14, yhh2+5, colorhh) + +-------------------- +-- Keyboard stuff -- +-------------------- + + if (kb.on) then + -- capture leftclicks + if keys.xmouse <= 256 and keys.xmouse >= 205 and keys.ymouse >= 154 and keys.ymouse <= 181 then + if keys["leftclick"] and not prev_keys["leftclick"] then kb.on = false end + end + -- draw the kayboard + gui.box(kb.x-8, kb.y, kb.x+200, kb.y+16, "#ffffffff") -- white solid box + for a = -2, 49 do gui.box(kb.x+4*a, kb.y, kb.x+4*a, kb.y+16, "#00000000") end -- black lines + -- draw colored boxes as clean notes + for name, chan in pairs(channels) do + if name == "Square1" or name == "Square2" or name == "Triangle" then + if name == "Triangle" then color = "#00aaffff" + elseif name == "Square1" then color = "#ff0000ff" + else color = "#aa00ccff" + end + + if chan.semitone == "C" then gui.box(kb.x+1 +28*(chan.octave-1), kb.y, kb.x+3 +28*(chan.octave-1), kb.y+16, color) + elseif chan.semitone == "D" then gui.box(kb.x+5 +28*(chan.octave-1), kb.y, kb.x+7 +28*(chan.octave-1), kb.y+16, color) + elseif chan.semitone == "E" then gui.box(kb.x+9 +28*(chan.octave-1), kb.y, kb.x+11+28*(chan.octave-1), kb.y+16, color) + elseif chan.semitone == "F" then gui.box(kb.x+13+28*(chan.octave-1), kb.y, kb.x+15+28*(chan.octave-1), kb.y+16, color) + elseif chan.semitone == "G" then gui.box(kb.x+17+28*(chan.octave-1), kb.y, kb.x+19+28*(chan.octave-1), kb.y+16, color) + elseif chan.semitone == "A" then gui.box(kb.x+21+28*(chan.octave-1), kb.y, kb.x+23+28*(chan.octave-1), kb.y+16, color) + elseif chan.semitone == "B" then gui.box(kb.x+25+28*(chan.octave-1), kb.y, kb.x+27+28*(chan.octave-1), kb.y+16, color) + end + end + end + -- draw accidental keys + gui.box(kb.x-3, kb.y, kb.x-5, kb.y+10, "#00000000") + for oct = 0, 6 do + gui.box(kb.x+3+28*oct, kb.y, kb.x+5+28*oct, kb.y+10, "#00000000") + gui.box(kb.x+7+28*oct, kb.y, kb.x+9+28*oct, kb.y+10, "#00000000") + gui.box(kb.x+15+28*oct, kb.y, kb.x+17+28*oct, kb.y+10, "#00000000") + gui.box(kb.x+19+28*oct, kb.y, kb.x+21+28*oct, kb.y+10, "#00000000") + gui.box(kb.x+23+28*oct, kb.y, kb.x+25+28*oct, kb.y+10, "#00000000") + end + -- draw colored boxes over accidental keys + for name, chan in pairs(channels) do + if name == "Square1" or name == "Square2" or name == "Triangle" then + if name == "Triangle" then color = "#00aaffff" + elseif name == "Square1" then color = "#ff0000ff" + else color = "#aa00ccff" + end + + if chan.semitone == "C#" then gui.box(kb.x+3 +28*(chan.octave-1), kb.y, kb.x+5 +28*(chan.octave-1), kb.y+10, color) + elseif chan.semitone == "D#" then gui.box(kb.x+7 +28*(chan.octave-1), kb.y, kb.x+9 +28*(chan.octave-1), kb.y+10, color) + elseif chan.semitone == "F#" then gui.box(kb.x+15+28*(chan.octave-1), kb.y, kb.x+17+28*(chan.octave-1), kb.y+10, color) + elseif chan.semitone == "G#" then gui.box(kb.x+19+28*(chan.octave-1), kb.y, kb.x+21+28*(chan.octave-1), kb.y+10, color) + elseif chan.semitone == "A#" then gui.box(kb.x+23+28*(chan.octave-1), kb.y, kb.x+25+28*(chan.octave-1), kb.y+10, color) + end + end + end + + grey = "#aaaaaaaa" + for oct = 0, 6 do + gui.line(kb.x+3+28*oct, kb.y+10, kb.x+5+28*oct, kb.y+10, grey) + gui.line(kb.x+7+28*oct, kb.y+10, kb.x+9+28*oct, kb.y+10, grey) + gui.line(kb.x+15+28*oct, kb.y+10, kb.x+17+28*oct, kb.y+10, grey) + gui.line(kb.x+19+28*oct, kb.y+10, kb.x+21+28*oct, kb.y+10, grey) + gui.line(kb.x+23+28*oct, kb.y+10, kb.x+25+28*oct, kb.y+10, grey) + end + gui.line(kb.x-3, kb.y+10, kb.x-5, kb.y+10, grey) + gui.line(kb.x-8, kb.y, kb.x+200, kb.y, "#00000088") + gui.line(kb.x-8, kb.y+16, kb.x+200, kb.y+16, "#00000088") + gui.line(kb.x-8, kb.y, kb.x-8, kb.y+16, "#00000088") + gui.line(kb.x+200, kb.y, kb.x+200, kb.y+16, "#00000088") + else + -- capture leftclicks + if keys.xmouse <= 256 and keys.xmouse >= 205 and keys.ymouse >= 154 and keys.ymouse <= 181 then + if keys["leftclick"] and not prev_keys["leftclick"] then kb.on = true end + end + end + +-------------------- +-- Floating notes -- +-------------------- + + if (kb.on) then + for name, chan in pairs(channels) do + if name == "Square1" or name == "Square2" or name == "Triangle" then + + if chan.prev_semitone ~= chan.semitone then + if chan.semitone == "C" then table.insert(chan.float, 1, kb.x+1 +28*(chan.octave-1)) + elseif chan.semitone == "D" then table.insert(chan.float, 1, kb.x+5 +28*(chan.octave-1)) + elseif chan.semitone == "E" then table.insert(chan.float, 1, kb.x+9 +28*(chan.octave-1)) + elseif chan.semitone == "F" then table.insert(chan.float, 1, kb.x+13+28*(chan.octave-1)) + elseif chan.semitone == "G" then table.insert(chan.float, 1, kb.x+17+28*(chan.octave-1)) + elseif chan.semitone == "A" then table.insert(chan.float, 1, kb.x+21+28*(chan.octave-1)) + elseif chan.semitone == "B" then table.insert(chan.float, 1, kb.x+25+28*(chan.octave-1)) + elseif chan.semitone == "C#" then table.insert(chan.float, 1, kb.x+3 +28*(chan.octave-1)) + elseif chan.semitone == "D#" then table.insert(chan.float, 1, kb.x+7 +28*(chan.octave-1)) + elseif chan.semitone == "F#" then table.insert(chan.float, 1, kb.x+15+28*(chan.octave-1)) + elseif chan.semitone == "G#" then table.insert(chan.float, 1, kb.x+19+28*(chan.octave-1)) + elseif chan.semitone == "A#" then table.insert(chan.float, 1, kb.x+23+28*(chan.octave-1)) + end + end + + if name == "Triangle" then color = "#00aaffff" + elseif name == "Square1" then color = "#ff0000ff" + else color = "#aa00ccff" + end + + if #chan.float < 13 then + for i = 2, #chan.float do + if movie.framecount()%2 == 0 then gui.box(chan.float[i]-1, 161+i*5, chan.float[i]+3, 165+i*5, "#eedd2200") end + gui.box(chan.float[i], 162+i*5, chan.float[i]+2, 164+i*5, color) + end + else + for i = 2, 13 do + if movie.framecount()%2 == 0 then gui.box(chan.float[i]-1, 161+i*5, chan.float[i]+3, 165+i*5, "#eedd2200") end + gui.box(chan.float[i], 162+i*5, chan.float[i]+2, 164+i*5, color) + end + table.remove(chan.float, 14) + end + end + end + end + +--------------------- +-- Volumes display -- +--------------------- + + for name, chan in pairs(channels) do + if name == "Square1" or name == "Square2" then + -- set color for each duty value + if chan.duty == 0 then table.insert(chan.color,1,"#aaff00ff") + elseif chan.duty == 1 then table.insert(chan.color,1,"#00ff00ff") + elseif chan.duty == 2 then table.insert(chan.color,1,"#00bb00ff") + else table.insert(chan.color,1,"#008800ff") + end + end + -- capture leftclicks + if iterator == 15 then + if keys.ymouse <= 24 and keys.ymouse >= 0 then + if keys["leftclick"] and not prev_keys["leftclick"] then iterator = 1 end + end + else + if keys.ymouse <= 24 and keys.ymouse >= 0 then + if keys["leftclick"] and not prev_keys["leftclick"] then iterator = 15 end + end + end + -- draw volumes + gui.text(chan.x, 9, name, "#ffffffff", "#000000ff") + if iterator <=14 then + -- draw just first volume values + gui.text(chan.x, chan.y+9+1, chan.vol[1]) + if tonumber(chan.vol[1]) > 0 then + for j = 0, chan.vol[1]-1 do + gui.box(chan.x+13+j*2, chan.y+9, chan.x+15+j*2, chan.y+8+9, "#000000ff") + gui.line(chan.x+14+j*2, chan.y+1+9, chan.x+14+j*2, chan.y+7+9, "#00ff00ff") + if name == "Square1" or name == "Square2" then + -- color comes from duty + gui.text(chan.x+38, chan.y, chan.duty, chan.color[1], "#000000ff") + gui.line(chan.x+14+j*2, chan.y+1+9, chan.x+14+j*2, chan.y+7+9, chan.color[1]) + end + end + end + else + -- draw all 15 volume values + for i = 1, #chan.vol do + gui.text(chan.x, chan.y+i*9+1, chan.vol[i]) + if tonumber(chan.vol[i]) > 0 then + for j = 0, chan.vol[i]-1 do + gui.box(chan.x+13+j*2, chan.y+i*9, chan.x+15+j*2, chan.y+8+i*9, "#000000ff") + gui.line(chan.x+14+j*2, chan.y+1+i*9, chan.x+14+j*2, chan.y+7+i*9, "#00ff00ff") + if name == "Square1" or name == "Square2" then + -- color comes from duty + gui.text(chan.x+38, chan.y, chan.duty, chan.color[1], "#000000ff") + gui.line(chan.x+14+j*2, chan.y+1+i*9, chan.x+14+j*2, chan.y+7+i*9, chan.color[i]) + end + end + end + end + end + -- keep the table limited + table.remove(chan.vol, 15) + + -- highlight the first values + -- 30 Hz blinking, works properly if your monitor is set to 60 Hz + if chan.vol[1] > 0 and movie.framecount()%2 == 0 then + gui.box(chan.x+12, chan.y+8, chan.x+14+chan.vol[1]*2, chan.y+18, "#ffcc0000") + end + end + + for name, chan in pairs(channels) do + if name == "Square1" or name == "Square2" or name == "Triangle" then + chan.prev_semitone = chan.semitone + end + end + + prev_keys = keys +end +emu.registerafter(Draw); \ No newline at end of file diff --git a/src/drivers/win/config.cpp b/src/drivers/win/config.cpp index 558033fe..a1f611bb 100644 --- a/src/drivers/win/config.cpp +++ b/src/drivers/win/config.cpp @@ -347,6 +347,7 @@ static CFGSTRUCT fceuconfig[] = { AC(taseditor_config.savecompact_selection), AC(taseditor_config.findnote_matchcase), AC(taseditor_config.findnote_search_up), + AC(taseditor_config.deselect_on_doubleclick), AC(taseditor_config.silent_autosave), AC(taseditor_config.tooltips), AC(taseditor_config.current_pattern), diff --git a/src/drivers/win/res.rc b/src/drivers/win/res.rc index 4a42fdb2..8eae80bf 100644 --- a/src/drivers/win/res.rc +++ b/src/drivers/win/res.rc @@ -289,7 +289,9 @@ BEGIN MENUITEM "Use Input keys for Column Set", ID_CONFIG_USEINPUTKEYSFORCOLUMNSET,MFT_STRING,MFS_ENABLED MENUITEM "Allow keyboard controls in Piano Roll", ID_CONFIG_KEYBOARDCONTROLSINPIANOROLL,MFT_STRING,MFS_ENABLED MENUITEM "Superimpose affects copy/paste", ID_CONFIG_SUPERIMPOSE_AFFECTS_PASTE,MFT_STRING,MFS_ENABLED + MENUITEM MFT_SEPARATOR MENUITEM "Autofire Pattern skips Lag", ID_CONFIG_COLUMNSETPATTERNSKIPSLAG,MFT_STRING,MFS_ENABLED + MENUITEM "Deselect on doubleclick", ID_CONFIG_DESELECTONDOUBLECLICK,MFT_STRING,MFS_ENABLED MENUITEM MFT_SEPARATOR MENUITEM "Silent Autosave", ID_CONFIG_SILENTAUTOSAVE,MFT_STRING,MFS_ENABLED MENUITEM "Mute Turbo", ID_CONFIG_MUTETURBO,MFT_STRING,MFS_ENABLED @@ -1451,7 +1453,7 @@ BEGIN LTEXT "TAS Editor",IDC_TASEDITOR_NAME,43,8,83,13 LTEXT "Version 1.0",IDC_STATIC,63,25,37,8 LTEXT "Created by AnS",IDC_STATIC,138,12,52,8 - LTEXT "Based on TASEdit v0.1",IDC_STATIC,138,25,83,9,SS_NOPREFIX + LTEXT "Originated from TASEdit",IDC_STATIC,138,25,83,9,SS_NOPREFIX LTEXT "made by zeromus & adelikat",IDC_STATIC,138,35,96,9,SS_NOPREFIX END diff --git a/src/drivers/win/resource.h b/src/drivers/win/resource.h index 90596508..4ffa1672 100644 --- a/src/drivers/win/resource.h +++ b/src/drivers/win/resource.h @@ -994,6 +994,7 @@ #define ID_CONFIG_COLUMNSETPATTERNSKIPSLAG 40535 #define ID_EDIT_DESELECT 40536 #define ID_SELECTED_DESELECT 40537 +#define ID_CONFIG_DESELECTONDOUBLECLICK 40538 #define IDC_DEBUGGER_ICONTRAY 55535 #define MW_ValueLabel2 65423 #define MW_ValueLabel1 65426 @@ -1003,7 +1004,7 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 206 -#define _APS_NEXT_COMMAND_VALUE 40538 +#define _APS_NEXT_COMMAND_VALUE 40539 #define _APS_NEXT_CONTROL_VALUE 1281 #define _APS_NEXT_SYMED_VALUE 101 #endif diff --git a/src/drivers/win/taseditor.cpp b/src/drivers/win/taseditor.cpp index 4e17e820..6fbce309 100644 --- a/src/drivers/win/taseditor.cpp +++ b/src/drivers/win/taseditor.cpp @@ -23,11 +23,11 @@ Main - Logical center of the program #include "utils/xstring.h" #include "main.h" // for GetRomName #include "taseditor.h" -#include "version.h" using namespace std; // TAS Editor data +bool emulator_must_run_taseditor = false; bool Taseditor_rewind_now = false; bool must_call_manual_lua_function = false; std::vector autofire_patterns_names; @@ -193,7 +193,6 @@ bool EnterTasEditor() } FCEUI_StopMovie(); movieMode = MOVIEMODE_TASEDITOR; - currMovieData.emuVersion = FCEU_VERSION_NUMERIC; } // ensure that movie has correct set of ports/fourscore SetInputType(currMovieData, GetInputType(currMovieData)); @@ -278,6 +277,14 @@ void UpdateTasEditor() { // TAS Editor is not engaged... but we still should run Lua auto function TaseditorAutoFunction(); + if (emulator_must_run_taseditor) + { + char fullname[512]; + strcpy(fullname, curMovieFilename); + if (EnterTasEditor()) + LoadProject(fullname); + emulator_must_run_taseditor = false; + } return; } @@ -514,10 +521,14 @@ bool SaveProjectAs() } bool SaveProject() { - if (!project.save()) + if (project.GetProjectFile().empty()) + { return SaveProjectAs(); - else + } else + { + project.save(); taseditor_window.UpdateCaption(); + } return true; } @@ -628,9 +639,7 @@ void SaveCompact() ofn.lpstrInitialDir = initdir.c_str(); if(GetSaveFileName(&ofn)) //If it is a valid filename - { - project.save_compact(nameo, taseditor_config.savecompact_binary, taseditor_config.savecompact_markers, taseditor_config.savecompact_bookmarks, taseditor_config.savecompact_greenzone, taseditor_config.savecompact_history, taseditor_config.savecompact_piano_roll, taseditor_config.savecompact_selection); - } + project.save(nameo, taseditor_config.savecompact_binary, taseditor_config.savecompact_markers, taseditor_config.savecompact_bookmarks, taseditor_config.savecompact_greenzone, taseditor_config.savecompact_history, taseditor_config.savecompact_piano_roll, taseditor_config.savecompact_selection); } } diff --git a/src/drivers/win/taseditor/bookmarks.cpp b/src/drivers/win/taseditor/bookmarks.cpp index 498f9b2d..4e05950c 100644 --- a/src/drivers/win/taseditor/bookmarks.cpp +++ b/src/drivers/win/taseditor/bookmarks.cpp @@ -344,9 +344,13 @@ void BOOKMARKS::set(int slot) // save time of this slot before rewriting it char saved_time[TIME_DESC_LENGTH]; if (bookmarks_array[slot].not_empty) - strncpy(saved_time, bookmarks_array[slot].snapshot.description, TIME_DESC_LENGTH-1); - else + { + strncpy(saved_time, bookmarks_array[slot].snapshot.description, TIME_DESC_LENGTH - 1); + saved_time[TIME_DESC_LENGTH - 1] = 0; + } else + { saved_time[0] = 0; + } bookmarks_array[slot].set(); @@ -369,7 +373,7 @@ void BOOKMARKS::set(int slot) break; } if (i >= TOTAL_BOOKMARKS) - // didn't find another child of cloud + // didn't find another child of cloud, change cloud's time, sice "root" has shifted strcpy(cloud_time, saved_time); } // before disconnecting from old parent, connect all childs to the old parent diff --git a/src/drivers/win/taseditor/greenzone.h b/src/drivers/win/taseditor/greenzone.h index 4b6964dc..edecb25d 100644 --- a/src/drivers/win/taseditor/greenzone.h +++ b/src/drivers/win/taseditor/greenzone.h @@ -2,7 +2,7 @@ #define GREENZONE_ID_LEN 10 -#define TIME_BETWEEN_CLEANINGS 10000 // in milliseconds +#define TIME_BETWEEN_CLEANINGS 15000 // in milliseconds // greenzone cleaning masks #define EVERY16TH 0xFFFFFFF0 #define EVERY8TH 0xFFFFFFF8 diff --git a/src/drivers/win/taseditor/piano_roll.cpp b/src/drivers/win/taseditor/piano_roll.cpp index bf4ffb01..5d30d4a1 100644 --- a/src/drivers/win/taseditor/piano_roll.cpp +++ b/src/drivers/win/taseditor/piano_roll.cpp @@ -619,8 +619,14 @@ LONG PIANO_ROLL::CustomDraw(NMLVCUSTOMDRAW* msg) } else if((cell_x - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS == 0 || (cell_x - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS == 2) { // pad 1 or 3 - // font - SelectObject(msg->nmcd.hdc, hMainListFont); + // font: empty cells have "SelectFont", non-empty have normal font + int joy = (cell_x - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS; + int bit = (cell_x - COLUMN_JOYPAD1_A) % NUM_JOYPAD_BUTTONS; + if ((int)currMovieData.records.size() <= cell_y || + ((currMovieData.records[cell_y].joysticks[joy]) & (1<nmcd.hdc, hMainListFont); + else + SelectObject(msg->nmcd.hdc, hMainListSelectFont); // bg if (cell_y == history.GetUndoHint()) { @@ -652,8 +658,14 @@ LONG PIANO_ROLL::CustomDraw(NMLVCUSTOMDRAW* msg) } else if((cell_x - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS == 1 || (cell_x - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS == 3) { // pad 2 or 4 - // font - SelectObject(msg->nmcd.hdc, hMainListFont); + // font: empty cells have "SelectFont", non-empty have normal font + int joy = (cell_x - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS; + int bit = (cell_x - COLUMN_JOYPAD1_A) % NUM_JOYPAD_BUTTONS; + if ((int)currMovieData.records.size() <= cell_y || + ((currMovieData.records[cell_y].joysticks[joy]) & (1<nmcd.hdc, hMainListFont); + else + SelectObject(msg->nmcd.hdc, hMainListSelectFont); // bg if (cell_y == history.GetUndoHint()) { @@ -1092,7 +1104,6 @@ LRESULT APIENTRY ListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) if(column_index == COLUMN_ICONS) { // click on the "icons" column - jump to the frame - selection.ClearSelection(); playback.jump(row_index); } else if(column_index == COLUMN_FRAMENUM || column_index == COLUMN_FRAMENUM2) { @@ -1100,7 +1111,8 @@ LRESULT APIENTRY ListWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) if (msg == WM_LBUTTONDBLCLK && !alt_pressed) { // doubleclick - jump to the frame - selection.ClearSelection(); + if (taseditor_config.deselect_on_doubleclick) + selection.ClearSelection(); playback.jump(row_index); } else { diff --git a/src/drivers/win/taseditor/recorder.cpp b/src/drivers/win/taseditor/recorder.cpp index d00eff29..94229585 100644 --- a/src/drivers/win/taseditor/recorder.cpp +++ b/src/drivers/win/taseditor/recorder.cpp @@ -182,14 +182,18 @@ void RECORDER::update() // call ColumnSet if needed if (taseditor_config.columnset_by_keys && movie_readonly && taseditor_window.TASEditor_focus) { - bool alt_pressed = ((GetAsyncKeyState(VK_MENU) & 0x8000) != 0); - for (int joy = 0; joy < num_joys; ++joy) + // if Ctrl or Shift is held, do not call ColumnSet, because maybe this is accelerator + if ((GetAsyncKeyState(VK_CONTROL) >= 0) && (GetAsyncKeyState(VK_SHIFT) >= 0)) { - for (int button = 0; button < NUM_JOYPAD_BUTTONS; ++button) + bool alt_pressed = ((GetAsyncKeyState(VK_MENU) & 0x8000) != 0); + for (int joy = 0; joy < num_joys; ++joy) { - // if the button was pressed right now - if ((current_joy[joy] & (1 << button)) && !(old_joy[joy] & (1 << button))) - piano_roll.ColumnSet(COLUMN_JOYPAD1_A + joy * NUM_JOYPAD_BUTTONS + button, alt_pressed); + for (int button = 0; button < NUM_JOYPAD_BUTTONS; ++button) + { + // if the button was pressed right now + if ((current_joy[joy] & (1 << button)) && !(old_joy[joy] & (1 << button))) + piano_roll.ColumnSet(COLUMN_JOYPAD1_A + joy * NUM_JOYPAD_BUTTONS + button, alt_pressed); + } } } } diff --git a/src/drivers/win/taseditor/selection.cpp b/src/drivers/win/taseditor/selection.cpp index 4ab1b983..68f164a4 100644 --- a/src/drivers/win/taseditor/selection.cpp +++ b/src/drivers/win/taseditor/selection.cpp @@ -463,7 +463,8 @@ void SELECTION::EnforceSelectionToList() void SELECTION::SelectAll() { - ListView_SetItemState(piano_roll.hwndList, -1, LVIS_SELECTED, LVIS_SELECTED); + // select all, but remove "focused" from all + ListView_SetItemState(piano_roll.hwndList, -1, LVIS_FOCUSED|LVIS_SELECTED, LVIS_SELECTED); } void SELECTION::SetRowSelection(int index) { @@ -472,7 +473,7 @@ void SELECTION::SetRowSelection(int index) void SELECTION::SetRegionSelection(int start, int end) { for (int i = start; i < end; ++i) - ListView_SetItemState(piano_roll.hwndList, i, LVIS_SELECTED, LVIS_SELECTED); + ListView_SetItemState(piano_roll.hwndList, i, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED); } void SELECTION::SelectBetweenMarkers() { @@ -510,7 +511,7 @@ void SELECTION::SelectBetweenMarkers() // default: select all between markers for (int i = upper_marker+1; i < lower_marker; ++i) { - ListView_SetItemState(piano_roll.hwndList, i, LVIS_SELECTED, LVIS_SELECTED); + ListView_SetItemState(piano_roll.hwndList, i, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED); } } else if (upper_border == upper_marker+1 && lower_border == lower_marker-1) { @@ -519,14 +520,14 @@ void SELECTION::SelectBetweenMarkers() if (lower_marker >= movie_size) lower_marker = movie_size - 1; for (int i = upper_marker; i <= lower_marker; ++i) { - ListView_SetItemState(piano_roll.hwndList, i, LVIS_SELECTED, LVIS_SELECTED); + ListView_SetItemState(piano_roll.hwndList, i, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED); } } else if (upper_border <= upper_marker && lower_border >= lower_marker) { // selected all between markers and both markers selected too - now deselect lower marker for (int i = upper_marker; i < lower_marker; ++i) { - ListView_SetItemState(piano_roll.hwndList, i, LVIS_SELECTED, LVIS_SELECTED); + ListView_SetItemState(piano_roll.hwndList, i, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED); } } else if (upper_border == upper_marker && lower_border == lower_marker-1) { @@ -534,14 +535,14 @@ void SELECTION::SelectBetweenMarkers() if (lower_marker >= movie_size) lower_marker = movie_size - 1; for (int i = upper_marker+1; i <= lower_marker; ++i) { - ListView_SetItemState(piano_roll.hwndList, i, LVIS_SELECTED, LVIS_SELECTED); + ListView_SetItemState(piano_roll.hwndList, i, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED); } } else if (upper_border == upper_marker+1 && lower_border == lower_marker) { // selected all between markers and lower marker selected too - now deselect lower marker (return to "selected all between markers") for (int i = upper_marker + 1; i < lower_marker; ++i) { - ListView_SetItemState(piano_roll.hwndList, i, LVIS_SELECTED, LVIS_SELECTED); + ListView_SetItemState(piano_roll.hwndList, i, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED); } } } diff --git a/src/drivers/win/taseditor/splicer.cpp b/src/drivers/win/taseditor/splicer.cpp index d750adb1..54132419 100644 --- a/src/drivers/win/taseditor/splicer.cpp +++ b/src/drivers/win/taseditor/splicer.cpp @@ -547,6 +547,9 @@ bool SPLICER::Paste() } } result = true; + } else + { + SetWindowText(hwndTextClipboard, clipboardEmptyText); } GlobalUnlock(hGlobal); } @@ -664,6 +667,9 @@ bool SPLICER::PasteInsert() } } result = true; + } else + { + SetWindowText(hwndTextClipboard, clipboardEmptyText); } GlobalUnlock(hGlobal); } diff --git a/src/drivers/win/taseditor/taseditor_config.cpp b/src/drivers/win/taseditor/taseditor_config.cpp index 3c191e72..53ea9689 100644 --- a/src/drivers/win/taseditor/taseditor_config.cpp +++ b/src/drivers/win/taseditor/taseditor_config.cpp @@ -70,6 +70,7 @@ TASEDITOR_CONFIG::TASEDITOR_CONFIG() findnote_matchcase = false; findnote_search_up = false; enable_auto_function = true; + deselect_on_doubleclick = true; silent_autosave = true; tooltips = true; current_pattern = 0; diff --git a/src/drivers/win/taseditor/taseditor_config.h b/src/drivers/win/taseditor/taseditor_config.h index caa439ee..eb96a7cd 100644 --- a/src/drivers/win/taseditor/taseditor_config.h +++ b/src/drivers/win/taseditor/taseditor_config.h @@ -68,6 +68,7 @@ public: bool findnote_matchcase; bool findnote_search_up; bool enable_auto_function; + bool deselect_on_doubleclick; bool silent_autosave; bool tooltips; int current_pattern; diff --git a/src/drivers/win/taseditor/taseditor_lua.cpp b/src/drivers/win/taseditor/taseditor_lua.cpp index 246211a4..0e11ef39 100644 --- a/src/drivers/win/taseditor/taseditor_lua.cpp +++ b/src/drivers/win/taseditor/taseditor_lua.cpp @@ -179,7 +179,7 @@ void TASEDITOR_LUA::setnote(int index, const char* newtext) strncpy(text, newtext, MAX_NOTE_LEN - 1); if (strcmp(markers_manager.GetNote(index).c_str(), text)) { - // text differs from old note - rename + // text differs from old Note - rename markers_manager.SetNote(index, text); history.RegisterMarkersChange(MODTYPE_LUA_MARKER_RENAME, markers_manager.GetMarkerFrame(index), -1, text); selection.must_find_current_marker = playback.must_find_current_marker = true; diff --git a/src/drivers/win/taseditor/taseditor_project.cpp b/src/drivers/win/taseditor/taseditor_project.cpp index a18b3607..6d15e985 100644 --- a/src/drivers/win/taseditor/taseditor_project.cpp +++ b/src/drivers/win/taseditor/taseditor_project.cpp @@ -33,6 +33,8 @@ extern PIANO_ROLL piano_roll; extern SELECTION selection; extern SPLICER splicer; +extern FCEUGI *GameInfo; + extern void FCEU_PrintError(char *format, ...); extern bool SaveProject(); extern bool SaveProjectAs(); @@ -70,59 +72,85 @@ void TASEDITOR_PROJECT::update() } -bool TASEDITOR_PROJECT::save() +bool TASEDITOR_PROJECT::save(const char* different_name, bool save_binary, bool save_markers, bool save_bookmarks, bool save_greenzone, bool save_history, bool save_piano_roll, bool save_selection) { - std::string PFN = GetProjectFile(); - if (PFN.empty()) return false; - const char* filename = PFN.c_str(); - EMUFILE_FILE* ofs = FCEUD_UTF8_fstream(filename, "wb"); + if (!different_name && GetProjectFile().empty()) + // no different name specified, and there's no current filename of the project + return false; - currMovieData.loadFrameCount = currMovieData.records.size(); - currMovieData.dump(ofs, true); - - // save all modules - unsigned int saved_stuff = ALL_SAVED; - write32le(saved_stuff, ofs); - markers_manager.save(ofs); - bookmarks.save(ofs); - greenzone.save(ofs); - history.save(ofs); - piano_roll.save(ofs); - selection.save(ofs); - - delete ofs; - - playback.updateProgressbar(); - this->reset(); - return true; -} -bool TASEDITOR_PROJECT::save_compact(char* filename, bool save_binary, bool save_markers, bool save_bookmarks, bool save_greenzone, bool save_history, bool save_piano_roll, bool save_selection) -{ - EMUFILE_FILE* ofs = FCEUD_UTF8_fstream(filename, "wb"); - - currMovieData.loadFrameCount = currMovieData.records.size(); - currMovieData.dump(ofs, save_binary); - - // save specified modules - unsigned int saved_stuff = 0; - if (save_markers) saved_stuff |= MARKERS_SAVED; - if (save_bookmarks) saved_stuff |= BOOKMARKS_SAVED; - if (save_greenzone) saved_stuff |= GREENZONE_SAVED; - if (save_history) saved_stuff |= HISTORY_SAVED; - if (save_piano_roll) saved_stuff |= PIANO_ROLL_SAVED; - if (save_selection) saved_stuff |= SELECTION_SAVED; - write32le(saved_stuff, ofs); - markers_manager.save(ofs, save_markers); - bookmarks.save(ofs, save_bookmarks); - greenzone.save(ofs, save_greenzone); - history.save(ofs, save_history); - piano_roll.save(ofs, save_piano_roll); - selection.save(ofs, save_selection); - - delete ofs; - - playback.updateProgressbar(); - return true; + // check MD5 + char md5_movie[256]; + char md5_rom[256]; + strcpy(md5_movie, md5_asciistr(currMovieData.romChecksum)); + strcpy(md5_rom, md5_asciistr(GameInfo->MD5)); + if(strcmp(md5_movie, md5_rom)) + { + // checksums mismatch, check if they both aren't zero + unsigned int k, count1 = 0, count2 = 0; + for(k = 0; k < strlen(md5_movie); k++) count1 += md5_movie[k] - '0'; + for(k = 0; k < strlen(md5_rom); k++) count2 += md5_rom[k] - '0'; + if(count1 && count2) + { + // ask user if he wants to fix the checksum before saving + char message[2048]; + strcpy(message, "Movie ROM:\n"); + strncat(message, currMovieData.romFilename.c_str(), 2047 - strlen(message)); + strncat(message, "\nMD5: ", 2047 - strlen(message)); + strncat(message, md5_movie, 2047 - strlen(message)); + strncat(message, "\n\nCurrent ROM: \n", 2047 - strlen(message)); + strncat(message, GameInfo->filename, 2047 - strlen(message)); + strncat(message, "\nMD5: ", 2047 - strlen(message)); + strncat(message, md5_rom, 2047 - strlen(message)); + strncat(message, "\n\nFix the movie header before saving? ", 2047 - strlen(message)); + int answer = MessageBox(taseditor_window.hwndTasEditor, message, "ROM Checksum Mismatch", MB_YESNOCANCEL); + if (answer == IDCANCEL) + { + // cancel saving + return false; + } else if (answer == IDYES) + { + // change ROM data in the movie to current ROM + currMovieData.romFilename = GameInfo->filename; + currMovieData.romChecksum = GameInfo->MD5; + } + } + } + // open file for write + EMUFILE_FILE* ofs = 0; + if (different_name) + ofs = FCEUD_UTF8_fstream(different_name, "wb"); + else + ofs = FCEUD_UTF8_fstream(GetProjectFile().c_str(), "wb"); + if (ofs) + { + currMovieData.loadFrameCount = currMovieData.records.size(); + currMovieData.emuVersion = FCEU_VERSION_NUMERIC; + currMovieData.dump(ofs, save_binary); + // save specified modules + unsigned int saved_stuff = 0; + if (save_markers) saved_stuff |= MARKERS_SAVED; + if (save_bookmarks) saved_stuff |= BOOKMARKS_SAVED; + if (save_greenzone) saved_stuff |= GREENZONE_SAVED; + if (save_history) saved_stuff |= HISTORY_SAVED; + if (save_piano_roll) saved_stuff |= PIANO_ROLL_SAVED; + if (save_selection) saved_stuff |= SELECTION_SAVED; + write32le(saved_stuff, ofs); + markers_manager.save(ofs, save_markers); + bookmarks.save(ofs, save_bookmarks); + greenzone.save(ofs, save_greenzone); + history.save(ofs, save_history); + piano_roll.save(ofs, save_piano_roll); + selection.save(ofs, save_selection); + delete ofs; + playback.updateProgressbar(); + // also reset autosave period if we saved the project to its current filename + if (!different_name) + this->reset(); + return true; + } else + { + return false; + } } bool TASEDITOR_PROJECT::load(char* fullname) { @@ -134,14 +162,43 @@ bool TASEDITOR_PROJECT::load(char* fullname) return false; } - FCEU_printf("\nLoading TAS Editor project %s...\n", fullname); - MovieData tempMovieData = MovieData(); extern bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader); if (LoadFM2(tempMovieData, &ifs, ifs.size(), false)) { + // check MD5 + char md5_original[256]; + char md5_current[256]; + strcpy(md5_original, md5_asciistr(tempMovieData.romChecksum)); + strcpy(md5_current, md5_asciistr(GameInfo->MD5)); + if(strcmp(md5_original, md5_current)) + { + // checksums mismatch, check if they both aren't zero + unsigned int k, count1 = 0, count2 = 0; + for(k = 0; k < strlen(md5_original); k++) count1 += md5_original[k] - '0'; + for(k = 0; k < strlen(md5_current); k++) count2 += md5_current[k] - '0'; + if(count1 && count2) + { + // ask user if he really wants to load the project + char message[2048]; + strcpy(message, "This project was made using different ROM!\n\n"); + strcat(message, "Original ROM:\n"); + strncat(message, tempMovieData.romFilename.c_str(), 2047 - strlen(message)); + strncat(message, "\nMD5: ", 2047 - strlen(message)); + strncat(message, md5_original, 2047 - strlen(message)); + strncat(message, "\n\nCurrent ROM: \n", 2047 - strlen(message)); + strncat(message, GameInfo->filename, 2047 - strlen(message)); + strncat(message, "\nMD5: ", 2047 - strlen(message)); + strncat(message, md5_current, 2047 - strlen(message)); + strncat(message, "\n\nLoad the project anyway? ", 2047 - strlen(message)); + int answer = MessageBox(taseditor_window.hwndTasEditor, message, "ROM Checksum Mismatch", MB_YESNO); + if(answer == IDNO) + return false; + } + } + FCEU_printf("\nLoading TAS Editor project %s...\n", fullname); + // save data to currMovieData and continue loading currMovieData = tempMovieData; - currMovieData.emuVersion = FCEU_VERSION_NUMERIC; LoadSubtitles(currMovieData); } else { diff --git a/src/drivers/win/taseditor/taseditor_project.h b/src/drivers/win/taseditor/taseditor_project.h index c7e83afe..70355b59 100644 --- a/src/drivers/win/taseditor/taseditor_project.h +++ b/src/drivers/win/taseditor/taseditor_project.h @@ -26,7 +26,6 @@ #define HISTORY_SAVED 8 #define PIANO_ROLL_SAVED 16 #define SELECTION_SAVED 32 -#define ALL_SAVED MARKERS_SAVED|BOOKMARKS_SAVED|GREENZONE_SAVED|HISTORY_SAVED|PIANO_ROLL_SAVED|SELECTION_SAVED class TASEDITOR_PROJECT { @@ -36,8 +35,7 @@ public: void reset(); void update(); - bool save(); - bool save_compact(char* filename, bool save_binary, bool save_markers, bool save_bookmarks, bool save_greenzone, bool save_history, bool save_piano_roll, bool save_selection); + bool save(const char* different_name = 0, bool save_binary = true, bool save_markers = true, bool save_bookmarks = true, bool save_greenzone = true, bool save_history = true, bool save_piano_roll = true, bool save_selection = true); bool load(char* fullname); void RenameProject(char* new_fullname); diff --git a/src/drivers/win/taseditor/taseditor_window.cpp b/src/drivers/win/taseditor/taseditor_window.cpp index 4b011ec0..f9b10014 100644 --- a/src/drivers/win/taseditor/taseditor_window.cpp +++ b/src/drivers/win/taseditor/taseditor_window.cpp @@ -441,10 +441,10 @@ void TASEDITOR_WINDOW::UpdateCheckedItems() CheckMenuItem(hmenu, ID_CONFIG_KEYBOARDCONTROLSINPIANOROLL, taseditor_config.keyboard_for_piano_roll?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_CONFIG_SUPERIMPOSE_AFFECTS_PASTE, taseditor_config.superimpose_affects_paste?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_CONFIG_COLUMNSETPATTERNSKIPSLAG, taseditor_config.pattern_skips_lag?MF_CHECKED : MF_UNCHECKED); + CheckMenuItem(hmenu, ID_CONFIG_DESELECTONDOUBLECLICK, taseditor_config.deselect_on_doubleclick?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_CONFIG_SILENTAUTOSAVE, taseditor_config.silent_autosave?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_CONFIG_MUTETURBO, muteTurbo?MF_CHECKED : MF_UNCHECKED); CheckMenuItem(hmenu, ID_HELP_TOOLTIPS, taseditor_config.tooltips?MF_CHECKED : MF_UNCHECKED); - } void TASEDITOR_WINDOW::SetTaseditorInput() @@ -1053,6 +1053,10 @@ BOOL CALLBACK WndprocTasEditor(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPara taseditor_config.pattern_skips_lag ^= 1; taseditor_window.UpdateCheckedItems(); break; + case ID_CONFIG_DESELECTONDOUBLECLICK: + taseditor_config.deselect_on_doubleclick ^= 1; + taseditor_window.UpdateCheckedItems(); + break; case ID_CONFIG_SILENTAUTOSAVE: taseditor_config.silent_autosave ^= 1; taseditor_window.UpdateCheckedItems(); diff --git a/src/drivers/win/window.cpp b/src/drivers/win/window.cpp index 3517fb73..26ef3e3e 100644 --- a/src/drivers/win/window.cpp +++ b/src/drivers/win/window.cpp @@ -73,6 +73,9 @@ #include #include +#include "taseditor/taseditor_window.h" +extern TASEDITOR_WINDOW taseditor_window; + using namespace std; //----Context Menu - Some dynamically added menu items @@ -1225,50 +1228,46 @@ LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) mouseb=wParam; goto proco; + case WM_MOUSEWHEEL: + { + // send the message to TAS Editor + if (taseditor_window.hwndTasEditor) + SendMessage(taseditor_window.hwndTasEditor, msg, wParam, lParam); + return 0; + } + case WM_RBUTTONUP: { - if (rightClickEnabled) + // If TAS Editor is engaged, rightclick shouldn't popup menus, because right button is used with wheel input for TAS Editor's own purposes + if (!FCEUMOV_Mode(MOVIEMODE_TASEDITOR)) { - hfceuxcontext = LoadMenu(fceu_hInstance,"FCEUCONTEXTMENUS"); + if (rightClickEnabled) + { + //If There is a movie loaded in read only + if (GameInfo && FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD|MOVIEMODE_FINISHED) && movie_readonly) + whichContext = 0; // Game+Movie+readonly + //If there is a movie loaded in read+write + else if (GameInfo && FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD|MOVIEMODE_FINISHED) && !movie_readonly) + whichContext = 3; // Game+Movie+readwrite + //If there is a ROM loaded but no movie + else if (GameInfo) + whichContext = 1; // Game+NoMovie + //Else no ROM + else + whichContext = 2; // NoGame - //If There is a movie loaded in read only - if (GameInfo && FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD|MOVIEMODE_FINISHED) && movie_readonly) + hfceuxcontext = LoadMenu(fceu_hInstance,"FCEUCONTEXTMENUS"); + hfceuxcontextsub = GetSubMenu(hfceuxcontext, whichContext); + UpdateContextMenuItems(hfceuxcontextsub, whichContext); + pt.x = LOWORD(lParam); //Get mouse x in terms of client area + pt.y = HIWORD(lParam); //Get mouse y in terms of client area + ClientToScreen(hAppWnd, (LPPOINT) &pt); //Convert client area x,y to screen x,y + TrackPopupMenu(hfceuxcontextsub,TPM_RIGHTBUTTON,(pt.x),(pt.y),0,hWnd,0); //Create menu + } else { - hfceuxcontextsub = GetSubMenu(hfceuxcontext,0); - whichContext = 0; // Game+Movie+readonly + mouseb=wParam; } - - //If there is a movie loaded in read+write - else if (GameInfo && FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD|MOVIEMODE_FINISHED) && !movie_readonly) - { - hfceuxcontextsub = GetSubMenu(hfceuxcontext,3); - whichContext = 3; // Game+Movie+readwrite - } - - - //If there is a ROM loaded but no movie - else if (GameInfo) - { - hfceuxcontextsub = GetSubMenu(hfceuxcontext,1); - whichContext = 1; // Game+NoMovie - } - - //Else no ROM - else - { - hfceuxcontextsub = GetSubMenu(hfceuxcontext,2); - whichContext = 2; // NoGame - } - UpdateContextMenuItems(hfceuxcontextsub, whichContext); - pt.x = LOWORD(lParam); //Get mouse x in terms of client area - pt.y = HIWORD(lParam); //Get mouse y in terms of client area - ClientToScreen(hAppWnd, (LPPOINT) &pt); //Convert client area x,y to screen x,y - TrackPopupMenu(hfceuxcontextsub,TPM_RIGHTBUTTON,(pt.x),(pt.y),0,hWnd,0); //Create menu } - else - { - mouseb=wParam; - } } case WM_MOVE: diff --git a/src/emufile.h b/src/emufile.h index e86f8eea..3888f16f 100644 --- a/src/emufile.h +++ b/src/emufile.h @@ -250,7 +250,8 @@ public: void set_len(s32 length) { len = length; - if(pos>length) pos=length; + if(pos > length) + pos = length; } void trim() { diff --git a/src/movie.cpp b/src/movie.cpp index 4fc2379f..f32848bd 100644 --- a/src/movie.cpp +++ b/src/movie.cpp @@ -44,7 +44,7 @@ extern void AddRecentMovieFile(const char *filename); #include "./drivers/win/taseditor/recorder.h" extern PLAYBACK playback; extern RECORDER recorder; - +extern bool emulator_must_run_taseditor; extern bool TaseditorIsRecording(); #endif @@ -1195,20 +1195,13 @@ bool FCEUMOV_ReadState(EMUFILE* is, uint32 size) { if (currMovieData.loadFrameCount >= 0) { - #ifdef WIN32 +#ifdef WIN32 int result = MessageBox(hAppWnd, "This movie is a TAS Editor project file.\nIt can be modified in TAS Editor only.\n\nOpen it in TAS Editor now?", "Movie Replay", MB_YESNO); if (result == IDYES) - { - extern bool EnterTasEditor(); - extern bool LoadProject(char* fullname); - char fullname[512]; - strcpy(fullname, curMovieFilename); - if (EnterTasEditor()) - LoadProject(fullname); - } - #else + emulator_must_run_taseditor = true; +#else FCEUI_printf("This movie is a TAS Editor project file! It can be modified in TAS Editor only.\nMovie is now Read-Only.\n"); - #endif +#endif movie_readonly = true; } if (FCEU_isFileInArchive(curMovieFilename)) diff --git a/src/state.cpp b/src/state.cpp index d801b4e0..6b584cb6 100644 --- a/src/state.cpp +++ b/src/state.cpp @@ -360,8 +360,10 @@ extern int geniestage; bool FCEUSS_SaveMS(EMUFILE* outstream, int compressionLevel) { - // reset memory_savestate - memory_savestate.set_len(0); + // reinit memory_savestate + // memory_savestate is global variable which already has its vector of bytes, so no need to allocate memory every time we use save/loadstate + memory_savestate.set_len(0); // this also seeks to the beginning + memory_savestate.unfail(); EMUFILE* os = &memory_savestate; @@ -648,10 +650,12 @@ bool FCEUSS_LoadFP(EMUFILE* is, ENUM_SSLOADPARAMS params) int stateversion = FCEU_de32lsb(header + 8); int comprlen = FCEU_de32lsb(header + 12); - // memory_savestate is global variable which already has its vector of bytes + // reinit memory_savestate + // memory_savestate is global variable which already has its vector of bytes, so no need to allocate memory every time we use save/loadstate if ((int)(memory_savestate.get_vec())->size() < totalsize) (memory_savestate.get_vec())->resize(totalsize); memory_savestate.set_len(totalsize); + memory_savestate.unfail(); memory_savestate.fseek(0, SEEK_SET); if(comprlen != -1)