Belgabor
Versuch mal, nur eine Textur zu nehmen.
BlackMambaFan
Du meinst das geht?
Also eine Textur insgesamt (also auf die einzelnen Gruppen gelegt) oder nur eine Gruppe mit Textur?
Belgabor
Insgesammt nur eine Textur.
Markus Lomberg
Mit der Texturanzahl sollte das eigentlich gar nichts zu tun haben. Wie kommst du darauf, Belgabor?
Meine Erklärung des Problems:
Die maximale Blockgröße, die ich bisher in den original RCT3 OVLs gesehen habe, beträgt $10000 (=65536). Folglich habe ich fürs Einlesen der Blöcke im Programm ein Feld angelegt "char BlockBuffer[65536];"
Wie BMFs Datei mir jetzt zeigte, schreibt der Importer jedoch Blöcke, deren Größe $100000 (=1048576) beträgt. Beim Einlesen dieser großen Datenmenge in das kleinere Feld "BlockBuffer[65536]" wird dann undefiniert auf Speicherbereiche zugegriffen, was zu der Fehlermeldung/Absturz führt. Logischerweise tritt dieses Problem nur bei Verwendung sehr großer Texturen auf, welche ich bisher nie benutzte.
Die Problemlösung ist allerdings recht schwierig:
Ich habe natürlich als erstes einfach probiert, mein Feld größer anzulegen "char BlockBuffer[1048576];"
Das führt bei mir sofort zu einem Stack-Overflow. Das verstehe ich nicht, denn es ist doch nur 1 MB, was locker in mein RAM von 768 MB reinpassen sollte.

Woran liegt das?
Fechu's erster CTR-Versuch funktioniert bei mir übrigens einwandfrei. Er verwendet auch nur kleine Texturen. Dass bei ihm der Fehler schon beim Befehl "char BlockBuffer[65536];" auftritt, ist sehr seltsam.
BlackMambaFan
Kann es vielleicht an der Anzahl der Texturen liegen? Ich hab jetzt 4 64x64 Texturen. Ich kann gleich mal versuchen, alle Groups mit nur einer Textur zu belegen. Nur ich weiß ja nicht, ob es in der OVL einen Bereich "Texturen" (oder so ähnlich) gibt, und dann bei der Definierung der Gruppen nur noch die Textur zugewiesen wird, oder ob nach jedem Objekt die Textur folgt. Im zweiten Fall würde eine reduzierung der Texturen rein gar nichts nutzen.
EDIT: So, ich hab jetzt jede Gruppe mit der selben Textur belegt. Der Fehler tritt immer noch auf!
Belgabor
Das mit der Anzahl war nur eine wilde Vermutung von mir =)
Der zur Verfügung stehende Stack hat mit Deinem Hauptspeicher nichts zu tun, das ist eine Einstellung des Compilers. Solche Datengrößen solltest Du aber auch nicht auf dem Stack anlegen sondern dynamisch allozieren. Dann kanns Dir auch egal sein, wie groß ein Block tatsächlich ist.
| code: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
|
// Im include Bereich. Soweit ich mich erinnere ist bei Borland boost dabei
#include <boost/shared_array.hpp>
// Anfang Deiner Funktion
unsigned long blocksize;
boost::shared_array<char> blockdata;
// [Code, der blocksize einliest]
blockdata.reset(new char[blocksize]);
fread(blockdata.get(), 1, blocksize, ovl_file);
// Mit blockdata.get() hast Du Zugriff auf einen Zeiger auf die Daten |
|
Das ist die sichere Variante, da Du dich nicht um das Freigeben des Speichers zu kümmern brauchst.
BlackMambaFan
Ich mach jetzt einfach mal einen neuen Wagen, einfach einen blauen Würfel. Vielleicht hängt das ja mit der Anzahl der Gruppen zusammen.
EDIT: Nein, tut es auch nicht. Ich hab jetzt nur eine Gruppe mit einer 64x64 Textur.
EDIT vol.2:
Mir fällt grade erst auf: Die Fehlermeldung hat sich verändert (nicht einfach so, ich hab auch an den OVLs gefeilt).
| Fehlermeldung vol.2 |
Zugriffsverletzung bei Adresse 77062E7B in Modul 'ntdll.dll'. Schreiben
von Adresse 80455DE0.
|
Ich hänge mal die OVLs an, an der Wagendaten_txt kann das nicht liegen, ich hab das auch mal mit dem Beispiel getestet (was ja, da die OVLs immer gleich heißen müssen, auch geht), und da trat der selbe Fehler auf.
Markus Lomberg
Bei mir funktioniert deine Bahn, BMF! Wie ich oben erklärte, liegt das Problem weniger in deinen 3D-Modelldaten und WagenDaten.txt, sondern hauptsächlich an deinem und Fechus PC-System, was durch die schlechte Programmierung von CTR_Creator begünstigt wird. Daher funktioniert mein Code auf manchen PC-Systemen einwandfrei, während es bei anderen immer den Speicher-Fehler gibt.
@Belgabor: Der Begriff Stack ist mir eigentlich nur als Stapelverarbeitung bekannt, wo nach der Methode Last-In-First-Out die Adressen bei Unterroutinen-Aufruf abgelegt werden, um danach wieder korrekt im Hauptprogramm weitermachen zu können. Warum Variablen auf dem Stack gespeichert werden, ist mir ein Rätsel.
Dynamische Allocation ist mir zu kompliziert (ich erwähnte ja schon des öfteren, dass CTR_Creator schlimm programmiert ist). Da ich sowieso maximal große Blöcke (bisher 65536 Bytes) einlesen können muss, hab ich das statisch gemacht, was für mich deutlich einfacher ist.
Da die 65536 Bytes bei fechu und BMF (selbst bei kleinen Texturen) zu Problemen aufgrund des PC-Systems führen, muss ich CTR_Creator entsprechend umprogrammieren. Das wird leider aufwändig und dauert somit noch etwas.
Kann man die maximale Blockgröße, die der Importer schreibt, vielleicht von $100000 Bytes auf die in den original OVLs üblichen $10000 Bytes beschränken? (in nächster Version?)
Belgabor
| quote: |
Original von Markus Lomberg
@Belgabor: Der Begriff Stack ist mir eigentlich nur als Stapelverarbeitung bekannt, wo nach der Methode Last-In-First-Out die Adressen bei Unterroutinen-Aufruf abgelegt werden, um danach wieder korrekt im Hauptprogramm weitermachen zu können. Warum Variablen auf dem Stack gespeichert werden, ist mir ein Rätsel. |
Das ist kein Rätsel sondern bei allen mir bekannten compilierten Programmiersprachen so. Lokale Variablen werden auf dem Stack alloziiert.
Was Du machen kannst ist eine globale Puffervariable zu machen, da dürfte nur der Hauptspeicher limitierend sein.
| quote: |
Original von Markus Lomberg
Kann man die maximale Blockgröße, die der Importer schreibt, vielleicht von $100000 Bytes auf die in den original OVLs üblichen $10000 Bytes beschränken? (in nächster Version?) |
Wenn Du mir sagst, wie ich unkomprimiert $40000 bzw. $100000 Bytes in einen $10000 Byte großen Block hineinbekommen soll, gerne...
Mein Alternativvorschlag wäre, dass Du aus CTR_Creator ein Frontend für ovlmake machst, dann wirst Du mit einem Schlag sämtliche Probleme los. Dann bräuchte ich aber noch die Infos zu den rit und ric Strukturen von Dir, damit ich das einbauen kann (nach Möglichkeit heute oder morgen früh, denn danach bin ich bis zum 1. offline).
Markus Lomberg
| quote: |
| Wenn Du mir sagst, wie ich unkomprimiert $40000 bzw. $100000 Bytes in einen $10000 Byte großen Block hineinbekommen soll, gerne... |
Daten von $40000 Bytes werden einfach auf 4 Blöcke je $10000 Bytes gesplittet -- das macht RCT3 in original OVLs m.E. genauso. $100000 werden entsprechend auf 16 Blöcke gesplittet.
| quote: |
| ...aus CTR_Creator ein Frontend für ovlmake machst, dann wirst Du mit einem Schlag sämtliche Probleme los. |
In diesem Fall würde ich vermutlich tatsächlich alle bisherigen Probleme loswerden. Allerdings kommen dafür viele neue Probleme dazu, von denen ich die 3 gravierendsten kurz auflisten möchte:
1.) Ich kenn mich mit der Bedienung von OVLmake überhaupt nicht aus. Vorallem verstehe ich nicht, wie man damit etwas anderes als Animationen erstellen kann (z.B. rit, ric, trk, trr, spl Strukturen).
2.) Da ich die Ergänzungen für OVLmake nicht selbst programmieren kann, bin ich zukünftig immer auf dich angewiesen, Belgabor. Ich möchte aber selbstständig neu gefundene Schlüsselwörter einfügen können und verschiedenste Dinge ausprobieren, ohne dich jedesmal zu belästigen. Außerdem würde die Abhängigkeit von deiner OVLmake-Programmierung dazu führen, dass ich mit den CTRs in einer Sackgasse lande, falls du dich irgendwann mal nicht mehr für RCT3 interessierst (ähnlich wie JonWil) und die Unterstützung einstellst.
*hoffend, dass so ein Fall niemals eintritt*
3.) Ist es für mich momentan weniger Aufwand, die CTR_Creator Programmierung zu verändern als die rit- und ric-Strukturen zu übermitteln. Beide Strukturen werde ich natürlich veröffentlichen, allerdings erst, wenn die Tutorials draußen sind, weil ich dann viel weniger erklären muss.
Ireyon
| quote: |
Original von Markus Lomberg
Warum Variablen auf dem Stack gespeichert werden, ist mir ein Rätsel. |
da werden zum beispiel an prozeduren übergebene parameter abgelegt, rückkehradressen für RET von CALL und sonstige registerinalte, die temporär gesichert werden müssen.
SLiPCoR
Die Frage war nicht was sondern warum

...
Ich persönlich glaube es hatte einfach den Sinn für verschachtelte Systeme, weil wenn man so ne if-schleife verschachtelt,braucht man evtl. die zuletzt gemachten Variablen zuerst, und wenn die weg sind dann die die man davor gemacht hat usw

.... keine Ahnung
Ireyon
ganz einfach: es geht schneller, variablen erst mal da abzulegen, als sie direkt an ihre position zu schreiben, da die CPU ja die netten schnellen Befehle PUSH und POP hat.
Markus Lomberg
Es werden scheinbar nur Variablen auf den Stack abgelegt, die temporär (d.h. in einer Unterroutine/Prozedur) definiert sind. Um mein Problem zu umgehen, werde ich die Variablen einfach global anlegen.
fechu
| quote: |
Original von BlackMambaFan
Aaaalso.
Ich hab mich jetzt nochmal dran gesetzt (trotz des Urlaubes).
Ich hab alle Texturen auf 64x64 verkleinert. Trotzdem taucht der Fehler immer noch auf. Kann es vielleicht doch an der fehlenden Animation liegen? Stellt für mich kaum ein Problem dar (dank Belgabor), ich kann mich morgen daran setzen. Ich glaube eher, dass es an Vista liegt. Fechu, benutzt du Vista? Da hatte ich schon oft Probleme mit Zugriffrechtsverletzungen. |
Jap. (scheiss) Vista.

Ich könnte mir gut vorstellen, dass es an dem liegt. Denn auch mit ovl-make hatte ich am anfang Probleme. Jetzt aber gehts.
Schnell zu meinem Model:
Ich hatte einen Block gemacht und oben eine lehne dran. DAs ist alles. eine Einfache Eisentextur. Also eine einzige. Grösse weiss ich jetzt gerade nicht. An was es liegt weiss ich auch nicht. Dafür ist Markus zuständig.
Und ausserdem bin ich froh, dass ich nicht soviel verpasst habe in diesen zwei Wochen. Dann kann ihc mich doch nochmal reinlegen, sobald Markus für Vista benutzer eine passende Lösung gefunden hat.
P.S. Ich bin wieder zurück. Für eine Woche.^^
Belgabor
| quote: |
Original von Markus Lomberg
| quote: |
| Wenn Du mir sagst, wie ich unkomprimiert $40000 bzw. $100000 Bytes in einen $10000 Byte großen Block hineinbekommen soll, gerne... |
Daten von $40000 Bytes werden einfach auf 4 Blöcke je $10000 Bytes gesplittet -- das macht RCT3 in original OVLs m.E. genauso. $100000 werden entsprechend auf 16 Blöcke gesplittet. |
Kannst Du mir da bitte ein Beispiel geben, wo das passiert?
| quote: |
Original von Markus Lomberg
| quote: |
| ...aus CTR_Creator ein Frontend für ovlmake machst, dann wirst Du mit einem Schlag sämtliche Probleme los. |
In diesem Fall würde ich vermutlich tatsächlich alle bisherigen Probleme loswerden. Allerdings kommen dafür viele neue Probleme dazu, von denen ich die 3 gravierendsten kurz auflisten möchte:
1.) Ich kenn mich mit der Bedienung von OVLmake überhaupt nicht aus. Vorallem verstehe ich nicht, wie man damit etwas anderes als Animationen erstellen kann (z.B. rit, ric, trk, trr, spl Strukturen). |
Die Syntax ist ähnlich der die man für Flatrides benötigt. Die Informationen darüber würde ich Dir natürlich zukommen lassen. rit und ric sind auch noch nicht implementiert.
| quote: |
Original von Markus Lomberg
2.) Da ich die Ergänzungen für OVLmake nicht selbst programmieren kann, bin ich zukünftig immer auf dich angewiesen, Belgabor. Ich möchte aber selbstständig neu gefundene Schlüsselwörter einfügen können und verschiedenste Dinge ausprobieren, ohne dich jedesmal zu belästigen. Außerdem würde die Abhängigkeit von deiner OVLmake-Programmierung dazu führen, dass ich mit den CTRs in einer Sackgasse lande, falls du dich irgendwann mal nicht mehr für RCT3 interessierst (ähnlich wie JonWil) und die Unterstützung einstellst. *hoffend, dass so ein Fall niemals eintritt* |
Das ist in sofern nur ein Teilproblem da ich im Normalfall sämmtliche Variablen implementiere und auch per Volldump teste, was die einzelnen Variblen sind (Integer, Float, String, Symbolreferenz, etc.) wenn das aus den Originaldateien hervorgeht. Bei neuen Strukturen bzw. komplexeren Dingen hast Du natürlich recht.
| quote: |
Original von Markus Lomberg
3.) Ist es für mich momentan weniger Aufwand, die CTR_Creator Programmierung zu verändern als die rit- und ric-Strukturen zu übermitteln. Beide Strukturen werde ich natürlich veröffentlichen, allerdings erst, wenn die Tutorials draußen sind, weil ich dann viel weniger erklären muss. |
Ok, das kannst natürlich nur Du wissen =)
Markus Lomberg
| quote: |
| Kannst Du mir da bitte ein Beispiel geben, wo das passiert? |
Ich hab da mal mehrere OVLs gesehen, die ich jetzt wieder raussuchen müsste. Ist aber egal, weil ich mittlerweile einige wenige original OVLs gefunden habe, bei denen die Blockgröße $10000 übersteigt (z.B. etwa $12000); d.h. meine alte Aussage bzgl. Obergrenze von $10000 war falsch. CTR_Creator ist bereits so umprogrammiert, dass man beliebige Blockgrößen einlesen kann (schrittweise in 1000 Byte Stücken).
Zudem hab ich auch schon angefangen, CTR_Creator so umzuprogrammieren, dass nicht mehr einfach nur die gesamten vom Importer erstellten OVLs kopiert werden. Stattdessen werden zukünftig nur die benötigten Strukturen kopiert. Dazu gehören auch die Textureigenschaften der BoneShape-Struktur, wie folgt:
| code: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
|
$0561 $FB24 long FixValue -1 (=$FFFFFFFF) // bisher nur -1 gesehen
$0565 $FB28 long SZN von Textur:ftx 0 (SZN von 'HauntedMansionCar_Flexi:ftx')
$0569 $FB2C long SZN von TexturTyp:txs 0 (SZN von 'SIOpaqueGlossSpecular50:txs')
$056D $FB30 long SeeTextureWhenPlacingFlag 0 (=$0) // laut JonWil
$0571 $FB34 long TexturFlags 0 (=$0) // laut JonWil
$0575 $FB38 long Unknown13 3 (=$3)
$0579 $FB3C long VerticesAnzahl (=Anzahlfürfolgenden*P) 131 (=$83)
$057D $FB40 long FaceEckNrAnzahl (=Anzahlfürfolgenden*P) 300 (=$12C)
$0581 $FB44 long *P auf VerticesBereich -> $8C04
$0585 $FB48 long *P auf FaceEckNrBereich -> $A288 |
|
Was ich noch nicht weiß ist, wie ich aus diesen Daten die Anzahl der Bytes im "VerticesBereich" und der Bytes im "FaceEckNrBereich" erhält. Ich tippe auf sowas wie folgt. Stimmt das? Gibt es Ausnahmen?
| code: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
|
--------------------------------------------------------
VERTICES BEREICH (von 'hauntedMansionCarLOD1:bsh' Textureigenschaften[1])
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$8CFC $8C04 FOR i=1 TO 131 (=VerticesAnzahl)
{ float VertexKoordinateX[i] // oder ähnlich
float VertexKoordinateY[i]
float VertexKoordinateZ[i]
float VertexRichtungsvectorX[i] // oder ähnlich
float VertexRichtungsvectorY[i]
float VertexRichtungsvectorZ[i]
long Unknown[i] // meist 0
long Unknown[i] // meist 255 (=$FF)
long Unknown[i] // meist -1
float UnknownEndeAFlag[i]
float UnknownEndeBFlag[i]
}
--------------------------------------------------------
FACE ECK NR BEREICH (von 'hauntedMansionCarLOD1:bsh' Textureigenschaften[1])
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$A380 $A288 FOR i=1 TO 100 (=FaceEckNrAnzahl/3)
{ short FaceEckNrA von Face[i]
short FaceEckNrB von Face[i]
short FaceEckNrC von Face[i]
} |
|
Noch mehr im Unklaren bin ich mir bei der FlexiTexture-Struktur:
| code: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
|
--------------------------------------------------------
FLEXI TEXTURE DETAIL BEREICH (von 'HauntedMansionCar_Flexi:ftx')
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
$F3D8 $F2DC long TexturSkalierung 7 (=$7) // laut JonWil (evtl. Farbtiefe?)
$F3DC $F2E0 long TexturBreite 128 (=$80)
$F3E0 $F2E4 long TexturHoehe 128 (=$80)
$F3E4 $F2E8 long RecolorFlags 7 (=$7) // laut JonWil
$F3E8 $F2EC long *P auf Farbpalette -> $F2F8
$F3EC $F2F0 long *P auf Texturdaten -> $0304
$F3F0 $F2F4 long *P auf AlphaMaske -> $4304 |
|
Wie berechne ich aus diesen Daten, wieviele Bytes in der "Farbpalette", in "Texturdaten" und in "AlphaMaske" drin sind? Vielen Dank im Voraus!
Belgabor
Ok, ich beantworte das in mehereren Posts, der übersichtlichkeit wegen =)
Ich muss zunächst mit der grundlegeneden BoneStruct Struktur anfangen:
| code: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
|
struct BoneShape {
VECTOR bounding_box_min;
VECTOR bounding_box_max;
uint32_t total_vertex_count;
uint32_t total_index_count;
uint32_t mesh_count2;
uint32_t mesh_count;
BoneShapeMesh** sh;
uint32_t bone_count;
BoneStruct* bones;
MATRIX* bone_positions1;
MATRIX* bone_positions2;
};
struct BoneStruct {
char* bone_name;
uint32_t parent_bone_number;
}; |
|
(VECTOR sind 3 floats, x, y und z. MATRIX ist eine 4x4 float matrix)
mesh_count2 ist dabei die auf jeden Fall angeseigte Anzahl an BoneShapeMeshes, mesh_count die Gesamtanzahl. In den meisten Fällen sind beide identisch. Mehr dazu unten.
Der Rest müsste eigentlich selbsterklärend sein.
Belgabor
Hier die BoneShapeMesh Struktur:
| code: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
|
struct BoneShapeMesh {
uint32_t support_type;
FlexiTextureInfoStruct* ftx_ref;
void* txs_ref;
uint32_t transparency;
uint32_t texture_flags;
uint32_t sides;
uint32_t vertex_count;
uint32_t index_count;
VERTEX2* vertexes;
uint16_t* indices;
}; |
|
support_type ist normalerweise -1. Ansonsten handelt es sich um Supportteile (kommt bei Track-Sektionen und Wegen vor), die nur angezeigt werden, wenn von unten, oben oder beiden Richtungen Supports kommen. Entsprechende Meshes zählen dann nicht in mesh_count2 hinein. Möglicherweise müssen diese Meshes am Ende des Mesh-Arrays kommen.
transparency regelt die Transparenz.
Das ist für Dich extrem wichtig, da wenn dieser Wert > 0 ist, der indices Array 3*index_count Einträge hat!
texture_flags sind diverse Flags.
sides regelt, ob Faces doppelseitig (1) oder einseitig (3) sind.
indices sind wie Du gesagt hast 16 bit Integer (Shorts).
| code: |
1:
2:
3:
4:
5:
6:
7:
8:
|
truct VERTEX2 {
VECTOR position;
VECTOR normal;
int8_t bone[4];
uint8_t boneweight[4];
uint32_t color;
float_t tu, tv;
}; |
|
color ist soweit ich weis immer $FFFFFFFF.
tu und tv sind die Texturkoordinaten (UV-mapping).
bone ist ein Array von Bones denen der Vertex zugewiesen ist. Bisher habe ich maximal zwei gesehen, deshalb weis ich nicht, ob mehr gehen. boneweight sind die zugehörigen Gewichtungen und sollten in Summe 255 ergeben.
Belgabor
Die Hauptstruktur einer FlexiTexture sieht so aus:
| code: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
|
struct FlexiTextureInfoStruct {
unsigned long scale;
unsigned long width;
unsigned long height;
unsigned long fps;
unsigned long Recolorable;
unsigned long offsetCount;
unsigned long*offset1;
unsigned long fts2Count;
FlexiTextureStruct* fts2;
}; |
|
scale ist dabei der 2er Logarithmus der Texturgröße (Breite bzw. Höhe). Sprich bei einer 128*128 Textur gilt: 128 = 2^7, daher scale = 7.
width und height müssen identisch sein, da quadratische Textur. (Nein, ich weis nicht warum die selbe Information dreimal in der Struktur steht).
fps ist die Geschwindigkeit einer Animierten Textur und entspricht etwa Frames pro Sekunde.
Recolorable regelt, welche Farbwahlmöglichkeiten der Spieler hat (Flags). 1 = erste, 2 = zweite, 4 = dritte.
offsetCount/offset1 ist ein Array von indices in den fts2 Array und regelt die Animationsreihenfolge.