How to I clean up my code? It's a mess! I can't even develop it further.

Pages: 12
Thanks for all the help, wow. I'll give sourcenav a try if it's in my repositories. I'll definitely give the facade method a try. I'll try to figure getopt() out. I'll consider using the llvm utilities, but why is early compliance with the newest version so important? I like the idea of stability in the binaries, when I'm programming. Wouldn't trying to run C++ 17 too early cause issues i.e. unknown bugs?

EDIT:
I like to chat with you! ^^

If both of you are on at the same time, and you find a way to PM each other, you could use this websites IRC channel on freenode. I honestly didn't know we had a channel until I found it on Google. The website is freenode.net and the channel is #cplusplus.com.
Last edited on
I'll give sourcenav a try if it's in my repositories.


Consider some of the IDE's as well.

I'll definitely give the facade method a try.


Not sure why one would try to emulate OOP with C, why not just use C++ in that scenario? There is much more to OOP than just inheritance and function overloading. The "overhead" of C++ may not be as bad as you think: The STL in C++ is supposed to be zero overhead. Sure I can understand that there will be a bit of overhead as soon as one adds classes (vtables etc.) but it shouldn't be that bad.

I'll consider using the llvm utilities, but why is early compliance with the newest version so important?


It isn't really. Just that with some compilers (notably MSVC) there was a huge delay (~3 years) before they were C++11 compliant. Apparently they still have bugs with some of the C++11 stuff. As mentioned earlier, they are much better now with their progress towards C++17. But that is irrelevant for you on Linux with gcc. gcc has been pretty good at early compliance too. It's just that one might as well have the most up to date compiler if it's easy to get it.

I like the idea of stability in the binaries, when I'm programming. Wouldn't trying to run C++ 17 too early cause issues i.e. unknown bugs?


Well some of their stuff is still experimental at the moment, but they are careful to say what the status is. So once they say it is OK for use, then it will be. I am pretty sure they have a good reputation in that regard. You can still choose which release version you want, and you don't have to use a C++17 feature if you don't want to.
The STL in C++ is supposed to be zero overhead.

It's zero overhead compared to a hand-coded version of the same thing. The problem is that it's so convenient that it is often used when a much smaller and faster alternative exists. I would have to dig, but I posted an example a few months ago where one proposed solution generated about 15 kbytes of code and a simpler solution was less than 1 kbyte.

It is no doubt true that memory is cheap and size doesn't matter as much as correctness, but there are plenty of applications on small devices where memory is tight. I think it's important for programmers to know the cost of handy solutions.
Get rid of global "saving" flag. First, it shouldn't be a global. Second, You can determine if you're saving by whether safefile is open (initialize it to nullptr). Never use two variables to mean the same thing: it opens you up to a bug by having then set inconsistently.

IfileSize is never used. That means GetIfileSize() is not needed.

Doing a bunch of strcmps in op for every single character processed is very expensive. Instead, create an enum to represent the operations and use a switch statement in op(). This will be very fast. The main program can convert from the operand string to the enum.

This is a filter. Ideally it should read and write from cin/cout rather than requiring the user to specify file names. The big advantage of reading/writing cin/cout is that you can read/write from a pipe.

Here is a version cleaned up a little:
- command line options handled a little more cleanly
- loadfile/savefile are very similar
- comments

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstdint>
#include<cstring>
#include<fstream>
#include <errno.h>
#include <string>
#include <unistd.h>

using std::string;

// WARNING: If you change this enum you must also change operStrings below
enum Oper {add, subtract, multiply, divide, Random, XOR, AND, OR, NOT, MOD};

// Names of the opers. WARNING: These must correspond 1-1 with the Oper's above
static const char * operStrings[] = {
    "add", "sub", "mul", "div", "ran", "xor", "and", "or", "not", "mod",
    nullptr
};


FILE *ifile;
FILE *ofile;

// Just like fopen() but it prints a message to stdout on error
FILE *myfopen(const char *name, const char *mode)
{
    FILE *result = fopen(name, mode);
    if (result == nullptr) {
        printf("Can't open %s: %s\n", name, strerror(errno));
    }
    return result;
}


void
errormsg()
{
    printf("%s", "Syntax error. Syntax is:\n");
    printf("%s",
           "corrupt [switches] <ifile> <ofile> <start> <stop> <every> <operation> <additional>\n");
    printf("%s", "ifile is the path to the input file.\n");
    printf("%s", "ofile is the path to the output file.\n");
    printf("%s", "start is the position in the file to start corrupting.\n");
    printf("%s", "stop is the position in the file to stop corrupting.\n");
    printf("%s", "every is the frequency of memory to ignore.\n");
    printf("%s", "\n");
    printf("%s", "Operations:\n");
    printf("%s", "add   Adds current byte to addative\n");
    printf("%s", "sub   Subtracts current byte from addative\n");
    printf("%s", "mul   Multiplies current byte by addative\n");
    printf("%s", "div   Divides current byte by addative\n");
    printf("%s", "mod   Modular current byte by addative\n");
    printf("%s", "xor   Xor's current byte by addative\n");
    printf("%s", "and   And's current byte by addative\n");
    printf("%s", " or   Or's current byte by addative\n");
    printf("%s", "ran   Randomizes current byte\n");
    printf("%s", "not   Not's current byte\n");
    printf("%s", "\n");
    printf("%s", "Switches:\n");
    printf("%s", "-l [file]     Load corruption from file\n");
    printf("%s", "-v            Output corruptor version\n");
    printf("%s", "-s [file]     Save corruption to file\n");

    exit(1);
}

enum Oper getOper(const string &str)
{
    for (int i=0; operStrings[i]; ++i) {
        if (str == operStrings[i]) {
            return (Oper)i;
        }
    }
    printf("%s is not a valid operation string\n", str.c_str());
    exit(1);
}

char
op(enum Oper oper, char a, char b)
{
    switch(oper) {
    case add:
        return a + b;
        break;
    case subtract:
        return a - b;
        break;
    case multiply:
        return a * b;
        break;
    case divide:
        return a / b;
        break;
    case Random:
        return rand() % 128 - 64;
        break;
    case XOR:
        return a xor b;
        break;
    case AND:
        return a and b;
        break;
    case OR:
        return a or b;
        break;
    case NOT:
        return not(a);
        break;
    case MOD:
        return a % b;
        break;
    }
    return 0;                   // should not be reached.
}


// Corrupt every nth byte in ifile from strt to stop by changing the byte to
// byte <oper> operand
void
corrupt(unsigned long long int start, unsigned long long int stop,
        unsigned int n, enum Oper oper, char operand)
{
    unsigned long long int dimX = 0;
    unsigned int FreqCounter = 0;
    int regbyte;
    while ((regbyte = fgetc(ifile)) != EOF)      //While we haven't reached the end of the file...
    {
        if ((FreqCounter >= n) and((dimX >= start) and(dimX <= stop)))  //And the conditions are juuust right...
        {
            regbyte = op(oper, regbyte, operand);
            putc(regbyte, ofile);
            FreqCounter = 0;                     //corrupt dat byte!
        } else {
            putc(regbyte, ofile);
        }                                        //Or don't...
        FreqCounter = FreqCounter + 1;
        dimX = dimX + 1;                         //counting
    }
    printf("%s", "The file seems to have been successfully corrupted...\n");
}

int
main(int argc, char *argv[])
{
    string opString;
    std::ofstream savefile;
    std::ifstream loadfile;
    int op;

    // These are arguments to corrupt
    unsigned long long start, stop;
    unsigned int frequency;
    enum Oper oper;
    char operand;

    while ((op = getopt(argc, argv, "l:vs:")) != EOF) {
        switch (op) {
        case 'l':
            loadfile.open(optarg);
            if (!loadfile) {
                printf("Can't open %s\n", optarg);
                return 1;
            }
            break;
        case 'v':
            printf("%s", "LAwl\n");
            break;
        case 's':
            savefile.open(optarg);
            if (!savefile) {
                printf("Can't open %s\n", optarg);
                return 1;
            }
            break;
        default:
            errormsg();
        }
    }

    if (optind+2 > argc) errormsg();

    if ((ifile = myfopen(argv[optind++], "rb")) == nullptr) {
        return 1;
    }

    if ((ofile = myfopen(argv[optind++], "wb")) == nullptr) {
        return 1;
    }


    // Now get the corruption options from the command
    // line or loadFile
    if (loadfile.is_open()) {
        int tmp;
        loadfile >> start >> stop >> frequency >> opString >> tmp;
        operand = tmp;
        oper = getOper(opString);
    } else {
        if (optind + 5 > argc) {
            errormsg();
        }
        start = atoi(argv[optind++]);
        stop = atoi(argv[optind++]);
        frequency = atoi(argv[optind++]);
        oper = getOper(argv[optind++]);
        operand = atoi(argv[optind++]);
    }

    // Now you have all the options
    corrupt(start, stop, frequency, oper, operand);

    fclose(ifile);
    fclose(ofile);

    if (savefile.is_open()) {
        savefile << start << '\n'
                 << stop << '\n'
                 << frequency << '\n'
                 << operStrings[(int)oper] << '\n'
                 << operand << '\n';
    }

    return 0;
}

@RealGiganitris
What you want to accomplish is called Code Refactoring. It consists of many small steps. Have alook at the wiki.
https://en.wikipedia.org/wiki/Code_refactoring

There is a excellent tutorial on NetTuts about it - though it's in PHP it might be useful.
http://code.tutsplus.com/tutorials/refactoring-legacy-code-part-1-the-golden-master--cms-20331
I've been lucky enough to get a bit of free time. I'm nowhere near finished, but how's this? Better?

main.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstdint>
#include<cstring>
#include"Portable.h"
char version[16] = "[A.1.3.2]";

char* Settings[8];	//Stores a POINTER to the user settings
char iputCa[8][32];
FILE* iputROM;
uint32_t iputROMsize;
FILE* oputROM;
FILE* iputC;
FILE* oputC;
uint32_t Start;
uint32_t Stop;
uint32_t Period;
char Additional;

void load_from_settings(){
if((iputROM = fopen(Settings[1],"rb")) == NULL){perror(Settings[1]);exit(1);}	//Load the victim ROM file
if((oputROM = fopen(Settings[2],"wb")) == NULL){perror(Settings[2]);exit(1);}	//Load the new ROM file
iputROMsize = GetFileSize(iputROM);			//Get the ROM file size for percentage calcs (not implemented)
Start = FormattedStringToInt(Settings[3]);		//Where to start
Stop =  FormattedStringToInt(Settings[4]);		//Where to stop
Period =  FormattedStringToInt(Settings[5]);		//Period (Reciprocal of the frequency)
Additional =  FormattedStringToInt(Settings[7]);	//Additional value for op(op doesn't need processing, that's why 6 is skipped)
}

char op(char opc){
if(strcmp(Settings[6], "add") == 0){return opc+Additional;}
else if(strcmp(Settings[6], "sub") == 0){return opc-Additional;}
else if(strcmp(Settings[6], "mul") == 0){return opc*Additional;}
else if(strcmp(Settings[6], "div") == 0){return opc/Additional;}
else if(strcmp(Settings[6], "ran") == 0){return rand() % 128 -64;}
else if(strcmp(Settings[6], "xor") == 0){return opc xor Additional;}
else if(strcmp(Settings[6], "and") == 0){return opc and Additional;}
else if(strcmp(Settings[6], "or") == 0){return opc or Additional;}
else if(strcmp(Settings[6], "not") == 0){return not(opc);}
else if(strcmp(Settings[6], "mod") == 0){return opc % Additional;}
else{printf("Error 3 %s\n",Settings[6]);exit(1);}
}

void corrupt(){
uint32_t CdimX = 0;
uint16_t CFreqCounter = 0;
int Cregbyte;
while((Cregbyte = fgetc(iputROM)) != EOF){						//While we haven't reached the end of the file...
	if((CFreqCounter >= Period) and ((CdimX >= Start) and (CdimX <= Stop))){	//And the conditions are juuust right...
		Cregbyte = op(Cregbyte);putc(Cregbyte, oputROM);CFreqCounter = 0;}	//corrupt dat byte!
	else{putc(Cregbyte, oputROM);}							//Or don't...
	CFreqCounter = CFreqCounter +1;CdimX = CdimX +1;}				//counting
perror("");
}

int main(int argc, char* argv[])
{
uint8_t MainArgIndex = 1; 	//which argument to check
uint8_t MainArgSI;		//An index variable for the settings
while(MainArgIndex < argc){	//Begin parsing CMD
MainArgSI = 1; 			//Restore Settings Indexer (so it can be reused)
if(strcmp(argv[MainArgIndex],"-v") == 0){printf("%s\n", version);}		//Output version
else if(strcmp(argv[MainArgIndex],"-s") == 0){					//Create corruption file
	if((argc-(MainArgIndex+1))<0){printf("Error 2 %i %i\n",MainArgIndex,argc);exit(1);}			//Avoid seg fault
	while(MainArgSI != 2){Settings[MainArgSI] = argv[MainArgIndex +MainArgSI];MainArgSI = MainArgSI +1;}	//Load settings
	MainArgIndex = MainArgIndex +1; 									//Restore the cursor
	if((oputC = fopen(Settings[1],"wb")) == NULL){perror(Settings[1]);exit(1);}	//Load the new file
	fputs(version,oputC);
	fputs("\n",oputC);
	fputs(IntToString(Start),oputC);
	fputs("\n",oputC);
	fputs(IntToString(Stop),oputC);
	fputs("\n",oputC);
	fputs(IntToString(Period),oputC);
	fputs("\n",oputC);
	fputs(Settings[6],oputC);
	fputs("\n",oputC);
	fputs(IntToString(Additional),oputC);
	fputs("\n",oputC);
	perror("");
	while(fclose(oputC) == EOF){}	//Close the file as needed
	}	
else if(strcmp(argv[MainArgIndex],"-l") == 0){					//Corrupt using a file
	if((argc-(MainArgIndex+3))<0){printf("Error 2\n");exit(1);}	//Avoid seg fault
	while(MainArgSI != 4){Settings[MainArgSI] = argv[MainArgIndex +MainArgSI];MainArgSI = MainArgSI +1;}	//load settings
	MainArgIndex = MainArgIndex +3; 									//Restore the cursor
	if((iputC = fopen(Settings[1],"rb")) == NULL){perror(Settings[1]);exit(1);}				//Load the instructions
	Settings[1] = Settings[2];
	Settings[2] = Settings[3];
	fgets(iputCa[1],256,iputC);
	fgets(iputCa[2],256,iputC);Settings[3] = iputCa[2];
	fgets(iputCa[3],256,iputC);Settings[4] = iputCa[3];
	fgets(iputCa[4],256,iputC);Settings[5] = iputCa[4];
	fgets(iputCa[5],256,iputC);iputCa[5][3] = '\0';Settings[6] = iputCa[5];
	fgets(iputCa[6],256,iputC);Settings[7] = iputCa[6];
	load_from_settings();
	corrupt();
	while(fclose(iputROM) == EOF){}	//Close the files as needed
	while(fclose(oputROM) == EOF){}	//If you can't close the file, try again
	}
else if(strcmp(argv[MainArgIndex],"-c") == 0){					//Corrupt using settings
	if((argc-(MainArgIndex+7))<0){printf("Error 2\n");exit(1);}						//Avoid seg fault
	while(MainArgSI != 8){Settings[MainArgSI] = argv[MainArgIndex +MainArgSI];MainArgSI = MainArgSI +1;}	//load settings
	MainArgIndex = MainArgIndex +7; //Restore the cursor
	load_from_settings();		//Prepare for corruption
	corrupt();			//Corrupt
	while(fclose(iputROM) == EOF){}	//Close the files as needed
	while(fclose(oputROM) == EOF){}	//If you can't close the file, try again
	}
else{printf("Error 1\n");exit(1);}
MainArgIndex = MainArgIndex +1;
}
}


Portable.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<cstdint>
#include<cstdio>

int32_t GetFileSize(FILE* GetFileSizeFile){
int32_t getfilesizesize = 0;
fseek(GetFileSizeFile, 0L, SEEK_SET);
while(fgetc(GetFileSizeFile) != EOF){getfilesizesize = getfilesizesize +1;}
fseek(GetFileSizeFile, 0L, SEEK_SET);
return getfilesizesize;
}

int32_t FormattedStringToInt(const char* FStoIiS){
//This function will be built upon in the future
return strtol(FStoIiS, NULL, 0);
}

char IntToStrStr[256];
const char* IntToString(int64_t IntToStrInt){
sprintf(IntToStrStr,"%d",IntToStrInt);
return IntToStrStr;
}
at least bother to indent it.
Why do you have fclose() in a loop? If it fails once I don't think it will succeed the next time.
What do you mean at least bother to indent it? What needs indenting? I've heard that fclose may fail sometimes, and that it's best to have it in a loop like that. I'll try to find the resource...
$ dict indent
<text, programming> Space and/or {tab} characters added at the beginning of a
line to indicate structure, e.g. indenting a quotation to make it stand out or
indenting a {block} of code controlled by an {if statement}.

Indentation is important in {source code} for readability.  There are a number
of different {indent styles}.  Some programming languages go further and use
indentation as the main method to represent block structure to the {compiler}
or {interpreter}, see {off-side rule}.

What do you mean at least bother to indent it? What needs indenting?


Well, all of it. As mentioned earlier, have a go with a code formatter: Astyle or llvm-format for example. You could do with more vertical white space, white space around operators, avoid several statements on 1 line, indent block statements.

This program is probably too small to warrant splitting up, but if you figure out how to do this, then you will know what to do when your code base gets a little larger - like 5000 LOC say :+)

So you have started with more use of functions into a separate files, but you shouldn't have implementation code in header files. Just like C++ with classes, one has header files with declarations of functions, then function implementations in the .c or .cpp files. Should still have header guards, or #pragma once maybe - it's not standard, but is widely supported by compilers.

https://en.wikipedia.org/wiki/Pragma_once


You could aim to not have any function definitions in main.cpp. Even for small programs, I like to put function definitions after main, purely so that main is at the top of the file.

Do you have to have that many global variables? I know it's easy, but it is not usually a good sign.
Yeah, all of them are necessary. The program will not run (properly without segfaults) otherwise.

Also, all lines are indented for the contents of if statements, while loops and so on. What's missing?
Last edited on
By convention, only things at global scope should not be indented. The contents of your functions are not at global scope, therefore they should be indented.

I cannot look at your code and easily tell where your plethora of global variables end and your functions begin (or end.)
Yeah, all of them are necessary. The program will not run (properly without segfaults) otherwise.


Disagree, it should always be possible to re-factor so there are no global variables. You could start by declaring them in main, then send them as arguments to whatever function needs them. There might even be some that could be local to a function.

Also, all lines are indented for the contents of if statements, while loops and so on. What's missing?


You almost* get away with having the same indentation because you have multiple statements on 1 line.

* The while loop on line 61 of main, everything in it should be indented one level.

Right, so I ran your code through clang formatter, which I have in my IDE. I also put comments before code, not after. There were a number of places where I used ++a; rather than a =a +1;, and a couple of += operator. I also added a little bit more vertical white space.

Also for some of the functions with no arguments, I made the parameter void. This is because the code is essentially C, so that is a little defensive measure in case it is compiled as C one day.

The else if statements in main could call functions IMO, that would be much easier to read.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cstring>
#include "Portable.h"
char version[16] = "[A.1.3.2]";

char *Settings[8]; // Stores a POINTER to the user settings
char iputCa[8][32];
FILE *iputROM;
uint32_t iputROMsize;
FILE *oputROM;
FILE *iputC;
FILE *oputC;
uint32_t Start;
uint32_t Stop;
uint32_t Period;
char Additional;


void load_from_settings(void); // Load the victim ROM file
char op(char opc);
void corrupt(void);

int main(int argc, char *argv[]) {
  uint8_t MainArgIndex = 1; // which argument to check
  uint8_t MainArgSI; // An index variable for the settings

  // Begin parsing CMD
  while (MainArgIndex < argc) {
    MainArgSI = 1; // Restore Settings Indexer (so it can be reused)

    // Output version
    if (strcmp(argv[MainArgIndex], "-v") == 0) {
      printf("%s\n", version);
    }
    else if (strcmp(argv[MainArgIndex], "-s") == 0) { // Create corruption file

      // Avoid seg fault
      if ((argc - (MainArgIndex + 1)) < 0) {
        printf("Error 2 %i %i\n", MainArgIndex, argc);
        exit(1);
      }

      // Load settings
      while (MainArgSI != 2) {
        Settings[MainArgSI] = argv[MainArgIndex + MainArgSI];
        ++MainArgSI;
      }

      ++MainArgIndex; // Restore the cursor

      // Load the new file
      if ((oputC = fopen(Settings[1], "wb")) == NULL) {
        perror(Settings[1]);
        exit(1);
      }

      fputs(version, oputC);
      fputs("\n", oputC);
      fputs(IntToString(Start), oputC);
      fputs("\n", oputC);
      fputs(IntToString(Stop), oputC);
      fputs("\n", oputC);
      fputs(IntToString(Period), oputC);
      fputs("\n", oputC);
      fputs(Settings[6], oputC);
      fputs("\n", oputC);
      fputs(IntToString(Additional), oputC);
      fputs("\n", oputC);
      perror("");

      // Close the file as needed
      while (fclose(oputC) == EOF) {
      }
    } else if ( strcmp(argv[MainArgIndex], "-l") == 0 ) { // Corrupt using a file
      // Avoid seg fault
      if ((argc - (MainArgIndex + 3)) < 0) {
        printf("Error 2\n");
        exit(1);
      }

      // load settings
      while (MainArgSI != 4) {
        Settings[MainArgSI] = argv[MainArgIndex + MainArgSI];
        ++MainArgSI;
      }
      MainArgIndex += 3; // Restore the cursor

      // Load the instructions
      if ( (iputC = fopen(Settings[1], "rb") ) == NULL ) {
        perror(Settings[1]);
        exit(1);
      }

      Settings[1] = Settings[2];
      Settings[2] = Settings[3];
      fgets(iputCa[1], 256, iputC);
      fgets(iputCa[2], 256, iputC);
      Settings[3] = iputCa[2];
      fgets(iputCa[3], 256, iputC);
      Settings[4] = iputCa[3];
      fgets(iputCa[4], 256, iputC);
      Settings[5] = iputCa[4];
      fgets(iputCa[5], 256, iputC);
      iputCa[5][3] = '\0';
      Settings[6] = iputCa[5];
      fgets(iputCa[6], 256, iputC);
      Settings[7] = iputCa[6];
      load_from_settings();
      corrupt();

      // Close the files as needed
      while (fclose(iputROM) == EOF) {
      }
      // If you can't close the file, try again
      while (fclose(oputROM) == EOF) {
      }

    } else if (strcmp(argv[MainArgIndex], "-c") == 0) { // Corrupt using settings
      // Avoid seg fault
      if ((argc - (MainArgIndex + 7)) < 0) {
        printf("Error 2\n");
        exit(1);
      }

      // load settings
      while (MainArgSI != 8) {
        Settings[MainArgSI] = argv[MainArgIndex + MainArgSI];
        ++MainArgSI;
      }

      MainArgIndex += 7; // Restore the cursor
      load_from_settings(); // Prepare for corruption
      corrupt(); // Corrupt

      // Close the files as needed
      while (fclose(iputROM) == EOF) {
      }
      // If you can't close the file, try again
      while (fclose(oputROM) == EOF) {
      }
    } else {
      printf("Error 1\n");
      exit(1);
    }
    MainArgIndex += 1;
  }
}

void corrupt(void) {
  uint32_t CdimX = 0;
  uint16_t CFreqCounter = 0;
  int Cregbyte;

  // While we haven't reached the end of the file...
  while ((Cregbyte = fgetc(iputROM)) !=EOF) {
    // And the conditions are juuust right...
    if ((CFreqCounter >= Period) and
        ((CdimX >= Start) and
         (CdimX <= Stop))) {
      // corrupt dat byte!
      Cregbyte = op(Cregbyte);
      putc(Cregbyte, oputROM);
      CFreqCounter = 0;
    }
    // Or don't...
    else {
      putc(Cregbyte, oputROM);
    }
    // counting
    ++CFreqCounter;
    ++CdimX;
  }
  perror("");
}

char op(char opc) {
  if (strcmp(Settings[6], "add") == 0) {
    return opc + Additional;
  } else if (strcmp(Settings[6], "sub") == 0) {
    return opc - Additional;
  } else if (strcmp(Settings[6], "mul") == 0) {
    return opc * Additional;
  } else if (strcmp(Settings[6], "div") == 0) {
    return opc / Additional;
  } else if (strcmp(Settings[6], "ran") == 0) {
    return rand() % 128 - 64;
  } else if (strcmp(Settings[6], "xor") == 0) {
    return opc xor Additional;
  } else if (strcmp(Settings[6], "and") == 0) {
    return opc and Additional;
  } else if (strcmp(Settings[6], "or") == 0) {
    return opc or Additional;
  } else if (strcmp(Settings[6], "not") == 0) {
    return not(opc);
  } else if (strcmp(Settings[6], "mod") == 0) {
    return opc % Additional;
  } else {
    printf("Error 3 %s\n", Settings[6]);
    exit(1);
  }
}

void load_from_settings(void) {
  if ((iputROM = fopen(Settings[1], "rb")) == NULL) {
    perror(Settings[1]);
    exit(1);
  }

  // Load the new ROM file
  if ((oputROM = fopen(Settings[2], "wb")) == NULL) {
    perror(Settings[2]);
    exit(1);
  }

  // Get the ROM file size for percentage calcs (not implemented)
  iputROMsize = GetFileSize(iputROM);
  // Where to start
  Start = FormattedStringToInt(Settings[3]);
  // Where to stop
  Stop = FormattedStringToInt(Settings[4]);
  // Period (Reciprocal of the frequency)
  Period = FormattedStringToInt(Settings[5]);
  // Additional value for op(op doesn't need processing, that's why 6 is skipped)
  Additional = FormattedStringToInt(Settings[7]);

}



Last edited on
Topic archived. No new replies allowed.
Pages: 12