As this thread still seems to have some interest, I will explain how I would approach doing this.
Whenever you create a project in GMS 1, you end up with a collection of folders and GML files. These files are the template for how your project is constructed, and can be read by software like Notepad, or you can even use GMS to make your own tool that will read the contents. No matter how the information is presented (GMS 2 are JSON, whereas GMS 1 is XML..??) these are all just text files, and GMS has the functionality to read and write them.
STEP ONE:
Read the 'Object' directory of the project
For each object you will see a GML document, and it will have this line of text:
GML:
<spriteName><undefined></spriteName>
This is what you will see if there is no sprite attached to the object ( <undefined> )
If it had a sprite, you would see the name shown here instead.
We want to read this line, and remove the start and end brackets to find the content.
Rough code (this is the basic gist only):
Code:
str = file_text_readln(file)
str = string_replace(str, '<spriteName>', '""); // delete string section, and leave empty
str = string_replace(str, '</spriteName>', ""); // delete string section, and leave empty
This would leave just what was between the brackets.
By reading that edited content as a string, we can get it's name (or not). We can ignore it if it has no sprite, or if it has one: save that sprites name to a data structure.
STEP TWO:
We want to know if there is any manual attachment of a sprite, that happens after creation and where it isn't done through the UI / engine. To do this, you have to read and parse all of your code. This isn't quite so straightforward, but it is doable.
Open up the file and read it line by line as a string. Whilst doing this you would use the "string_pos" function to see if there is the presence of code that sets up sprites ("sprite_index" / "draw_sprite" etc)
This would take more effort, but be simpler than trying to find each word in a line, and parsing it. You could try to do each one, and then see if it is actually a resource, and then if it's a sprite. But by doing it this way (looking for any possible coding way of allocating a sprite) you can be much more precise in your searching.
If "string_pos" does find the presence of these strings, then you parse that content and find the sprite name. Then add it to a data structure that holds all of those sprites that were used.
FINALLY:
Having done steps one and two you should now have a list of all the sprites actually used in your project (assuming I haven't overlooked an area where sprites may be called, such as shaders, or even timelines? if so: it's just another file to be read and parsed in the same fashion)
The last step is then editing the project files, and removing any sprites that aren't found on our compiled ACTUAL list.
This is what you will see in the GMX project file (whatever is the name.project)
Code:
<sprites name="sprites">
<sprite>sprites\prop_mask</sprite> // is this present? yes / no - delete if not
<sprite>sprites\sprite1</sprite> // is this present? yes / no - delete if not
<sprite>sprites\sprite4</sprite> // is this present? yes / no - delete if not
<sprite>sprites\sprite3</sprite> // etc
<sprite>sprites\sprite5</sprite> // etc
<sprite>sprites\sprite6</sprite> // etc
</sprites>
Remove here any that aren't used, and then delete them from the sprites directory too.
And there you go: How you can make a "clean up" tool for your projects. It is all just text files to be read and edited, and is what GMS does behind the scenes whenever you alter a projects contents. If you know what you're doing, it's perfectly possible to do it yourself, and make useful utilities that cover some things GMS 1 lacks. GMS 2, for example, has a much more advanced text editor, and this can be replicated in GMS 1 in a not too dissimilar fashion.