* 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
This commit is contained in:
ansstuff 2012-03-09 15:20:51 +00:00
parent 9722ac44c7
commit 0638d88ff9
21 changed files with 554 additions and 144 deletions

View File

@ -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);

View File

@ -347,6 +347,7 @@ static CFGSTRUCT fceuconfig[] = {
AC(taseditor_config.savecompact_selection), AC(taseditor_config.savecompact_selection),
AC(taseditor_config.findnote_matchcase), AC(taseditor_config.findnote_matchcase),
AC(taseditor_config.findnote_search_up), AC(taseditor_config.findnote_search_up),
AC(taseditor_config.deselect_on_doubleclick),
AC(taseditor_config.silent_autosave), AC(taseditor_config.silent_autosave),
AC(taseditor_config.tooltips), AC(taseditor_config.tooltips),
AC(taseditor_config.current_pattern), AC(taseditor_config.current_pattern),

View File

@ -289,7 +289,9 @@ BEGIN
MENUITEM "Use Input keys for Column Set", ID_CONFIG_USEINPUTKEYSFORCOLUMNSET,MFT_STRING,MFS_ENABLED 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 "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 "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 "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 MFT_SEPARATOR
MENUITEM "Silent Autosave", ID_CONFIG_SILENTAUTOSAVE,MFT_STRING,MFS_ENABLED MENUITEM "Silent Autosave", ID_CONFIG_SILENTAUTOSAVE,MFT_STRING,MFS_ENABLED
MENUITEM "Mute Turbo", ID_CONFIG_MUTETURBO,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 "TAS Editor",IDC_TASEDITOR_NAME,43,8,83,13
LTEXT "Version 1.0",IDC_STATIC,63,25,37,8 LTEXT "Version 1.0",IDC_STATIC,63,25,37,8
LTEXT "Created by AnS",IDC_STATIC,138,12,52,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 LTEXT "made by zeromus & adelikat",IDC_STATIC,138,35,96,9,SS_NOPREFIX
END END

View File

@ -994,6 +994,7 @@
#define ID_CONFIG_COLUMNSETPATTERNSKIPSLAG 40535 #define ID_CONFIG_COLUMNSETPATTERNSKIPSLAG 40535
#define ID_EDIT_DESELECT 40536 #define ID_EDIT_DESELECT 40536
#define ID_SELECTED_DESELECT 40537 #define ID_SELECTED_DESELECT 40537
#define ID_CONFIG_DESELECTONDOUBLECLICK 40538
#define IDC_DEBUGGER_ICONTRAY 55535 #define IDC_DEBUGGER_ICONTRAY 55535
#define MW_ValueLabel2 65423 #define MW_ValueLabel2 65423
#define MW_ValueLabel1 65426 #define MW_ValueLabel1 65426
@ -1003,7 +1004,7 @@
#ifdef APSTUDIO_INVOKED #ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS #ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 206 #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_CONTROL_VALUE 1281
#define _APS_NEXT_SYMED_VALUE 101 #define _APS_NEXT_SYMED_VALUE 101
#endif #endif

View File

@ -23,11 +23,11 @@ Main - Logical center of the program
#include "utils/xstring.h" #include "utils/xstring.h"
#include "main.h" // for GetRomName #include "main.h" // for GetRomName
#include "taseditor.h" #include "taseditor.h"
#include "version.h"
using namespace std; using namespace std;
// TAS Editor data // TAS Editor data
bool emulator_must_run_taseditor = false;
bool Taseditor_rewind_now = false; bool Taseditor_rewind_now = false;
bool must_call_manual_lua_function = false; bool must_call_manual_lua_function = false;
std::vector<std::string> autofire_patterns_names; std::vector<std::string> autofire_patterns_names;
@ -193,7 +193,6 @@ bool EnterTasEditor()
} }
FCEUI_StopMovie(); FCEUI_StopMovie();
movieMode = MOVIEMODE_TASEDITOR; movieMode = MOVIEMODE_TASEDITOR;
currMovieData.emuVersion = FCEU_VERSION_NUMERIC;
} }
// ensure that movie has correct set of ports/fourscore // ensure that movie has correct set of ports/fourscore
SetInputType(currMovieData, GetInputType(currMovieData)); SetInputType(currMovieData, GetInputType(currMovieData));
@ -278,6 +277,14 @@ void UpdateTasEditor()
{ {
// TAS Editor is not engaged... but we still should run Lua auto function // TAS Editor is not engaged... but we still should run Lua auto function
TaseditorAutoFunction(); TaseditorAutoFunction();
if (emulator_must_run_taseditor)
{
char fullname[512];
strcpy(fullname, curMovieFilename);
if (EnterTasEditor())
LoadProject(fullname);
emulator_must_run_taseditor = false;
}
return; return;
} }
@ -514,10 +521,14 @@ bool SaveProjectAs()
} }
bool SaveProject() bool SaveProject()
{ {
if (!project.save()) if (project.GetProjectFile().empty())
{
return SaveProjectAs(); return SaveProjectAs();
else } else
{
project.save();
taseditor_window.UpdateCaption(); taseditor_window.UpdateCaption();
}
return true; return true;
} }
@ -628,9 +639,7 @@ void SaveCompact()
ofn.lpstrInitialDir = initdir.c_str(); ofn.lpstrInitialDir = initdir.c_str();
if(GetSaveFileName(&ofn)) //If it is a valid filename if(GetSaveFileName(&ofn)) //If it is a valid filename
{ 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);
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);
}
} }
} }

View File

@ -344,9 +344,13 @@ void BOOKMARKS::set(int slot)
// save time of this slot before rewriting it // save time of this slot before rewriting it
char saved_time[TIME_DESC_LENGTH]; char saved_time[TIME_DESC_LENGTH];
if (bookmarks_array[slot].not_empty) 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; saved_time[0] = 0;
}
bookmarks_array[slot].set(); bookmarks_array[slot].set();
@ -369,7 +373,7 @@ void BOOKMARKS::set(int slot)
break; break;
} }
if (i >= TOTAL_BOOKMARKS) 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); strcpy(cloud_time, saved_time);
} }
// before disconnecting from old parent, connect all childs to the old parent // before disconnecting from old parent, connect all childs to the old parent

View File

@ -2,7 +2,7 @@
#define GREENZONE_ID_LEN 10 #define GREENZONE_ID_LEN 10
#define TIME_BETWEEN_CLEANINGS 10000 // in milliseconds #define TIME_BETWEEN_CLEANINGS 15000 // in milliseconds
// greenzone cleaning masks // greenzone cleaning masks
#define EVERY16TH 0xFFFFFFF0 #define EVERY16TH 0xFFFFFFF0
#define EVERY8TH 0xFFFFFFF8 #define EVERY8TH 0xFFFFFFF8

View File

@ -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) } else if((cell_x - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS == 0 || (cell_x - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS == 2)
{ {
// pad 1 or 3 // pad 1 or 3
// font // font: empty cells have "SelectFont", non-empty have normal font
SelectObject(msg->nmcd.hdc, hMainListFont); 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<<bit)) )
SelectObject(msg->nmcd.hdc, hMainListFont);
else
SelectObject(msg->nmcd.hdc, hMainListSelectFont);
// bg // bg
if (cell_y == history.GetUndoHint()) 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) } else if((cell_x - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS == 1 || (cell_x - COLUMN_JOYPAD1_A) / NUM_JOYPAD_BUTTONS == 3)
{ {
// pad 2 or 4 // pad 2 or 4
// font // font: empty cells have "SelectFont", non-empty have normal font
SelectObject(msg->nmcd.hdc, hMainListFont); 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<<bit)) )
SelectObject(msg->nmcd.hdc, hMainListFont);
else
SelectObject(msg->nmcd.hdc, hMainListSelectFont);
// bg // bg
if (cell_y == history.GetUndoHint()) 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) if(column_index == COLUMN_ICONS)
{ {
// click on the "icons" column - jump to the frame // click on the "icons" column - jump to the frame
selection.ClearSelection();
playback.jump(row_index); playback.jump(row_index);
} else if(column_index == COLUMN_FRAMENUM || column_index == COLUMN_FRAMENUM2) } 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) if (msg == WM_LBUTTONDBLCLK && !alt_pressed)
{ {
// doubleclick - jump to the frame // doubleclick - jump to the frame
selection.ClearSelection(); if (taseditor_config.deselect_on_doubleclick)
selection.ClearSelection();
playback.jump(row_index); playback.jump(row_index);
} else } else
{ {

View File

@ -182,14 +182,18 @@ void RECORDER::update()
// call ColumnSet if needed // call ColumnSet if needed
if (taseditor_config.columnset_by_keys && movie_readonly && taseditor_window.TASEditor_focus) if (taseditor_config.columnset_by_keys && movie_readonly && taseditor_window.TASEditor_focus)
{ {
bool alt_pressed = ((GetAsyncKeyState(VK_MENU) & 0x8000) != 0); // if Ctrl or Shift is held, do not call ColumnSet, because maybe this is accelerator
for (int joy = 0; joy < num_joys; ++joy) 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 for (int button = 0; button < NUM_JOYPAD_BUTTONS; ++button)
if ((current_joy[joy] & (1 << button)) && !(old_joy[joy] & (1 << button))) {
piano_roll.ColumnSet(COLUMN_JOYPAD1_A + joy * NUM_JOYPAD_BUTTONS + button, alt_pressed); // 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);
}
} }
} }
} }

View File

@ -463,7 +463,8 @@ void SELECTION::EnforceSelectionToList()
void SELECTION::SelectAll() 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) void SELECTION::SetRowSelection(int index)
{ {
@ -472,7 +473,7 @@ void SELECTION::SetRowSelection(int index)
void SELECTION::SetRegionSelection(int start, int end) void SELECTION::SetRegionSelection(int start, int end)
{ {
for (int i = start; i < end; ++i) 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() void SELECTION::SelectBetweenMarkers()
{ {
@ -510,7 +511,7 @@ void SELECTION::SelectBetweenMarkers()
// default: select all between markers // default: select all between markers
for (int i = upper_marker+1; i < lower_marker; ++i) 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) } 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; if (lower_marker >= movie_size) lower_marker = movie_size - 1;
for (int i = upper_marker; i <= lower_marker; ++i) 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) } else if (upper_border <= upper_marker && lower_border >= lower_marker)
{ {
// selected all between markers and both markers selected too - now deselect lower marker // selected all between markers and both markers selected too - now deselect lower marker
for (int i = upper_marker; i < lower_marker; ++i) 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) } 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; if (lower_marker >= movie_size) lower_marker = movie_size - 1;
for (int i = upper_marker+1; i <= lower_marker; ++i) 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) } 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") // 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) 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);
} }
} }
} }

View File

@ -547,6 +547,9 @@ bool SPLICER::Paste()
} }
} }
result = true; result = true;
} else
{
SetWindowText(hwndTextClipboard, clipboardEmptyText);
} }
GlobalUnlock(hGlobal); GlobalUnlock(hGlobal);
} }
@ -664,6 +667,9 @@ bool SPLICER::PasteInsert()
} }
} }
result = true; result = true;
} else
{
SetWindowText(hwndTextClipboard, clipboardEmptyText);
} }
GlobalUnlock(hGlobal); GlobalUnlock(hGlobal);
} }

View File

@ -70,6 +70,7 @@ TASEDITOR_CONFIG::TASEDITOR_CONFIG()
findnote_matchcase = false; findnote_matchcase = false;
findnote_search_up = false; findnote_search_up = false;
enable_auto_function = true; enable_auto_function = true;
deselect_on_doubleclick = true;
silent_autosave = true; silent_autosave = true;
tooltips = true; tooltips = true;
current_pattern = 0; current_pattern = 0;

View File

@ -68,6 +68,7 @@ public:
bool findnote_matchcase; bool findnote_matchcase;
bool findnote_search_up; bool findnote_search_up;
bool enable_auto_function; bool enable_auto_function;
bool deselect_on_doubleclick;
bool silent_autosave; bool silent_autosave;
bool tooltips; bool tooltips;
int current_pattern; int current_pattern;

View File

@ -179,7 +179,7 @@ void TASEDITOR_LUA::setnote(int index, const char* newtext)
strncpy(text, newtext, MAX_NOTE_LEN - 1); strncpy(text, newtext, MAX_NOTE_LEN - 1);
if (strcmp(markers_manager.GetNote(index).c_str(), text)) 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); markers_manager.SetNote(index, text);
history.RegisterMarkersChange(MODTYPE_LUA_MARKER_RENAME, markers_manager.GetMarkerFrame(index), -1, text); history.RegisterMarkersChange(MODTYPE_LUA_MARKER_RENAME, markers_manager.GetMarkerFrame(index), -1, text);
selection.must_find_current_marker = playback.must_find_current_marker = true; selection.must_find_current_marker = playback.must_find_current_marker = true;

View File

@ -33,6 +33,8 @@ extern PIANO_ROLL piano_roll;
extern SELECTION selection; extern SELECTION selection;
extern SPLICER splicer; extern SPLICER splicer;
extern FCEUGI *GameInfo;
extern void FCEU_PrintError(char *format, ...); extern void FCEU_PrintError(char *format, ...);
extern bool SaveProject(); extern bool SaveProject();
extern bool SaveProjectAs(); 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 (!different_name && GetProjectFile().empty())
if (PFN.empty()) return false; // no different name specified, and there's no current filename of the project
const char* filename = PFN.c_str(); return false;
EMUFILE_FILE* ofs = FCEUD_UTF8_fstream(filename, "wb");
currMovieData.loadFrameCount = currMovieData.records.size(); // check MD5
currMovieData.dump(ofs, true); char md5_movie[256];
char md5_rom[256];
// save all modules strcpy(md5_movie, md5_asciistr(currMovieData.romChecksum));
unsigned int saved_stuff = ALL_SAVED; strcpy(md5_rom, md5_asciistr(GameInfo->MD5));
write32le(saved_stuff, ofs); if(strcmp(md5_movie, md5_rom))
markers_manager.save(ofs); {
bookmarks.save(ofs); // checksums mismatch, check if they both aren't zero
greenzone.save(ofs); unsigned int k, count1 = 0, count2 = 0;
history.save(ofs); for(k = 0; k < strlen(md5_movie); k++) count1 += md5_movie[k] - '0';
piano_roll.save(ofs); for(k = 0; k < strlen(md5_rom); k++) count2 += md5_rom[k] - '0';
selection.save(ofs); if(count1 && count2)
{
delete ofs; // ask user if he wants to fix the checksum before saving
char message[2048];
playback.updateProgressbar(); strcpy(message, "Movie ROM:\n");
this->reset(); strncat(message, currMovieData.romFilename.c_str(), 2047 - strlen(message));
return true; strncat(message, "\nMD5: ", 2047 - strlen(message));
} strncat(message, md5_movie, 2047 - strlen(message));
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) strncat(message, "\n\nCurrent ROM: \n", 2047 - strlen(message));
{ strncat(message, GameInfo->filename, 2047 - strlen(message));
EMUFILE_FILE* ofs = FCEUD_UTF8_fstream(filename, "wb"); strncat(message, "\nMD5: ", 2047 - strlen(message));
strncat(message, md5_rom, 2047 - strlen(message));
currMovieData.loadFrameCount = currMovieData.records.size(); strncat(message, "\n\nFix the movie header before saving? ", 2047 - strlen(message));
currMovieData.dump(ofs, save_binary); int answer = MessageBox(taseditor_window.hwndTasEditor, message, "ROM Checksum Mismatch", MB_YESNOCANCEL);
if (answer == IDCANCEL)
// save specified modules {
unsigned int saved_stuff = 0; // cancel saving
if (save_markers) saved_stuff |= MARKERS_SAVED; return false;
if (save_bookmarks) saved_stuff |= BOOKMARKS_SAVED; } else if (answer == IDYES)
if (save_greenzone) saved_stuff |= GREENZONE_SAVED; {
if (save_history) saved_stuff |= HISTORY_SAVED; // change ROM data in the movie to current ROM
if (save_piano_roll) saved_stuff |= PIANO_ROLL_SAVED; currMovieData.romFilename = GameInfo->filename;
if (save_selection) saved_stuff |= SELECTION_SAVED; currMovieData.romChecksum = GameInfo->MD5;
write32le(saved_stuff, ofs); }
markers_manager.save(ofs, save_markers); }
bookmarks.save(ofs, save_bookmarks); }
greenzone.save(ofs, save_greenzone); // open file for write
history.save(ofs, save_history); EMUFILE_FILE* ofs = 0;
piano_roll.save(ofs, save_piano_roll); if (different_name)
selection.save(ofs, save_selection); ofs = FCEUD_UTF8_fstream(different_name, "wb");
else
delete ofs; ofs = FCEUD_UTF8_fstream(GetProjectFile().c_str(), "wb");
if (ofs)
playback.updateProgressbar(); {
return true; 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) bool TASEDITOR_PROJECT::load(char* fullname)
{ {
@ -134,14 +162,43 @@ bool TASEDITOR_PROJECT::load(char* fullname)
return false; return false;
} }
FCEU_printf("\nLoading TAS Editor project %s...\n", fullname);
MovieData tempMovieData = MovieData(); MovieData tempMovieData = MovieData();
extern bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader); extern bool LoadFM2(MovieData& movieData, EMUFILE* fp, int size, bool stopAfterHeader);
if (LoadFM2(tempMovieData, &ifs, ifs.size(), false)) 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 = tempMovieData;
currMovieData.emuVersion = FCEU_VERSION_NUMERIC;
LoadSubtitles(currMovieData); LoadSubtitles(currMovieData);
} else } else
{ {

View File

@ -26,7 +26,6 @@
#define HISTORY_SAVED 8 #define HISTORY_SAVED 8
#define PIANO_ROLL_SAVED 16 #define PIANO_ROLL_SAVED 16
#define SELECTION_SAVED 32 #define SELECTION_SAVED 32
#define ALL_SAVED MARKERS_SAVED|BOOKMARKS_SAVED|GREENZONE_SAVED|HISTORY_SAVED|PIANO_ROLL_SAVED|SELECTION_SAVED
class TASEDITOR_PROJECT class TASEDITOR_PROJECT
{ {
@ -36,8 +35,7 @@ public:
void reset(); void reset();
void update(); void update();
bool save(); 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 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 load(char* fullname); bool load(char* fullname);
void RenameProject(char* new_fullname); void RenameProject(char* new_fullname);

View File

@ -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_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_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_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_SILENTAUTOSAVE, taseditor_config.silent_autosave?MF_CHECKED : MF_UNCHECKED);
CheckMenuItem(hmenu, ID_CONFIG_MUTETURBO, muteTurbo?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); CheckMenuItem(hmenu, ID_HELP_TOOLTIPS, taseditor_config.tooltips?MF_CHECKED : MF_UNCHECKED);
} }
void TASEDITOR_WINDOW::SetTaseditorInput() 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_config.pattern_skips_lag ^= 1;
taseditor_window.UpdateCheckedItems(); taseditor_window.UpdateCheckedItems();
break; break;
case ID_CONFIG_DESELECTONDOUBLECLICK:
taseditor_config.deselect_on_doubleclick ^= 1;
taseditor_window.UpdateCheckedItems();
break;
case ID_CONFIG_SILENTAUTOSAVE: case ID_CONFIG_SILENTAUTOSAVE:
taseditor_config.silent_autosave ^= 1; taseditor_config.silent_autosave ^= 1;
taseditor_window.UpdateCheckedItems(); taseditor_window.UpdateCheckedItems();

View File

@ -73,6 +73,9 @@
#include <sstream> #include <sstream>
#include <cmath> #include <cmath>
#include "taseditor/taseditor_window.h"
extern TASEDITOR_WINDOW taseditor_window;
using namespace std; using namespace std;
//----Context Menu - Some dynamically added menu items //----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; mouseb=wParam;
goto proco; 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: 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 hfceuxcontext = LoadMenu(fceu_hInstance,"FCEUCONTEXTMENUS");
if (GameInfo && FCEUMOV_Mode(MOVIEMODE_PLAY|MOVIEMODE_RECORD|MOVIEMODE_FINISHED) && movie_readonly) 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); mouseb=wParam;
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)
{
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: case WM_MOVE:

View File

@ -250,7 +250,8 @@ public:
void set_len(s32 length) void set_len(s32 length)
{ {
len = length; len = length;
if(pos>length) pos=length; if(pos > length)
pos = length;
} }
void trim() void trim()
{ {

View File

@ -44,7 +44,7 @@ extern void AddRecentMovieFile(const char *filename);
#include "./drivers/win/taseditor/recorder.h" #include "./drivers/win/taseditor/recorder.h"
extern PLAYBACK playback; extern PLAYBACK playback;
extern RECORDER recorder; extern RECORDER recorder;
extern bool emulator_must_run_taseditor;
extern bool TaseditorIsRecording(); extern bool TaseditorIsRecording();
#endif #endif
@ -1195,20 +1195,13 @@ bool FCEUMOV_ReadState(EMUFILE* is, uint32 size)
{ {
if (currMovieData.loadFrameCount >= 0) 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); 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) if (result == IDYES)
{ emulator_must_run_taseditor = true;
extern bool EnterTasEditor(); #else
extern bool LoadProject(char* fullname);
char fullname[512];
strcpy(fullname, curMovieFilename);
if (EnterTasEditor())
LoadProject(fullname);
}
#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"); 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; movie_readonly = true;
} }
if (FCEU_isFileInArchive(curMovieFilename)) if (FCEU_isFileInArchive(curMovieFilename))

View File

@ -360,8 +360,10 @@ extern int geniestage;
bool FCEUSS_SaveMS(EMUFILE* outstream, int compressionLevel) bool FCEUSS_SaveMS(EMUFILE* outstream, int compressionLevel)
{ {
// reset memory_savestate // reinit memory_savestate
memory_savestate.set_len(0); // 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; EMUFILE* os = &memory_savestate;
@ -648,10 +650,12 @@ bool FCEUSS_LoadFP(EMUFILE* is, ENUM_SSLOADPARAMS params)
int stateversion = FCEU_de32lsb(header + 8); int stateversion = FCEU_de32lsb(header + 8);
int comprlen = FCEU_de32lsb(header + 12); 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) if ((int)(memory_savestate.get_vec())->size() < totalsize)
(memory_savestate.get_vec())->resize(totalsize); (memory_savestate.get_vec())->resize(totalsize);
memory_savestate.set_len(totalsize); memory_savestate.set_len(totalsize);
memory_savestate.unfail();
memory_savestate.fseek(0, SEEK_SET); memory_savestate.fseek(0, SEEK_SET);
if(comprlen != -1) if(comprlen != -1)