Teile einer Zeile einer .txt Datei lesen und in eine ROM schreiben
-
Kazeshin schrieb:
Das ist mein Problem. Ich weiß nicht, wie das geht.
Das solltest du irgendwie herausfinden. Hier kann leider niemand hellsehen und solange selbst du nicht weißt, was du genau machen möchtest, wird dir daher leider keiner helfen können.
-
TNA schrieb:
Kazeshin schrieb:
Das ist mein Problem. Ich weiß nicht, wie das geht.
Das solltest du irgendwie herausfinden. Hier kann leider niemand hellsehen und solange selbst du nicht weißt, was du genau machen möchtest, wird dir daher leider keiner helfen können.
ich weiß, was ich damit tun will, das Problem ist nur, dass ich nicht weiß, wie ich diese Daten hereinbekomme. Sie sollen an eine bestimmte Stelle der Datei geschrieben werden. so wie ich es kenne, gibt es für jede 2. Hexadezimalstelle eine Addresse. Ich will die Zahlen an die Addresse BEA20 schreiben.
Nathan schrieb:
OK, mal ganz anders gefragt:
Was willst du mit diesen Zahlen im ROM erreichen?Ich habe einen Assembler code für die N64 geschrieben, der die Zahlen ausliest. Dadurch erhält das Spiel ein "ingame gameshark device", das wie ein echte funktioniert. Das soll für Romhacks nützlich sein

Das Problem ist halt, dass es für den Nutzer verdammt nervig sein wird, 1000 (wirklich 1000 ._.) Ziffern einzutippen.
-
Hallo Kazeshin,
Willkommen im C++-Forum.
Erzähl mal ein wenig vom Hintergrund; dann können wir Dir auch besser helfen.
Wo kommen die Daten her (Quelle der Datei) und wo sollen die Daten hin und warum? und was sollen sie dort bewirken?ROM steht für "Read Only Memory" - das ist Speicher, aus dem man nur Lesen, aber in dem man nicht schreiben kann. Vielleicht meinst Du RAM (random access memory).
Das was dort in der Datei steht, ist sogenannter HexCode. Es sollten also nur die Zeichen '0' bis '9' und 'A' bis 'F' dort vorkommen. Und zwar immer paarweise.
Wobei es überhaupt keine Rolle spielt, wenn zwischen den Paaren Leerzeichen auftauchen.
Jeweils zwei Zeichen bilden ein Byte und damit eine Zahl zwischen 0 und 255 (Hexadezimal 0x00 bis 0xFF). Mit C++ kannst Du Zahlen als Hexcode lesen. Auf Grund von einigen Gegebenheiten würde ich Dir hier aber empfehlen, Dir eine eigene kleine struct zu bauen, mit dem Du genau ein Byte einlesen kannst (also zwei Zeichen).Hier mal ein Vorschlag - bitte frage nach - Du wirst einiges davon nicht verstehen.
Das Schreiben in 'ROM' habe ich geraten, da Du dazu noch nichts gesagt hast.#include <iostream> #include <iomanip> // setw #include <fstream> #include <cctype> // toupper struct Byte { char get() const { return value_; } friend std::istream& operator>>( std::istream& in, Byte& b ); private: char value_; }; int calc_value_of_nibble( char nibble, bool& err ) // umwandel eines Zeichens '0'-'9' 'A'-'F' in dessen Wert 0-15 { const char hx[] = "0123456789ABCDEF"; const char* p = std::char_traits< char >::find( hx, sizeof(hx)-1, char(std::toupper(nibble)) ); if( p ) return p - hx; err = true; return 0; } std::istream& operator>>( std::istream& in, Byte& b ) // Einlesen eines Bytes { char high_nibble, low_nibble; if( in >> high_nibble && in.get( low_nibble ) ) { bool err = false; b.value_ = calc_value_of_nibble( high_nibble, err )*16 + calc_value_of_nibble( low_nibble, err ); if( err ) in.setstate( std::ios_base::failbit ); } return in; } // -- 'ROM' nur für Demozwecke class ROM { public: ROM() { std::clog.fill( '0' ); std::clog << std::hex << std::uppercase; } void write( char byte ) { std::clog << std::setw(2) << int(static_cast< unsigned char >( byte )); } }; int main() { using namespace std; ROM rom; for( ifstream in("input.txt"); (in >> ws).good(); ) { int i=0; for( Byte b; i<6 && in >> b; ++i ) rom.write( b.get() ); rom.write( char(0) ); // nach 6 Byte eine 0 hinzufügen } cout << endl; return 0; }Gruß
Werner
-
Kazeshin schrieb:
Nathan schrieb:
OK, mal ganz anders gefragt:
Was willst du mit diesen Zahlen im ROM erreichen?Ich habe einen Assembler code für die N64 geschrieben, der die Zahlen ausliest. Dadurch erhält das Spiel ein "ingame gameshark device", das wie ein echte funktioniert. Das soll für Romhacks nützlich sein

Das Problem ist halt, dass es für den Nutzer verdammt nervig sein wird, 1000 (wirklich 1000 ._.) Ziffern einzutippen.Ah, Memory-Hack, hatte ich mir schon fast gedacht.
Für die Implementierung der write()-Funktion sollst du dir mal WriteProcessMemory() unter Windows anschauen
-
Werner Salomon schrieb:
Hallo Kazeshin,
ROM steht für "Read Only Memory" - das ist Speicher, aus dem man nur Lesen, aber in dem man nicht schreiben kann. Vielleicht meinst Du RAM (random access memory).
Ne, der meint wahrscheinlich so was hier http://de.wikipedia.org/wiki/ROM_(Spielmodul). War auch die ganze Zeit auf dem falschen Dampfer aber langsam dämmert mir, was er vor hat.
-
@Kazeshin
Ist schlimmes C-gefrickel, aber das ist man der Aufgabe schuldig, was anderes wäre irgendwie nicht OK
(Nein, das ist nicht wirklich mein Ernst, aber mit den C Funktionen lässt sich das schnell lösen, und ne "schöne" C++ version ist vermutlich doppelt so lange, und > 10x so schwer für den OP nachzuvollziehen.)Und vollkommen ungetestet, aber es könnte u.U. das machen was du willst (sofern es überhaupt compiliert). Und wenn nicht, sollte es dir ein paar Ideen geben.
#include <stdio.h> int main() { // files aufmachen FILE* patchFile = fopen("patch.txt", "r"); // TODO: error handling FILE* romFile = fopen("rom.dat", "r+"); // TODO: error handling // im ROM file dorthin seeken wo wir patchen wollen fseek(romFile, 0xBEA20, SEEK_SET); // TODO: error handling (ich lass das ab jetzt weg, ich hab hier gar kein error-handling, also fehlt es eh überall :D) // zeilenweise reinlesen char lineBuffer[100] = {}; while (fgets(lineBuffer, sizeof(lineBuffer), patchFile)) { unsigned long part1 = 0; unsigned long part2 = 0; // zwei hex zahlen aus der zeile lesen if (sscanf(lineBuffer, "%lx %lx", &part1, &part2) < 2) // TODO: message ausgeben -- dazu müssten wir aber erstmal auf ne leerzeile prüfen // um unnötige warn-/fehlermeldungen zu vermeiden break; // in bytes zerlegen // hier reihenfolge ggf. umdrehen - je nachdem was für endian benötigt wird unsigned char patchBytes[4] = { ((part1 >> 24) & 0xFF), ((part1 >> 16) & 0xFF), ((part1 >> 8) & 0xFF), ( part1 & 0xFF) }; // ins ROM file schreiben fwrite(patchBytes, 1, 4, romFile); } // und files wieder zumachen fclose(patchFile); fclose(romFile); }Ich habe einen Assembler code für die N64 geschrieben, der die Zahlen ausliest. Dadurch erhält das Spiel ein "ingame gameshark device", das wie ein echte funktioniert.
Sorry, aber anhand deines Programmier-Kenntnisstandes ist wohl eher davon auszugehen dass du ihn dir ergoogelt hast. Ist aber andrerseits auch egal.
-
@hustbaer: Du hast 'part2' und die abschließende 0 vergessen und die C++-Lösung ist auch nicht doppelt so lang (s.o.)
Und warum gehen eigentlich so viele davon aus, dass fgets & fseek und in anderen Threads alloc & free & strtok sofort von jedem DAP verstanden werden? .. wohingegen man für
char c; std::cin >> c;ein Informatikstudium braucht.
Liegt vielleicht auch an C/C++-Kursen wie diesem hier (via Thread Schulaufgabe: Kleine Fehler.).
Gute Nacht
-
Werner Salomon schrieb:
@hustbaer: Du hast 'part2' und die abschließende 0 vergessen
Öhm. Versteh ich jetzt nicht. 'part2' wollte er doch so wie ich das verstanden habe nicht ausgegeben haben? Und welche abschliessende 0? *grübel*
Hab ich was übersehen, oder hab ich etwa gar die ollen FILE* Funktionen falsch im Kopf?und die C++-Lösung ist auch nicht doppelt so lang (s.o.)
Wenn man Kommentare-Anteil und Formatierung angleicht schon. Wenn ich dann natürlich Error-Handling in die C-Version reinmache gewinnt vermutlich sogar die C++ Lösung. Tendenziell ist sowas aber oft in C kürzer. Bzw. in C++ aber halt mit den FILE* Funktionen.
Und warum gehen eigentlich so viele davon aus, dass fgets & fseek und in anderen Threads alloc & free & strtok sofort von jedem DAP verstanden werden? .. wohingegen man für
char c; std::cin >> c;ein Informatikstudium braucht.
DAS ist das geringste Problem.
Eher...
friend std::istream& operator>>( std::istream& in, Byte& b ); //... const char hx[] = "0123456789ABCDEF"; ... return p - hx; //... std::istream& operator>>( std::istream& in, Byte& b ) // Einlesen eines Bytes //... if( in >> high_nibble && in.get( low_nibble ) ) //... for( ifstream in("input.txt"); (in >> ws).good(); ) //... for( Byte b; i<6 && in >> b; ++i )Zum Verstehen der C-Version reichen grundlegenste C-Grundkenntnisse, und den Rest kann man sich sofort anhand der Funktionsnamen ergoogeln.
Und auch halbwegs schnell verstehen. Einzig die
sscanf()Zeile könnte minimale Kopfschmerzen bereiten.In der C++ Variante dagegen...
* friend Funktionen
* Operator Overloading
* Der Arrayindex = Stellenwert "Trick" beireturn p - hx
* Das super nicht-intuitive Initialisieren desifstreamim Schleifenkopf
* Die super nicht-intuitive implizite Konvertierung (auf Umwegen)stream -> boolDas sind Dinge wo sogar manche "erfahrene" C++-ler noch ein oder zwei WTF Momente haben werden.
-
ps:
Natürlich kann man die C++-Variante auch so schreiben dass sie einfacher zu verstehen wird. Dann wird sie aber wieder länger
Also vermutlich hätte ich schreiben sollen doppelt so lange oder > 10x so schwer zu verstehen.
-
Werner Salomon schrieb:
ROM steht für "Read Only Memory" - das ist Speicher, aus dem man nur Lesen, aber in dem man nicht schreiben kann. Vielleicht meinst Du RAM (random access memory).
Nein, ich meinte ROM. ich brauche das für ein Romhacking tool.^^
hustbaer schrieb:
Sorry, aber anhand deines Programmier-Kenntnisstandes ist wohl eher davon auszugehen dass du ihn dir ergoogelt hast. Ist aber andrerseits auch egal.
Nein, ich hab ihn selber geschrieben, auch wenn ich nicht ganz verstehe, was das zur Sache beiträgt. Das ist ja schon fast ne Beleidigung :3 (mich als Lügner und "unfähig" zu bezeichnen...)
Die Sprachen, die ich kann, sind Mips ASM (N64) (wobei ich nicht weiß, ob man das Programmiersprache nennen kann), die Sprache von meinem TI 84+ und Pascal 1.0 (ja, der Informatik unterricht in der Schule was sinnvoll .___. //Ironie) .... sowas wie C hab ich nur nie vorher gesehen^^Naja, meine Frage wurde zur genüge beantwortet und google half mir beim Rest; der Thread hier kann geclosed werden.
-
Naja, es wundert mich nur ein wenig.
Ich hab' auch mit Assembler angefangen und dann C gelernt.Wenn ich damals vor so einem Problem gestanden wäre, und aus irgendeinem Grund keine Funktion ala
sscanf()gekannt/gefunden hätte, dann hätt' ich mir einfach nen Pointer auf das erste Zeichen geschnappt und den Inhalt "mit Hand" geparsed.
-
hustbaer schrieb:
Naja, es wundert mich nur ein wenig.
Ich hab' auch mit Assembler angefangen und dann C gelernt.Wenn ich damals vor so einem Problem gestanden wäre, und aus irgendeinem Grund keine Funktion ala
sscanf()gekannt/gefunden hätte, dann hätt' ich mir einfach nen Pointer auf das erste Zeichen geschnappt und den Inhalt "mit Hand" geparsed.naja, es geht mir hierbei um ein öffentliches tool. ich habe es auch jetzt erstmal so veröffentlicht, dass der benutzer es von hand reinschreiben muss, werde allerdings noch ein tool zum patchen der codes schreiben.