Author
|
Topic: Thinking about writing a NES DTE doc (Read 2 times)
|
Kagemusha
Guest
|
|
« on: September 01, 2009, 09:52:35 pm » |
|
I was wondering if anyone would be willing to read (and possibly offer advice/criticism) over a doc that I've started write up, but haven't decided on whether I want to finish it or not. I'll post the WIP if so. Anyway, I used KingMike's doc a few years ago, but a few instructions of his weren't correct and had to be changed and my methods on how I go about a few things aren't the same. So anyone interested?
|
|
|
|
RedComet
Guest
|
|
« Reply #1 on: September 01, 2009, 11:10:06 pm » |
|
I'll look over it for you. I'm curious if your method is different from mine.
|
|
|
|
Kagemusha
Guest
|
|
« Reply #2 on: September 01, 2009, 11:24:47 pm » |
|
Aw, I totally forgot about your doc. Not that it matters for my purposes, but I'll have to look it over because my methods are probably the same or similar. Code's probably mostly the same as well.
Incidently, I remember having some difficulty trying to comprehend/follow your doc to the point where I ultimately gave up on it and went back to KingMike's doc. It also happens that I didn't have much of an idea of what I was doing.
|
|
|
|
aishsha
Guest
|
|
« Reply #3 on: September 02, 2009, 04:12:56 am » |
|
Pictures would be of much help, if it's a beginning level doc. I do remember my first DTE from King Mike's illustrated doc on Y's.
|
|
|
|
Dragonsbrethren
Guest
|
|
« Reply #4 on: September 02, 2009, 09:31:46 am » |
|
The more assembly guides the better. I think the vast majority of people, myself included, get a little overwhelmed by the existing guides (not commenting on the other DTE docs; it's been years since I read them) that assume too much knowledge. Guides that teach you how to do a specialized hack, explain how and why it works well, and give you a tangible result at the end do wonders for me. Most of my assembly knowledge, as minimal as it is, comes from guides like that.
|
|
|
|
Kagemusha
Guest
|
|
« Reply #5 on: September 02, 2009, 10:41:59 am » |
|
I wish I could do pictures, but for now it'll just be plain text. Ideally, I'd like the doc to be for people who know basic romhacking, but not much on the assembly side. My goal is to make as it simple and understandable as I can. Once I get around to Red's doc, I'll post what I've got so far, which will cover up to the abort routine. Edit: I'm not sure if this is any good at all. I'm not really satisfied right now and I suppose I have the majority of this particular part done. I suppose the important part is whether or not I did a good job explaining it and telling you how to do things. Pre-step #1 - Before you actually begin to code a DTE routine, you need free space for the code and table to go into. For the NES, that space will be in $8000-FFFF in the PRG-RAM and it will usually be a bunch of FF's. If they are preceded by a 60 (RTS), they are good to go. The PRG-RAM can be viewed in the memory editor in FCEU.
Optional Step - Dakuten (Not done, last-minute addition. Needs work) Note: While looking at Red's doc, I noticed it and remembered I've used it for Goemon. Very useful if you're tight on space.
Step #1 - The first thing I always do when I code a DTE routine is to find the text routine. This can be found easily by setting a read breakpoint for the beginning offset of some text say intro text. You can find the offset easily by just finding the pointer for the string. The code you want should only be 2 instructions and should consist of an LDY and an LDA, generally speaking. The LDA is what the debugger will break on and the LDY should be before it.
Step #2 - After you've found the text routine, you're going to want to JSR out to that free space you found eariler. You should have one or more bytes left over from the original code (The place where you JSR'd from), so you're going to want to NOP that. Then you're going to want to replace that code you overwrote exactly how it was in the free space and RTS after that. If the game is working fine after that, you should be good. However, this depends entirely on the game and some games might not like being JSR'd from. For example, you might screw up the A, X or Y registers, but like all things, it can be dealt with. Anyway next step!
Step #3 - After you've got the JSR working you're going to want to pick a spot in RAM to store the A register. Ram is $00-07FF in the NES and it very important that you don't use $00-FF or game RAM because it is a crapshoot and I know from experience. It might work somewhere else, but it might not elsewhere. Anyway, the safest place in RAM to use is the end of RAM, $07FF. Okay, now why RAM usage matters, if our supposedly free RAm byte isn't free and is used somewhere then the second part lit. second DTE code will not work at all because we rely on our free RAM byte to get to that code. In short, it will mess things up.
Step #4 - Now it's time for the first DTE instruction forget about the code you have in your free space for now (you know that code overwrote) , you're going to want to replace it with a LDA $RAM Offset. Make sure your using the right LDA too. It depends on the RAM offset. Make sure you know the difference between a 1 byte and 2 byte RAM address. Anyway after the LDA, you're going to want to do a BNE followed by a hex value that will be equal to length it takes to get to the 2nd time routine, which is the code for the second DTE character. For now, you can just make something up. Now for the importance of this code. Once free RAM byte = 1 the code will skip over to the 2nd time routine. It's basically a branch. I've tried explaining the purpose of the code and I didn't bother to explain basic 6502 stuff. I dunno, perhaps I should. Anyway, right now I want to explain a DTE routine hypothetically and once I'm done, I'll apply it to a game. Not sure which one yet though.
|
|
« Last Edit: September 02, 2009, 02:06:56 pm by Pennywise »
|
|
|
|
KingMike
Guest
|
|
« Reply #6 on: September 02, 2009, 02:25:17 pm » |
|
I called $8000-FFFF RAM in my document and got complained at, so I had to rewrite it as "address space" or just "address".
|
|
|
|
Kagemusha
Guest
|
|
« Reply #7 on: September 02, 2009, 02:32:52 pm » |
|
Yeah, I'm not entirely sure if PRG-RAM is correct. Maybe PRG-ROM instead. Technically speaking, if this were the FDS, it would be correct because the FDS only has PRG-RAM. Okay it's a little fuzzy, but I think it's right.
Also anyone have any input on using stack space for the free RAM byte. I know it's been mentioned a few times in previous discussions.
|
|
|
|
Tauwasser
Guest
|
|
« Reply #8 on: September 02, 2009, 02:58:02 pm » |
|
Are there any other parts to your document or is this is? I personally do not like the punctuation and register. Also, I think you did not meet your own requirements, that is not knowing much about assembly. You still require those guys to know what LDA etc. stand for. "JSR out" ⇒ "crazy acronym here out"?? To make this ost not only criticism, I will edit your text and put it here shortly.EDIT: Preparations: Before you actually begin to code your DTE routine, you will need to find free space in the ROM for your new code and data to go. For NES, that space will be in RAM from 0x8000 to 0xFFFF. Usually free space is indicated by lots of 0xFF's preceded by 0x60. You can view this RAM area with FCEU's memory editor. > I would put that after step 1, because it seems you try to avoid switching PRG banks. So not just any free space the user finds will be good to go.Planning your DTE: - Dakuten
- Special commands inside of strings (CR, LF, WAIT etc.)
Step #1: The first this we need is the original text routine. There may be several, so we may have to repeat these steps multiple times until we found all text routines. You usually go about this with breakpoints. Breakpoints halt the emulation and open the debugger when the conditions of the breakpoint are met. There are three general types of breakpoints, execution breakpoints, read breakpoints and write breakpoints. Execution breakpoints are usually just called breakpoints. You tell the emulator to stop emulating when a certain command on a certain address in the ROM is executed. Read and write breakpoints catch reads from resp. writes to a certain address in ROM/RAM. We will use a read breakpoint and set it on the beginning of a string we can locate with a hex editor in the ROM. When you know play the game, the emulator will halt emulation and begin debugging when that string usually appears on the screen. Beware of multiple instances of the same string. You will be seeing a part of the text routine in the debugger window. Usually there will be a load command (LDA, LDX etc.). Step #2: Now that we found the text routine, we would want to insert code there. This, however is not possible as would possibly change the offsets of all other routines after the text routine. What we do is, we override two or three commands from the load command we just found with a jump instruction (JSR) to the free space we located earlier (> notice how is is important now that we found free space around here somewhere). If you have to break up a command to write the JSR into the ROM, that means, it consisted of multiple bytes and you did not overwrite all of them, be sure to change the remaining bytes to NOP. Now, put the code you just overwrote at the free space you found and put a RET after it. Usually, this should work out, however, we will need to add some actual DTE code in the future. This will likely change some registers, so we will preserve the original registers and recall them before we RTS out of our DTE routine. However, for now we should be fine. Step #3: Playtest and see if the game still works after you edited the code. If it doesn't, > awesome solution here. We now need to find a place to store our value read from our string via the load command. Usually, the value read will be in register A. In general, try to avoid 0x00 to 0xFF of RAM, as many games have their own global variables in there, so our saved value might be changed by some code outside of the text routine, if we use those addresses. > So you...Guess? That's not a good approach.After rereading, I think my text is somewhat of an improvement. However, it still assumes too many things. I would explain this these things totally differently... Notice how I refrained from using parentheses or casual language in the middle of a paragraph. If something is longer than thee words and worth mentioning, do so in a dedicated sentence and don't throw it in there for the heck of it. Also, don't do "believe me because I know" or something. Rather give quick, concise blanket explanations. I also feel that casual language doesn't really belong in a document of this sort as it draws attention to it that should be on the subject instead. - Introduction
- About the author
- Who should read this guide?
- Introduction to ASM
- Introduction to FCEU debugger
- Dual Tile Encoding
- Basic idea
- Game-specific adaptation
- Logic flaws
- Implementation of a DTE
- Current text routines
- Data tables for DTE
- Code changes
- Graphics insertion
- Debugging
- Afterword
- Credits
- Relating to MTE
- Relating to VWF
Basically, I would strictly separate the explanation of what a DTE is and the debugging process. I would do a quick and dirty intro to ASM and FCEU only stating the bare necessities and only mentioning opcodes used in the examples. I would do an actual implementation for 03. Maybe corollary show some pointers how a MTE might be achieved (if the game is suitable). The reason why I devoted 03.ii and 03.iii to seemingly "random/unnecessary" topics is solely because they are not unnecessary and can save you a lot of trouble later on. Here you might mention the difficulties of actually having a solid ram slot to work with and when it should be initialized, cleared and what to do if 0x00 (the "empty compare value") is an actual character etc. Somewhere in there should also be a statement when it is viable to do a DTE and when not. There are games that have to undergo a massive amount of changes before any kind of direct drawing is possible. Dakuten/Handakuten are game-specific and should be mentioned in there, but need not be in the implementation example. MTE and VWF are related to this, so I think they merit mention. If you do include some pointers in what to change to have a simple MTE in place (depending on the game and your own implementation, it might be as simple as expanding the data tables). VWF needs some of the ssame steps, some different steps. It could be discussed when it is viable to try and go for a VWF and when not, i.e. if the game already does half the stuff a VWF needs to exist, why change it all around for a DTE. cYa, Tauwasser
|
|
« Last Edit: September 02, 2009, 03:51:20 pm by Tauwasser »
|
|
|
|
Kagemusha
Guest
|
|
« Reply #9 on: September 02, 2009, 03:15:02 pm » |
|
That's all I've got so far. I was going to include up to the DTE abort routine for now, but I got a little lazy. Doesn't matter, very much a WIP right now. It could use heavy revision right now. Anyway trying to aim the doc at someone who doesn't know much 6502 ASM (or ASM in general) is a complicated subject for me. For me personally, anyone who has very limited ASM experience shouldn't be trying to code a DTE routine. Granted when I first started out I did exactly that and it makes things confusing and difficult. I was thinking of perhaps of doing a doc that would teach 6502 basics by doing various ASM exercizes with various games.
Also JSR is not a crazy acronym. It's a common and accepted abbreviation that you can find listed in the 6502 docs. It simply stands for jump to subroutine. Now perhaps an explanation of why JSR and not JMP would be useful.
|
|
« Last Edit: September 02, 2009, 03:45:36 pm by Pennywise »
|
|
|
|
Tauwasser
Guest
|
|
« Reply #10 on: September 02, 2009, 03:53:40 pm » |
|
Also JSR is not a crazy acronym. It's a common and accepted abbreviation that you can find listed in the 6502 docs. It simply stands for jump to subroutine. Now perhaps an explanation of why JSR and not JMP would be useful.
I am familiar with that It would however be exactly that crazy acronym to me if I was not familiar with ASM. Things like "JSR to" "NOP out" are all accepted lingo, however, somebody with no real knowledge of ASM will feel a little uneasy when all he gets is "Do something from that piece of code..." out of three whole sentences of yours. Revision and suggestions above, Tauwasser
|
|
|
|
Kagemusha
Guest
|
|
« Reply #11 on: September 03, 2009, 03:27:18 pm » |
|
I like your suggested layout and will be following it. My question is what would you or anyone suggest what format the doc should be in? I've been considering making it a word document because I can easily include pictures and manipulate things easily.
|
|
|
|
UglyJoe
Guest
|
|
« Reply #12 on: September 03, 2009, 04:05:21 pm » |
|
A Word doc exported to PDF would be nice.
|
|
|
|
golden
Guest
|
|
« Reply #13 on: September 03, 2009, 04:16:58 pm » |
|
Personally, I like PDFs the most and Word docs the least. Don't know about Word but OpenOffice has a nice "Export to PDF" button.
|
|
|
|
Dragonsbrethren
Guest
|
|
« Reply #14 on: September 03, 2009, 04:37:46 pm » |
|
I absolutely loathe PDF.
|
|
|
|
|