Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
Jimmy²

PNAMES/TEXTURE1/2 sucks.

Recommended Posts

If you can read the OP without eventually feeling your blood pressure shoot through the roof you're probably dead inside

 

I agree, it's a shitty system, it's unintuitive, it is not fun to work with at any lengths, doubly so when it comes to trouble shooting of any kind. I had that experience once, and I shall be damned if I ever even risk encountering it again.

 

What can I do to help? Not a thing, I'm afraid. When it comes to coding I'm fucking useless, unfortunately.

 

I'd surely like to see this getting solved somehow, so that people have a few reasons less to shy away from using custom textures and such. Whatever solution there may be at some point in the future, I hope it's going to be available for Boom and ZDoom and their derivative formats for that matter, but I suppose that is asking quite a bit.

Share this post


Link to post

It’s definitely a crappy system to deal with. I think a lot of the problems you listed could probably be fixed in Slade itself, though. Imagine if there was a function to compare a wad’s texture1 with another (generally the iwad one) and autoselect all the distinct ones so you could copy and paste them over into your main resource? Things like that could help a lot to reduce the suffering.

Share this post


Link to post

I don't have much experience using the textures lumps (since I map for GZDoom, I stick them in between the TX markers), but I can certainly agree that they're a pain in the ass to use. I've had to modify PNAMES and TEXTURE1 only once and figuring out the problem and fixing it took much longer than it had any right to, and the fact it still got fixed within twenty minutes (for five textures) comes across to me as being nothing short of a miracle.

 

I would like to see it changed, but that's not anything I can help with. I may have a grip on the terms used in C, but I've never actually used it, so I'm of no help.

 

I actually prefer an alphanumeric order, but finding the custom textures scattered throughout the base textures is a needless chore, so I'd rather that custom textures used some sort of prefix or something (like the noir textures start with 0_) to make them easier to search and find in the map editor. GZDoom Builder's sorting system is an absolute godsend, but custom textures will likely always elude it.

 

Replacing existing IWAD textures and patches is something I can understand early wads doing, especially animated textures and switches, but it's irritating to deal with nonetheless when you're mapping with those textures.

 

I don't mind animated textures, really. I've seen the ANIMATED lump and don't really know what's going on there, but I'm generally able to use my ANIMDEFS, so I stick to it.

 

Probably the one thing I hate most about the TEXTURE1 lump is it doesn't differentiate between IWAD textures and custom textures like the TX markers can, so I can't view just the custom textures unless every IWAD texture and patch is replaced, which I'd rather not happen, which means if I'm looking for a custom brick texture, I'll have to search every one until I find it so I can memorize its naming scheme so I can just search it up and its sibling textures later.

 

My thoughts on the matter.

Share this post


Link to post

I know GLBoom+ supports HI_ (PR does not, and neither does EE), but sadly it doesn't support TX_. Seems a reasonable enough feature that somebody couldsend a patch in and have it integrated. TX_ support is quite good though. ZDoom derivates, EDGE/3DGE, and Eternity all do (as well as Vavoom). If somebody figures out if entryway would let such a feature in PRBoom+, then I see no trouble with somebody in the community trying to add it.

Share this post


Link to post

if this doesnt turn into a bikeshedding festival by tomorrow

if theres some solution, i could probably do the work on dbx to support any option that isnt horrible (or would be cool w maintaining it if someone else implements it)

 

however

 

having texture names be longer than 8 characters would be a clusterfuck to support in the doom builder 2 family of editors (and probably other software). a lot of stuff relies on being able to treat the texture names like unique 64-bit numbers (because that's what 8 characters is, actually). that intersects with with the whole maintaining-compatibility-with-the-existing-plugin-api-thing.

i know this sounds silly, but, it's by far the most infeasible thing in your post.

 

edit:

fuck it

here's my anti-bikeshedding measure

if u can get me to agree about a standard with one (1) person who will actually implement it into a non-zdoom port

(so 2 total people, counting me)

 

then i will implement it into dbx

Edited by anotak

Share this post


Link to post
33 minutes ago, anotak said:

having texture names be longer than 8 characters would be a clusterfuck to support in the doom builder 2 family of editors (and probably other software). a lot of stuff relies on being able to treat the texture names like unique 64-bit numbers (because that's what 8 characters is, actually).

Have you looked at how GZDB does it? GZDoom allows TEXTURES to define long names and GZDB supports it.

Share this post


Link to post

Seriously now, if Eternity & 3DGE support TX_ already, then somebody with some free time fork PrBoom+ (or for bonus points, the UMAPINFO fork), rename it KaBoom, add TX_ support, and the day is saved. It's your chance to be a superhero!

Share this post


Link to post

Managing a community project where participants provide their own resources in all imaginable formats and naming conventions probably highlights the challenges of the format better than anything I've ever done. That said, I do have experience juggling large sets of assets, and have some recommendations for how to deal with current limitations, and some thoughts on possible future formats.

 

In defense of patches

I will not defend PNAMES as a lump (more on that later), but rather patches as a means to create textures. In 1993 I'm assuming it was primarily motivated as a way to save on memory and disk space, but 25 years later it's still neat to be able to combine things to create new textures without adding any new pixel data. Additionally, this ensures consistency across textures that use a certain trim, for example. It's easy to accidentally alter some setting that triggers a slight variation when exporting multiple textures from whatever source you're working with, and if there's something I want to fix in that trim I only have to do it once, not in all its instances.

 

For a true 3D engine like Quake and onward, it's not necessary to do this—You can merely chop up your brushes to create the blend of texture elements that you want. The additional support for rotating and scaling textures makes patch based textures even less useful, and modern engines with proper normal maps will ensure your shadows from rivets and other bumps in the surface are accurate regardless of rotation. Doom however doesn't have any of that, so while you can chop up a line to create vertical columns of different textures and even to squeeze or extend the width of a texture with some careful aligning, vertically you're often stuck. A sector with ceiling and floor of the same height allows you to use upper and lower texture rather than middle in order to combine two, but if the lower texture of a ledge needs a trim, you're out of luck.

 

Because of these constraints in Doom I have personally opted to divide my textures into patches based on how they are segmented vertically. A 128x128 texture with four 32px wide columns of support beam will be a single patch, since I can always just make a 32px line if that's all I want to use. But the horizontal version with four 32px tall bands of the same support will be four patches, so that I can create combinations with other materials without adding more pixel data.

 

Lastly, a drawback of this approach. In my avatar here, the gargoyle face casts a shadow on the iron pentagram behind it, which in turn has a little shadow onto the wood planks. Since we have binary transparency for patches—a one bit alpha channel, essentially—I can't create these delicate shadows using patches. In the IWAD textures I feel the switches suffer a bit from this, for example. So personally I have opted to be somewhat lenient with my reliance on patches, rather than striving for maximum efficiency and modularity.

 

How to make a texture WAD

Assuming you will want to be BOOM compatible, you will need to use the TEXTURE1 or TEXTURE2 lumps in conjunction with PNAMES. I've used most tools for this over the years, and Slade 3 is by far the easiest and most stable. So while you kids have it easy, it has some weird behavior. I won't write a full tutorial here, but the basic steps I use seem to work consistently for me. As of this post my texture WAD has 3485 lumps and TEXTURE2 has 1623 textures, so I must be doing something right.

  1. Prepare your assets as much as possible outside of Slade. Make sure you are in the correct palette, and that the format is an 8 bit bitmap. As a legacy from earlier days of Doom editing I use the BMP format but 8 bit PNG works just as well. Also make sure pixel dimensions are correct, so no 128x129 images or similar errors. Basically I never do any recoloring, palette conversion, or editing in Slade.
  2. Don't import textures/patches into the main lump list. Instead, go to PNAMES and use the "New Patch from File" button. Make sure you are 100% certain what the patch name should be, as changing it later can be problematic. Staying consistent with this approach have lead me to only have a very small number of issues with patch references, and in those cases it was always human error and not because of the format or tools.
  3. Create your textures using your new patches. I use TEXTURE2 so there are no IWAD textures clogging up the view, allowing me to dodge the alphabetical sorting issue Jimmy mentioned. But I also prefix every texture name with O (no IWAD textures start with O) so even in an alphabetical list with IWAD + OTEX.WAD, it's easy to know what's what.
  4. Convert the image format to Doom's own. Before you can save your new textures into the TEXTURE1 or TEXTURE2 lump, you need to convert them to the correct image format. (You can do this before the texture creation step above if you want, but this is the order I use.) If you imported multiple patches, select them in the main lump list view and click the "Convert Gfx To..." button that appears in the lump view pane. "Doom Gfx (Paletted)" should be the default choice and you can just click "Convert All" and be done. But if you only had one patch, it gets trickier: You need to right click the lump and select "Graphic" —> "Convert to..." to invoke the same view, and after conversion you need to deselect the lump to be prompted to save the changes to it. This is unnecessarily convoluted and inconsistent, something I hope a future version of Slade could fix.
  5. Save TEXTURE1/2 before you save the WAD. That there is a difference between saving of lumps inside the WAD and then saving of the WAD itself is not immediately obvious to all users.

Bonus:

  • I try to keep my lumps in alphabetical order. Sorting them gets insanely slow once you're in the thousands, but somehow it's MUCH faster on MacOS! There are some other very minor differences versus the Windows version too, and in my opinion they're almost all in favor of the mac version.
  • Don't forget FLATs have a different graphics format from patches and sprites. So when you have imported them (which is done straight into the lumps list view and not via "New Patch from File" since FLATs don't use patches), make sure you have the correct setting for Gfx conversion.

 

Suggestions for a future format

I'm trying to think of things we could theoretically implement in ports that value backwards compatibility, which means we can't really change the level format and it should remain patch based.

 

Kill PNAMES: It seems logical to do away with PNAMES as Jimmy indicates: Just referencing patches by lump name should be the way to go. Not sure how easy it will be for that to coexist with the IWADs which obviously retain the vanilla structure.

 

Categories: In a PK3 you can have subfolders for textures themes which helps a lot when browsing large texture sets in the editor. A way to achieve something similar in a system that uses a patch based texture definition list would be very welcome, and ideally it should allow for multiple categories. I guess it'd be easiest to create a texture category definitions lump that references textures rather than having a few extra bits per texture (as the latter would break the map format I guess), but it'll be important to make this robust enough that if a texture is removed or renamed, stuff doesn't crash.

 

Names: Texture name lengths have implications in the level format too, so while more than 8 characters would be very useful, it's not a battle I'll be fighting.

 

Make stacking resource WADs less painful: In theory one resource WAD could use TEXTURE1 for its own as well as the IWAD's definitions, while another use TEXTURE2 and only defines its own textures, allowing them to be run together for maps that use textures from both. In reality this is broken in Boom ports, and even if it worked it'd limit us to two sets. Allowing any WAD to define its own textures might lead to naming conflicts at some point, but if the level is from X.WAD then it should look for its texture references in X.WAD before looking in Y.WAD or Z.WAD. So if I have defined a texture called DOOR9000 in all three WADs, the one in the same WAD as my level would be used. If the levels are separate from all resources, it should go by loading order I guess. There are use cases where you'd want to reference a patch from a different WAD, such as altering an IWAD texture or wanting to avoid duplicating pixel lumps, but I wonder if that gets too messy in this scenario?

 

ANIMATED / SWITCHES: Currently, even though GZDoom can load textures accumulatively, it only loads the last ANIMATED and SWITCHES lumps. A way to stack these would be very helpful, with a last-loaded priority for resolving conflicts. Testing Boom here is pointless as it can't even handle TEXTURE1/TEXTURE2 combinations in separate WADs, and I'm aware GZDoom uses ANIMDEFS. (...Which might still not be possible to combine across several WADs loaded at once?)

 

No fancy shit: As an old timer I don't recommend messing with the resolution or bit depth, nor with texture rotation/mirroring or alpha channels. Part of the charm for me is that Doom is Doom. If you're in the camp of people who want to combine PBR textures with Doom enemies, weapons, sounds and behavior (well, an approximation of it at least) there's gzdoom and you don't need to care about this thread really.

 

Palette woes: Even if we avoid high resolution, 24 bit textures in this future format, we might encounter situations where two different WADs define their own palettes. This currently means at least one set will look wrong in game, but since we don't need to worry about VGA display modes these days, we could render each texture based on the PLAYPAL in its parent WAD, and if no PLAYPAL is present we assume IWAD. This would allow BTSX and Ancient Aliens textures to coexist in a software renderer, I guess. I'm not sure whether there are pitfalls with COLORMAP, where for example BTSX defines a purple range as fullbright. But I think it'd work?

Share this post


Link to post

I don't mind the TEXTURE1 & TEXTURE2 lumps. Any quirks they have is offset by the ability to quickly create new textures on the fly by combining existing patches. That said, I would never even attempt to combine different texture resources into one, and the PNAMES lump can, of course, go to hell.

 

Recently, in converting DotB into ZDoom format, I discovered that the TEXTURES lump while even more powerful, has an unexpected quirk all of it own, in that patches and textures share the same namespace, so initially a few patches were being used instead of the intended textures in game. I ended up renaming all the patches with a different prefix just to keep it cleanly differentiated.

Share this post


Link to post

To be fair, ZZYZX solved most of these problems 3 years ago when he created an intelligent WAD merging tool that checks for duplicates, solves naming conflicts, deals with iwad texture replacements and all that good stuff. The only problem is that right now the code for animations and switches is partially broken. But otherwise you can feed it like 100 maps with different texture packs, conflicting names and stuff, and it will merge everything correctly.

Share this post


Link to post

I'll probably be called out for being uninformed, but why doesn't there seem to be an unlimited animations/dehacked code for Boom? I learned yesterday that certain texture packs replace stock textures because they have to in order to work. I am sure there must be a way to make it so this doesn't have to be done with Boom.

 

It's a shame because Boom is a fantastic port, yet some may see its limitations and be turned away from it. I would even vouch for a feature that simply added 20 or so free frames of animation.

Share this post


Link to post

I wrote another wad merging tool some years ago that also merges texture lumps and additionally concatenates text lumps together (such as ANIMDEFS and the like) to provide a crude merging for those as well. No support for the Boom binary animation lump though. Naming conflicts just mean one texture will be overwritten, though the conflict is logged to indicate it should really be solved by the author inside their source wad.

Share this post


Link to post
33 minutes ago, obake said:

I'll probably be called out for being uninformed, but why doesn't there seem to be an unlimited animations/dehacked code for Boom? I learned yesterday that certain texture packs replace stock textures because they have to in order to work. I am sure there must be a way to make it so this doesn't have to be done with Boom.

 

It's a shame because Boom is a fantastic port, yet some may see its limitations and be turned away from it. I would even vouch for a feature that simply added 20 or so free frames of animation.

 

I think ANIMATED lumps are what you're after - replacing stock textures for animations is more likely to be a vanilla-compatibility thing.

Share this post


Link to post

hmm, this is a good discussion. Honestly I find that bare textures floating in a textures directory (TX_START/END for wads, and an actual textures directory for the engines that support archive formats like .zip. bonus points if they can support subdirectories in textures (I think all can?)). I feel like texture composition is used rarely enough to the point where it's more of a pain to set it up for all your textures than anything (and fuck, even id stopped using it for the most part in Doom 2). The majority of games I've worked with usually have bare textures, or have a material file that describes a texture, using multiple images. Whether or not it's in some bigass archive like the id games or segemented into various packages like unreal tends to vary, but almost invariably the individual textures are stored in a relatively straightforward manner. You can drop the texture or material files into the archive and the game would see them. From this I'm fairly sold on the idea of dumping textures into some sort of package in a straightforward manner, with attached scripts if they need additional information.

 

I feel decals in ZDoom would be a pretty great way to add some details to walls, but for the longest time they've been an absolute pain in the dick to set up and place in maps. I wonder if GZDB improves that experience any, since if they can make it easy to do it might be worthwhile to use. With that you can then stick a sign, pipe, screen, or whatever (repeated details would be painful under this, so a one time splotch of dirt or an oil stain might work, but a dirty wall would be better as a separate texture, and most people do that already) onto a wall and not have to worry about sticking a line 1mu away from the wall or having to load up the texture to composite them.

 

ED: I also feel I'd have a lot less loathing for texture1 over the years if Doom could load multiple ones, but I get that it was a thing id wasn't really expecting. It does bug me that I think a lot of engines don't accept appending multiple texture1 lumps though, as they do with flat and sprite namespaces.

Share this post


Link to post

One more note on ANIMATED vs ANIMDEFS: The latter, being the zdoom version, brags about additional features over Boom's ANIMATED:

 

Quote

ANIMDEFS provides additional flexibility, allowing one to not only animate textures with any amount of images at any rate of animation, and not only to make standard Doom-style on/off switch textures, but to combine the two

 

But it is in fact perfectly possible to reference an ANIMATED texture in a SWITCHES definition in Boom:

 

https://imgur.com/9oZ1P7k

 

Edit: But not to have the transition itself be a separate animation, which is perhaps what they're referring to.

 

Share this post


Link to post

This discussion makes me think some people will not like my texture set I'm making for a GZDoom map. They are completely dependent on GZDoom, and you know what? I like it this way. I remember messing with these old patches methods for texture creation...pain in the ass that I'm just not willing to do nowadays. I'll make my high color textures in photoshop, save them as .png into a /textures dir, and package my map as a .pk3. If anyone wants to re purpose my textures for the antiquated patches and lumps and indexed colors, I dont care, but good fuckin' luck!

 

If you're old school, I respect that, but I'm not messing with that crap. I think that the engines that are limiting features that are possible now, just to keep backwards comparability, is a bit silly All of the engines should allow the simple texture directory method, and also do away with the color limitations. GZDoom can load both old textures from patches and lumps, and new textures at the same time...seems to me the best of both worlds already exists, just need some of the other engines to jump on the band wagon.

 

Just the opinions of an old man that values his editing time, and doesn't want to fuck with patches and lumps!

Share this post


Link to post
9 hours ago, ukiro said:

after conversion you need to deselect the lump to be prompted to save the changes to it.

There's a floppy disk icon in the entry panel that should let you save without having to deselect.

 

9 hours ago, ukiro said:

Palette woes: Even if we avoid high resolution, 24 bit textures in this future format, we might encounter situations where two different WADs define their own palettes. This currently means at least one set will look wrong in game, but since we don't need to worry about VGA display modes these days, we could render each texture based on the PLAYPAL in its parent WAD, and if no PLAYPAL is present we assume IWAD. This would allow BTSX and Ancient Aliens textures to coexist in a software renderer, I guess. I'm not sure whether there are pitfalls with COLORMAP, where for example BTSX defines a purple range as fullbright. But I think it'd work?

If you want to have different palettes at the same time, you'll have to have a true-color renderer. By definition. The vanilla software renderer outputs an 8-bit image because all it does is work with indices, not RGB color values.

 

You might be interested in this discussion on the topic:

 

Share this post


Link to post
11 hours ago, Gez said:

Have you looked at how GZDB does it? GZDoom allows TEXTURES to define long names and GZDB supports it.

so it uses a hashing function (Murmur2 in particular) to get filenames to be represented by 64 bits

 

i thought about doing this before. i originally just discarded the idea because there is no real way of handling a hash collision (within DB's existing architecture, i mean). i didn't think about the fact that maybe a collision is so unlikely that it's not worth worrying about too much?  but i'm not sure i love that approach.

 

after doing quite a bit of math myself and then finally remembering enough about probability to come up with the right search terms, i found the correct answers.

so, like, if you have 6100 textures your probability of a collision is 10 to the -12th.

and the consequences of a collision are unclear? i'm not sure i want to unleash a hard-to-track-down bug that has a chance to wreck someone's map with a 1 in some near-trillionish chance?

 

and that's assuming the Murmur2 hash used produces entirely uniform values. which, this is quite a bit outside my area of expertise, but i suspect it does not (?). in which case the probability of a collision goes up? maybe? how much? i don't really know? a quick google gives this stackoverflow answer, but unfortunately it is about the 32bit version of Murmur2, which is unhelpful. there's stuff like this, which might affect things? apparently there's a Murmur3, which fixes that particular flaw.

 

and if the probability is much higher, how easy would it be to debug the resulting problems? seems like a nasty can of worms

 

there's also just the whole, calculating-a-hash-thing isn't free, and one of my goals with DBX has always been performance. i haven't measured how this affects things at all though, and my instinct says it's "almost free", but i know better than to trust my instincts on this kind of thing, it must be measured.

 

idk, i'll have to think on this. i really don't love the idea of "bad things happen but only this tiny percent of the time, and that's fine and we accept it".

 

edit: and yes, hash collisions are a solvable problem, but i have to fight other conflicting aspects here (the Plugin API, my own time/effort put in, etc). i'd have to rewrite a loooot of stuff it seems. as far as i can tell, MAX-ED just didn't worry about it in GZDB.

Edited by anotak

Share this post


Link to post

The PNAMES/TEXTUREx system is quite powerful, and, if you follow the rules, it doesn't have to be difficult. Had id done just a little more work on it, it would have worked a lot better (like, if it supported multiple P_START/P_END markers, for one).

 

Especially if the IWAD is Doom2.wad, by far the easiest thing to do is simply add new patches, and new entries to the PNAMES and TEXTUREx lumps. Because Doom2 is always loaded, you know that those patches will exist. This should be done with tools vs. manual editing.

 

There's a couple of reasons for using P_START/P_END. First, it tells the texture engine where to start, when searching for the matching patches. Second, it lets WAD editors identify the lumps inbetween the markers.

 

The root of the confusion is that Doom makes textures out of multiple patches. This was most likely done to save memory and disk space. But, by making all your new walls consist of a single graphic, one entry in P_NAMES and one entry in TEXTUREx will get the job done.

Edited by kb1

Share this post


Link to post

Also, doom.exe actually completely ignores P_START and P_END.

Share this post


Link to post
9 hours ago, kb1 said:

The root of the confusion is that Doom makes textures out of multiple patches. This was most likely done to save memory and disk space. But, by making all your new walls consist of a single graphic, one entry in P_NAMES and one entry in TEXTUREx will get the job done.

 

Nowadays, the point is not to save disk space but to be able to combine existing patches into a new texture. So you don't have to open up your graphics editor of choice and create a brand new texture every time you need a new variation, and you especially don't have to redo a metric shitton of graphics whenever you replace or improve a patch.

Share this post


Link to post
11 hours ago, kb1 said:

The PNAMES/TEXTUREx system is quite powerful, and, if you follow the rules, it doesn't have to be difficult. Had id done just a little more work on it, it would have worked a lot better (like, if it supported multiple P_START/P_END markers, for one.

 

Especially if the IWAD is Doom2.wad, by far the easiest thing to do is simply add new patches, and new entries to the PNAMES and TEXTUREx lumps. Because Doom2 is always loaded, you know that those patches will exist. This should be done with tools vs. manual editing.

 

There's a couple of reasons for using P_START/P_END. First, it tells the texture engine where to start, when searching for the matching patches. Second, it lets WAD editors identify the lumps inbetween the markers.

 

The root of the confusion is that Doom makes textures out of multiple patches. This was most likely done to save memory and disk space. But, by making all your new walls consist of a single graphic, one entry in P_NAMES and one entry in TEXTUREx will get the job done.

 

What is the point of this post? I know how the system works on a basic level, you numpty. I'm talking about combining different texture sets together, something I've done numerous times and always run into problems with due to how the system is structured.

Share this post


Link to post
3 hours ago, Jimmy said:

 

What is the point of this post? I know how the system works on a basic level, you numpty. I'm talking about combining different texture sets together, something I've done numerous times and always run into problems with due to how the system is structured. 

 

Perhaps a mapinfo-like feature where you can set the TEXTUREx lump you would like to use for that level only. The engine can then (re)construct the texture set, without it overwriting a different TEXTUREx lump for a different level...?

 

But then again, it is not difficult to come up with a texture/patch naming standard for different contributors during development.

Share this post


Link to post
13 minutes ago, Mordeth said:

 

Perhaps a mapinfo-like feature where you can set the TEXTUREx lump you would like to use for that level only. The engine can then (re)construct the texture set, without it overwriting a different TEXTUREx lump for a different level...?

 

Wouldn't it make more sense then to implement something saner, like maybe a subset of ZDoom's TEXTURES?

I'd guess that many engines would have problems tearing down and recreating the entire texture data for each level. If I remember correctly texture setup is by far the biggest chunk of engine startup time.

Share this post


Link to post
On 6/21/2018 at 1:55 PM, Jimmy said:

Don't forget ANIMDEFS lumps don't have #include functionality.

Eternity also lets you define switches and animations in EDF (besides ANIMDEFS), which you can add and include together.

 

Also, doesn't SLADE abstract TEXTURE1 and PNAMES much better than predecessors? Does it let you do such things as merging them or converting them to/from simple graphics?

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×