Author
|
Topic: Menu Compression. (Read 5 times)
|
KingMike
Guest
|
|
« Reply #105 on: February 21, 2008, 01:26:32 pm » |
|
Depends on where the code starting the bankswap is. What I did in DD3.
I put 3 routines in the fixed banks (3C000/7C000. One of the those will be a fixed bank, depending on the 256K setting). One to swap to 256KB page 1, one to swap to 256KB page 0 (maybe you could combine those, so bank 3C000 swaps to page 1, and the code at the same spot in bank 7C000 swaps to page 0), and another to swap a 16KB bank into CPU $8000-BFFF). Then I have my hacks all in the fixed bank, so I can just JSR/JMP to whatever I want to in the $8000-BFFF range (and my code would be at ROM (address-8000)+(bank*$4000)+$40010. Then when I want to go back to the original code, from the fixed bank I swap back in the original bank and jump to whatever the next code is after my hack.
So my code is like: ;some of the original game's code JMP Some place in the fixed bank
Some place in the fixed bank (keeping all code that involves a 256KB bankswap mirrored in both fixed banks): JSR Swap 256 KB page LDA 16KB bank # JSR Swap 16KB bank ;whatever code I want JSR Swap 256 KB page LDA Backup of 16KB bank pre-swap (maybe your game already does it, but I had to modify the code in DD3 to automatically backup the bank number to somewhere in RAM every time it does a 16KB swap) JSR Swap 16KB bank JMP Place in the original code after my changes
If you called up the swap routine while in a non-fixed bank: If you used a JSR to call it, figure the offset of the next instruction, relative to the start of the bank. Then start your code at the same relative point to the start of the new bank. If you used a JMP to call it, then figure out where you want your code to start in the new bank, add make a JMP relative to the start of the new bank (remember the address needs to be between $8000 and $BFFF)
|
|
|
|
ded302
Guest
|
|
« Reply #106 on: February 21, 2008, 01:49:31 pm » |
|
Ill see what I can do with this info, thanks.
|
|
|
|
ded302
Guest
|
|
« Reply #107 on: February 24, 2008, 12:17:03 pm » |
|
I remember someone saying that most games that have banking have a function that can retrieve a byte from a certain address in a certain bank, how would this function look like in a mmc1 rom?
|
|
|
|
KingMike
Guest
|
|
« Reply #108 on: February 24, 2008, 01:43:14 pm » |
|
Only 8-bit game I can personally recall seeing such a function in is Star Ocean: Blue Sphere for GB/C, but that doesn't really help (completely different hardware).
If you have to write such a function: find 2 consecutive bytes of free space on the zero page (RAM $0000-00FF).
Your function should assume some RAM space has had the CPU address and bank written to it. (it will likely need to be in the fixed bank, and mirrored in both fixed banks if using 512KB PRG) You'll also need a couple bytes of free RAM space: -one to hold the bank currently swapped in $8000-BFFF. -another to hold the value you read from the ROM.
Save the bank # currently in $8000-BFFF. Swap in the bank you wish to read from. Load the pointer into some zero page space. TYA (you probably want to save Y in case the game needs it) PHA LDY #$00 LDA ($zero page address),Y. I'm pretty sure this is the only instruction the NES has for indirectly reading ROM/RAM. STA $some free RAM space PLA TAY (restore the original value for Y) Restore the bank that was previously in $8000-BFFF. LDA $some free RAM space.
If you can't find free space on zero page, pick something not used in the NMI/IRQ routines (since those routines can happen at any time, you don't want to change a value you can't change back before it's used again. A value used to read a text routine is a good choice), and sandwich your code between LDA $(zero page address) PHA LDA $(zero page address) + 1 PHA
and
PLA STA $(zero page address) + 1 PLA STA $(zero page address) with the LDA $free RAM space afterwards.
|
|
|
|
ded302
Guest
|
|
« Reply #109 on: February 24, 2008, 01:53:31 pm » |
|
Thanks for answering my question again, Ill see what I can do with this info.
|
|
|
|
ded302
Guest
|
|
« Reply #110 on: March 10, 2008, 06:02:57 pm » |
|
I tried that special case MMC1 bankswapping and when I try to implement this code the game resets. What I did was replace the initial text read with a jump to this code. [03E181] $e181: 4C 28 E9 JMP $E928 A:0A X:0D Y:FF S:F3 P0=18000 P1=1a000 P2=3c000 P3=3e000 [03E928] $e928: A9 10 LDA #$10 A:0A X:0D Y:FF S:F3 P0=18000 P1=1a000 P2=3c000 P3=3e000 [03E92A] $e92a: 8D 00 A0 STA $A000 A:10 X:0D Y:FF S:F3 P0=18000 P1=1a000 P2=3c000 P3=3e000 [03E92D] $e92d: 4A LSR A:10 X:0D Y:FF S:F3 P0=18000 P1=1a000 P2=3c000 P3=3e000 [03E92E] $e92e: 8D 00 A0 STA $A000 A:08 X:0D Y:FF S:F3 P0=18000 P1=1a000 P2=3c000 P3=3e000 [03E931] $e931: 4A LSR A:08 X:0D Y:FF S:F3 P0=18000 P1=1a000 P2=3c000 P3=3e000 [03E932] $e932: 8D 00 A0 STA $A000 A:04 X:0D Y:FF S:F3 P0=18000 P1=1a000 P2=3c000 P3=3e000 [03E935] $e935: 4A LSR A:04 X:0D Y:FF S:F3 P0=18000 P1=1a000 P2=3c000 P3=3e000 [03E936] $e936: 8D 00 A0 STA $A000 A:02 X:0D Y:FF S:F3 P0=18000 P1=1a000 P2=3c000 P3=3e000 [03E939] $e939: 4A LSR A:02 X:0D Y:FF S:F3 P0=18000 P1=1a000 P2=3c000 P3=3e000 [03E93A] $e93a: 8D 00 A0 STA $A000 A:01 X:0D Y:FF S:F3 P0=18000 P1=1a000 P2=3c000 P3=3e000 [07E93D] $e93d: A9 00 LDA #$00 A:01 X:0D Y:FF S:F3 P0=58000 P1=5a000 P2=7c000 P3=7e000 [07E93F] $e93f: 8D 00 E0 STA $E000 A:00 X:0D Y:FF S:F3 P0=58000 P1=5a000 P2=7c000 P3=7e000 [07E942] $e942: 4A LSR A:00 X:0D Y:FF S:F3 P0=58000 P1=5a000 P2=7c000 P3=7e000 [07E943] $e943: 8D 00 E0 STA $E000 A:00 X:0D Y:FF S:F3 P0=58000 P1=5a000 P2=7c000 P3=7e000 [07E946] $e946: 4A LSR A:00 X:0D Y:FF S:F3 P0=58000 P1=5a000 P2=7c000 P3=7e000 [07E947] $e947: 8D 00 E0 STA $E000 A:00 X:0D Y:FF S:F3 P0=58000 P1=5a000 P2=7c000 P3=7e000 [07E94A] $e94a: 4A LSR A:00 X:0D Y:FF S:F3 P0=58000 P1=5a000 P2=7c000 P3=7e000 [07E94B] $e94b: 8D 00 E0 STA $E000 A:00 X:0D Y:FF S:F3 P0=58000 P1=5a000 P2=7c000 P3=7e000 [07E94E] $e94e: 4A LSR A:00 X:0D Y:FF S:F3 P0=58000 P1=5a000 P2=7c000 P3=7e000 [07E94F] $e94f: 8D 00 E0 STA $E000 A:00 X:0D Y:FF S:F3 P0=58000 P1=5a000 P2=7c000 P3=7e000 [07E952] $e952: A0 00 LDY #$00 A:00 X:0D Y:FF S:F3 P0=40000 P1=42000 P2=7c000 P3=7e000 [07E954] $e954: B1 6B LDA ($6B),Y @ $B1F3 = $FF A:00 X:0D Y:00 S:F3 P0=40000 P1=42000 P2=7c000 P3=7e000 [07E956] $e956: A9 00 LDA #$00 A:FF X:0D Y:00 S:F3 P0=40000 P1=42000 P2=7c000 P3=7e000 [07E958] $e958: 8D 00 A0 STA $A000 A:00 X:0D Y:00 S:F3 P0=40000 P1=42000 P2=7c000 P3=7e000 [07E95B] $e95b: 4A LSR A:00 X:0D Y:00 S:F3 P0=40000 P1=42000 P2=7c000 P3=7e000 [07E95C] $e95c: 8D 00 A0 STA $A000 A:00 X:0D Y:00 S:F3 P0=40000 P1=42000 P2=7c000 P3=7e000 [07E95F] $e95f: 4A LSR A:00 X:0D Y:00 S:F3 P0=40000 P1=42000 P2=7c000 P3=7e000 [07E960] $e960: 8D 00 A0 STA $A000 A:00 X:0D Y:00 S:F3 P0=40000 P1=42000 P2=7c000 P3=7e000 [07E963] $e963: 4A LSR A:00 X:0D Y:00 S:F3 P0=40000 P1=42000 P2=7c000 P3=7e000 [07E964] $e964: 8D 00 A0 STA $A000 A:00 X:0D Y:00 S:F3 P0=40000 P1=42000 P2=7c000 P3=7e000 [07E967] $e967: 4A LSR A:00 X:0D Y:00 S:F3 P0=40000 P1=42000 P2=7c000 P3=7e000 [07E968] $e968: 8D 00 A0 STA $A000 A:00 X:0D Y:00 S:F3 P0=40000 P1=42000 P2=7c000 P3=7e000 [03E96B] $e96b: 4C 85 E1 JMP $E185 A:00 X:0D Y:00 S:F3 P0=00000 P1=02000 P2=3c000 P3=3e000
I know that this statement [07E952] $e952: A0 00 LDY #$00 A:00 X:0D Y:FF S:F3 P0=40000 P1=42000 P2=7c000 P3=7e000 [07E954] $e954: B1 6B LDA ($6B),Y @ $B1F3 = $FF A:00 X:0D Y:00 S:F3 P0=40000 P1=42000 P2=7c000 P3=7e000
is loading a value from bank 16. Is this how I am suppossed to do the swapping?
|
|
|
|
KingMike
Guest
|
|
« Reply #111 on: March 10, 2008, 06:55:01 pm » |
|
I notice you didn't swap the original 16K bank back in. Could that be the problem? (after storing 0 to register $A000, now you have bank 0 in $8000-BFFF)
Also, not sure if you're aware of it, but right after you read the expanded area, you're destroying the value by loading the accumulator with another value before saving it. Store that to RAM before the next statement (or do PHA, all the bankswapping, then PLA. That is, as long as you're using JMP commands to get back to the original code. If you use RTS, you're going to have to store to RAM, then read it back from RAM after you've finished swapping back.
|
|
« Last Edit: March 10, 2008, 07:03:50 pm by KingMike »
|
|
|
|
ded302
Guest
|
|
« Reply #112 on: March 10, 2008, 07:07:20 pm » |
|
Ill give that a try real fast.
Now the game doesnt reset.
|
|
« Last Edit: March 10, 2008, 07:21:17 pm by ded302 »
|
|
|
|
ded302
Guest
|
|
« Reply #113 on: March 30, 2008, 10:29:28 am » |
|
I recently downloaded a pc98 game called Aiza and messed around with it a little bit. I used Kingmikes shift-jis table file to locate the text in the executable file on the system floppy and in memory. After that, I found out that 2 bytes are used for a character. Then I was able to change Japanese letters to English letters. Also, I found the text routine using neko tracer and looking for in/out port commands. I also was able to use Disk Explorer to extract the Aiza.exe file and used hex workshop to add space to the end of the file. After that Aiza.exe was inserted back into the system floppy and the game ran without fail. Is there a list of pointers that corresponds to each text phrase in the executable file? If so can I modify those pointers to read text from an area with more space?
|
|
|
|
ded302
Guest
|
|
« Reply #114 on: April 29, 2008, 09:20:26 pm » |
|
Ive been trying to expand the main menu box in Shinsenden. A debugger was used to find the menubox data and its pointer. I found some freespace in the same bank as the menubox data and moved it there and remapped the pointer. I was able to change the size of the menubox to. But Ive ran into a problem, heres a screenshot of what Im talking about. Why would Equip and eck be repeated?
|
|
|
|
KaioShin
Guest
|
|
« Reply #115 on: April 30, 2008, 01:53:12 am » |
|
Double check your tilemap.
|
|
|
|
ded302
Guest
|
|
« Reply #116 on: April 30, 2008, 08:58:27 am » |
|
What does a tilemap look like and how would I find one?
|
|
|
|
KingMike
Guest
|
|
« Reply #117 on: April 30, 2008, 09:00:01 am » |
|
If you're still doing that PC98 game, you'd probably have to use Neko Tracer (and look up some docs on Intel 8086 ASM). Using the debugger, play the game, and do a RAM dump while playing. Look for the text in the RAM dump. Use breakpoints (set it for the RAM address of the text) to find the RAM address of the instruction that read the text. Now do a trace log (kinda hard to explain, so you'd have to read the docs with Neko Tracer). Hopefully, it'd lead you back to a table. addresses are represented as segment:offset, where address = (segment x $10) + offset. Hopefully, the game would play nice and only use segments that are multiples of $1000 (thus the high digit of the segment would be the $10000s digit of the address, but Last Armageddon wasn't so kind. It would reference the text using some combination like $1EAC:4672, which would be $1EAC0 + 4672 = (breaks out hex calculator) = $23132. Now, to answer your current question: The NES screen is like a big grid of tiles 32x30 (and there's 2 of them to help with scrolling). A nametable (aka tilemap) says which tile is at each location in that grid. Use FCEUXD SP, look at the Nametable to find where your text is located (note that in a free-scrolling game, it will likely be at a different every time you move). So don't move your character while debugging. Set a write breakpoint (in the debugger) for the tilemap address (choose PPU RAM) where the erroneous tiles appeared (the nametable viewer will tell you when you point to the specific tile. It'll probably start with a 2. Now go back to the game and open up the window, and the debugger should pop up. It'll be using a sta $2007 instuction to write the data (it'll probably use sta), so scroll up and see where it read from (should a ROM or CPU RAM). Trace back to find out where that data was accessed from until you find where the error came from.
|
|
« Last Edit: April 30, 2008, 09:10:10 am by KingMike »
|
|
|
|
Nightcrawler
Guest
|
|
« Reply #118 on: April 30, 2008, 09:03:45 am » |
|
That could happen for a variety of reasons relating to, as KaioShin said, writing to the tilemap. Your menu items are longer than the game expected, so it is doing something crazy after it's limit is reached. You'll have to find out what's happening and remedy the situation. You can fix this for sure, but it might be a little bit of a pain.
Already from the screenshot, it looks as though it's at least wrapping to some degree with 'Equip'. That's one limit you'll have to fix. The game hits a certain point and increments the tilemap write location by one line. I'm not certain about the repeat of the 'eck'. That, you'll discover in your research. I haven't worked on the NES in years, but I'd assume (never safe!) the tilemap is written out in RAM before it's copied to wherever it needs to go on the NES for video display.
EDIT: A tilemap is just that. A map of screen tiles. You have your tiles in video memory, and a map of the screen saying which tile goes where.
|
|
|
|
KingMike
Guest
|
|
« Reply #119 on: April 30, 2008, 09:18:25 am » |
|
Nitpicky, but NES games wouldn't often hold a copy of the nametable. A 2-screen nametable took up 2KB, which is also how much CPU RAM it had. It might have been easier if they used cart RAM. (otherwise I guess they'd reload the map data, maybe making a tilemap of a portion of the screen at a time)
|
|
|
|
|