jstout
-
Posts
545 -
Joined
-
Last visited
-
Days Won
5
Reputation Activity
-
jstout got a reaction from kamphuna8 in TSBm 1.3: Making your own FACES
Here is an example of how the faces are done:
Frank Reich:
x1C054 $A064 (POINTER) = B9A3
x1C3C9 $A3B9 (DESIGN) = CC10 CF60 CDCC CEBD CF97 B074
x1CC20 $AC10 (HAIR) = 700088 704090 710888 710890 7A0080 7A4098 FE
x1CDDC $ADCC (EARS) = 7A0080 7A4098 380800 384818 3A1000 3A5018 FE
x1CECD $AEBD (MOUTH) = 221408 225410 FE
x1CF70 $AF60 (EYES) = 1B0988 1B4990 FE
x1CFA7 $AF97 (LOWER HEAD) = 021008 025010 071808 075810 FE
x1D084 $B074 (UPPER HEAD) = 210008 214010 000808 004810 FF
Format: TILE ROW COLUMN
*ROW = +00 = NORMAL, +40 = HORIZONTAL MIRROR, +80 = VERTICAL MIRROR, +C0 = HORIZONTAL AND VERTICAL MIRROR
*COLUMN = +00 = PALETTE 0, +40 = PALETTE 01, +80 = PALETTE 02, +C0 = PALETTE 03
FE = NEXT
FF = END
-
jstout got a reaction from buck in NES Programming Info
I'm hoping the links work as this would be cleaner than having a few dozen posts thrown all about. This is still a work in progress with more in the future and the below files are still subject to changes/improvements as I'm not happy with all of them. All demos should contain source files for the ca65 assembler and a working rom. For those that read these please let me know of things that are good, bad, and need much more clarification.
Complete Folder
6502:
Number Formats
Registers
Processor Status Flags
Opcodes - Transfer Operations
Opcodes - Other Operations
Opcodes - Programming Model
Addressing Modes
Complete Opcodes
Basic Math
NES Programming:
Memory Map
NES Header
PPU Registers
Skeleton ROM
Palettes Demo
Sprites Demo
Controllers Demo
Backgrounds Demo
Scrolling Demo
Sprite 0 Hit Demo
Animated Sprites Demo
Camera Window Demo
Collision Detection Demo
MMC3 Demo
-
jstout got a reaction from Neerrm in NES Programming Info
I'm hoping the links work as this would be cleaner than having a few dozen posts thrown all about. This is still a work in progress with more in the future and the below files are still subject to changes/improvements as I'm not happy with all of them. All demos should contain source files for the ca65 assembler and a working rom. For those that read these please let me know of things that are good, bad, and need much more clarification.
Complete Folder
6502:
Number Formats
Registers
Processor Status Flags
Opcodes - Transfer Operations
Opcodes - Other Operations
Opcodes - Programming Model
Addressing Modes
Complete Opcodes
Basic Math
NES Programming:
Memory Map
NES Header
PPU Registers
Skeleton ROM
Palettes Demo
Sprites Demo
Controllers Demo
Backgrounds Demo
Scrolling Demo
Sprite 0 Hit Demo
Animated Sprites Demo
Camera Window Demo
Collision Detection Demo
MMC3 Demo
-
jstout got a reaction from quince3800 in NES Programming Info
I'm hoping the links work as this would be cleaner than having a few dozen posts thrown all about. This is still a work in progress with more in the future and the below files are still subject to changes/improvements as I'm not happy with all of them. All demos should contain source files for the ca65 assembler and a working rom. For those that read these please let me know of things that are good, bad, and need much more clarification.
Complete Folder
6502:
Number Formats
Registers
Processor Status Flags
Opcodes - Transfer Operations
Opcodes - Other Operations
Opcodes - Programming Model
Addressing Modes
Complete Opcodes
Basic Math
NES Programming:
Memory Map
NES Header
PPU Registers
Skeleton ROM
Palettes Demo
Sprites Demo
Controllers Demo
Backgrounds Demo
Scrolling Demo
Sprite 0 Hit Demo
Animated Sprites Demo
Camera Window Demo
Collision Detection Demo
MMC3 Demo
-
jstout got a reaction from Knobbe in NES Programming Info
I'm hoping the links work as this would be cleaner than having a few dozen posts thrown all about. This is still a work in progress with more in the future and the below files are still subject to changes/improvements as I'm not happy with all of them. All demos should contain source files for the ca65 assembler and a working rom. For those that read these please let me know of things that are good, bad, and need much more clarification.
Complete Folder
6502:
Number Formats
Registers
Processor Status Flags
Opcodes - Transfer Operations
Opcodes - Other Operations
Opcodes - Programming Model
Addressing Modes
Complete Opcodes
Basic Math
NES Programming:
Memory Map
NES Header
PPU Registers
Skeleton ROM
Palettes Demo
Sprites Demo
Controllers Demo
Backgrounds Demo
Scrolling Demo
Sprite 0 Hit Demo
Animated Sprites Demo
Camera Window Demo
Collision Detection Demo
MMC3 Demo
-
jstout got a reaction from buck in Passing Loft
Passing loft is just part of creating the arc you see in the game. The Arc needs to know other things like velocity to create a pass that will hit the mark. But if test or watch the video then you'll see the xFF loft is a straight line and the x01 has some upward movement but nothing that would be comical so all the x30 values will look fairly similar.
>http://www.youtube.com/watch?v=KsFvQ8MwaNc
-
jstout got a reaction from bruddog in A great intro to 6502 Assembly
I was intrigued as most wanted a hacking front to back example. The grappling hack was involved with only light complications. I spent much much much longer writing this all out then actually going through the steps this morning. This definitely needs some cleanup and only you guys can tell me if I need to dumb it down more or if I was babying you too much at times but this will give an idea of the steps I followed that you can replicate. Feedback will improve this too as I tried to get this done as fast as possible without detailing every last exact button name to press (just told to do it).
The FCEUX Save State and the Code/Data logs I remembered to save are attached so you can see what I saw with them. I'm using FCEUX 2.2.1, http://www.fceux.com/web/home.html, and the original TSB rom. So here it goes hoping all this text fits and I already know my clean looking notepad format will be ripped to shreds in the post =) I'll probably created a new topic when all the other stuff is created or more ready to go than this so its easily found in one place.
ManVsGrappleFiles.zip
GOAL: Improve Man vs Com Grappling
KNOW: Pressing buttons on controller helps determines grapple winner. High HP popcorns opponent. Com can't use a controller to press buttons.
START: Find the Man Presses.
HOW:
A. Find the controller RAM storage then using the storage to count presses
B. Find when it counts presses
We'll attempt with Option B as it would be the quickest method if found.
--------------------
GOAL: Find the press counter
Step 1. Get a save state just before a grapple occurs so we can reload and test over and over again.
Step 2. Open the Code/Data Logger and hit Start.
Step 3. Run winning a grapple then pause the emulator and then run losing a grapple (no presses) then pause the emulator then pause the Code/Data Logger.
Step 4. Pause the emulator during a grapple and open the Cheats...
1. In the Cheat Search hit Reset
2. Presses could be counted up (highest value) or down (first to a certain number). Logically we expect up.
3. Hit 00 Known Value = 639 Possibilities
4. Unpause grapple then repause during grapple. (If Grapple is done then reload save state to get back into grapple)
5. Hit 00 Known Value = 636 Possibilities
6. Unpause grapple, press A Button, then repause during grapple. (If Grapple is done then reload save state to get back into grapple then hit A Button)
7. Hit Greater Than = 51 Possibilites
8. Unpause grapple, press A Button, then repause during grapple. (If Grapple is done then reload save state to get back into grapple then hit A Button twice)
9. Hit Greater Than = 3 Possibilites (only $03BC == 02 so we expect this to be the location)
Step 5. We are looking for press confirmaton. In the Debugger, Add Breakpoint with Address: 03BC and Write
1. Reload the Save State
2. Determine the breakpoints by writing down each location and hitting run to find the next until grapple finishes then pause
3. Repeat 1 and 2 hitting the A button during the grapple
At Contact: x2826A 0A:825A:91 AE STA ($AE),Y @ $03BC [A = 00] This should be the press reset
At Press: x28285 0A:8275:91 AE STA ($AE),Y @ $03BC [A = 01] This should be the press storage
Step 6. Gather some information off these breakpoints.
1. Double-click on the 3BC breakpoint to disable
2. Add Breakpoint with Address: 825A and Execute
3. Add Breakpoint with Address: 8275 and Execute
4. Open the Trace Logger and have it start logging in the window
5. Reload the Save State and enter the grapple
Trace Logger:
$DAC1:A0 07 LDY #$07 A:00 X:00 Y:05 S:39 P:nvUBdiZC
$DAC3:B1 AE LDA ($AE),Y @ $0606 = #$82 A:00 X:00 Y:07 S:39 P:nvUBdizC
$DAC5:48 PHA A:82 X:00 Y:07 S:39 P:NvUBdizC
$DAC6:88 DEY A:82 X:00 Y:07 S:38 P:NvUBdizC
$DAC7:B1 AE LDA ($AE),Y @ $0605 = #$55 A:82 X:00 Y:06 S:38 P:nvUBdizC
$DAC9:48 PHA A:55 X:00 Y:06 S:38 P:nvUBdizC
$DACA:60 RTS (from $DACB) ----------------- A:55 X:00 Y:06 S:37 P:nvUBdizC
$8256:A9 00 LDA #$00 A:55 X:00 Y:06 S:39 P:nvUBdizC ; RESET PRESS COUNTER
$8258:A0 1D LDY #$1D A:00 X:00 Y:06 S:39 P:nvUBdiZC
Breakpoint 1 Hit at $825A: $825A:EC--X-
6. Change 825A Breakpoint Addresss to 8256
7. Stop the Trace Logger
8. Copy Code from the Debugger using 8256 and 8275 and label the obvious
0A:8256:A9 00 LDA #$00 ; RESET PRESS VALUE
0A:8258:A0 1D LDY #$1D ; #$1D INDEX to PRESS COUNTER
0A:825A:91 AE STA ($AE),Y @ $03BC ; $AE = POINTER, $03BC = PRESS COUNTER
0A:825C:A0 01 LDY #$01
0A:825E:B1 AE LDA ($AE),Y @ $03A0
0A:8260:29 40 AND #$40
0A:8262:F0 16 BEQ $827A
0A:8264:A9 01 LDA #$01
0A:8266:20 CB DA JSR $DACB
0A:8269:20 08 A1 JSR $A108 ; COUNT?
0A:826C:10 F6 BPL $8264
0A:826E:A0 1D LDY #$1D ; INDEX TO PRESS COUNTER
0A:8270:B1 AE LDA ($AE),Y @ $03BC ; LOAD PRESS COUNTER
0A:8272:18 CLC
0A:8273:69 01 ADC #$01 ; ADD 1 TO PRESS COUNTER
0A:8275:91 AE STA ($AE),Y @ $03BC ; STORE PRESSES
0A:8277:4C 64 82 JMP $8264 ; REPEAT AT $8264
Step 7. Determine when the press counter is used (exluding the read to store the counter we found above)
1. Add Breakpoint with Address: 03BC and Read with Condition: P != #8270
2. Reload the Save State and enter the grapple
At End: x284F6 0A:84E6:B1 AE LDA ($AE),Y @ $03BC This should be read for the press winner
3. Reset Code/Data Logger then hit Start. Win a grapple and Lose a Grapple as above.
4. Copy Code from Debugger (with help from Code/Data Logger spotting the entry point) and label the obvious
*In the Hex Editor, using the View Menu set to ROM File (Code/Data Logger makes Data Blue, Code Gold, Code and Data Green, Unused Black)
0A:84DC:20 4C B1 JSR $B14C
0A:84DF:A9 40 LDA #$40
0A:84E1:20 CB DA JSR $DACB
0A:84E4:A0 1D LDY #$1D ; PRESS COUNTER INDEX
0A:84E6:B1 AE LDA ($AE),Y @ $03BC ; LOAD PRESS COUNTER
0A:84E8:C9 02 CMP #$02
0A:84EA:90 0D BCC $84F9 ; LESS THAN 2 PRESSES?
; GREATER THAN OR EQUAL TO 2 PRESSES
0A:84EC:20 90 B1 JSR $B190
0A:84EF:A0 81 LDY #$81
0A:84F1:A2 85 LDX #$85
0A:84F3:20 C9 B1 JSR $B1C9
0A:84F6:4C 23 87 JMP $8723 ; EXIT
; LESS THAN 2 PRESSES
0A:84F9:20 90 B1 JSR $B190
0A:84FC:A0 22 LDY #$22
0A:84FE:A2 87 LDX #$87
0A:8500:20 C9 B1 JSR $B1C9
0A:8503:A9 01 LDA #$01
0A:8505:20 CB DA JSR $DACB
0A:8508:4C 51 85 JMP $8551 ; EXIT
5. When we force to $84F9 by either NOP or JMP (refer to the 6502 opcodes for these values), quick testing shows Player 1 always loses the grapple
6. When we force to $84EC by NOP, quick testing shows Player 1 always wins the grapple
We found our grapple section we need to edit but we are lacking all the info we what to use.
--------------------
GOAL 2: We want to include HP so we need to find if its already loaded for our use
KNOW: High HP popcorns opponent. Each Player has a section containing important game info. Its well documented and easy to find regardless so my Save State player QB Bills HP: x3011 2nd Nibble
START: HP of our player
Step 1. Add a Breakpoint for HP
1. Address: 9001 and Read with Condition: $9001 == #11
2. Address: B001 and Read with Condition: $B001 == #11
*We don't know if x3011 is in the $8000 or $A000 Bank so we set both.
3. Disable prior breakpoints
4. Determine the breakpoints by writing down each location and hitting run between the play call screen and game screen
First Hit: x3DDEB >0F:DDDB:B1 3E LDA ($3E),Y @ $B001 = #$11
Second Hit: x3DDEB >0F:DDDB:B1 3E LDA ($3E),Y @ $B001 = #$11
5. Do it again but in the Debugger hit Step Into after hit to determine how its used
First Step Into:
>0F:DDDB:B1 3E LDA ($3E),Y @ $B001
0F:DDDD:B0 04 BCS $DDE3
0F:DDDF:4A LSR
0F:DDE0:4A LSR
0F:DDE1:4A LSR
0F:DDE2:4A LSR
0F:DDE3:29 0F AND #$0F
0F:DDE5:85 3E STA $003E ; FIRST NIBBLE
Second Step Into:
>0F:DDDB:B1 3E LDA ($3E),Y @ $B001
0F:DDDD:B0 04 BCS $DDE3
0F:DDE3:29 0F AND #$0F
0F:DDE5:85 3E STA $003E ; SECOND NIBBLE
6. Add Breakpoint with Address: 3E and Read and Write but disable it
7. Wait until second breakpoint and enable the 3E breakpoint then hit run
x3DE0E 0F:DDFE:65 3E ADC $003E Adding our value to something
x3DDC8 0F:DDB8:85 3E STA $003E Removes our number and quick inspection of debugger shows its creating a pointer
8. In the Debugger seek to DDFE and copy the code until the exit.
0F:DDE7:A5 45 LDA $0045
0F:DDE9:4A LSR
0F:DDEA:4A LSR
0F:DDEB:A8 TAY
0F:DDEC:28 PLP
0F:DDED:B0 06 BCS $DDF5
0F:DDEF:B9 03 65 LDA $6503,Y
0F:DDF2:4C F8 DD JMP $DDF8
0F:DDF5:B9 08 66 LDA $6608,Y
0F:DDF8:A6 45 LDX $0045
0F:DDFA:20 40 DE JSR $DE40
0F:DDFD:18 CLC
0F:DDFE:65 3E ADC $003E
0F:DE00:38 SEC
0F:DE01:E9 01 SBC #$01
0F:DE03:B0 02 BCS $DE07
0F:DE05:A9 00 LDA #$00
0F:DE07:C9 10 CMP #$10
0F:DE09:90 02 BCC $DE0D
0F:DE0B:A9 0F LDA #$0F
0F:DE0D:A8 TAY
0F:DE0E:A6 44 LDX $0044
0F:DE10:20 E3 D8 JSR $D8E3
0F:DE13:98 TYA
0F:DE14:60 RTS ------------------------------- ; EXIT
9. Add a Breakpoint at Address: DE14 and Execute but disable
10. Do 6 and 7 again but also enable the DE14 breakpoint.
11. At the DE14 breakpoint, use the debugger Step Into storing the code until values are gone then label the obvious
0F:DDE7:A5 45 LDA $0045
0F:DDE9:4A LSR
0F:DDEA:4A LSR
0F:DDEB:A8 TAY
0F:DDEC:28 PLP
0F:DDED:B0 06 BCS $DDF5
0F:DDEF:B9 03 65 LDA $6503,Y @ $6503
0F:DDF2:4C F8 DD JMP $DDF8
0F:DDF5:B9 08 66 LDA $6608,Y @ $6608
0F:DDF8:A6 45 LDX $0045
0F:DDFA:20 40 DE JSR $DE40 ; GET CONDITIONAL BOOSTS
0F:DDFD:18 CLC
0F:DDFE:65 3E ADC $003E ; ADD HP
0F:DE00:38 SEC
0F:DE01:E9 01 SBC #$01 ; SUBTRACT 1
0F:DE03:B0 02 BCS $DE07 ; NEGATIVE VALUE?
0F:DE05:A9 00 LDA #$00 ; SET TO 0 IF NEGATIVE
0F:DE07:C9 10 CMP #$10
0F:DE09:90 02 BCC $DE0D ; ABOVE MAX?
0F:DE0B:A9 0F LDA #$0F ; SET TO MAX IF TOO LARGE
0F:DE0D:A8 TAY ; FINAL HP TO Y
0F:DE0E:A6 44 LDX $0044
0F:DE10:20 E3 D8 JSR $D8E3
0F:DE13:98 TYA ; FINAL HP TO A
0F:DE14:60 RTS -------------------------------
0D:86B4:AA TAX ; FINAL HP TO X (NOTE FINAL HP IS IN A, X, Y)
0D:86B5:60 RTS -------------------------------
0D:8675:AA TAX ; SET HP AS INDEX FOR TABLE
0D:8676:BD EF DF LDA $DFEF,X @ $DFF0 ; GET HP VALUE FROM TABLE
0D:8679:A0 1C LDY #$1C ; HP VALUE INDEX
0D:867B:91 40 STA ($40),Y @ $03BB ; STORE HP VALUE
... CONTINUE ELIMINATES FINAL HP IN REGISTERS A,X,Y
Step 2. Add a breakpoint for the new HP location we found
1. Delete the 9001, B001, 3E, DE14 breakpoints
2. Add a breakpoint for Address: 03BB and Read and Write
4. Enable the breakpoints at 8256 and 8275 (We know the HP has to be checked first)
5. Pause the emulator and reset the Code/Data Logger hit Run
6. Reload our save state just before the grapple and record the breakpoints for $03BB
At Contact: x284D9 0A:84C9:B1 AE LDA ($AE),Y @ $03BB Read HP for Popcorn Check
7. Pause the Code/Data Logger
8. Reload before the grapple until breakpoint and copy Code from Debugger (with help from Code/Data Logger spotting the entry point) and label the obvious
0A:84C7:A0 1C LDY #$1C ; HP VALUE INDEX
0A:84C9:B1 AE LDA ($AE),Y @ $03BB ; MAN HP VALUE ($AE is MAN POINTER)
0A:84CB:38 SEC
0A:84CC:F1 3E SBC ($3E),Y @ $061B ; SUBTRACT COM HP VALUE ($3E is COM POINTER; $61B ADDRESS - #$1C INDEX = $05FF POINTER)
0A:84CE:90 04 BCC $84D4 ; MAN LESS THAN COM HP VALUE?
; MAN MORE THAN COM HP VALUE
0A:84D0:C9 20 CMP #$20
0A:84D2:B0 18 BCS $84EC ; MAN MORE THAN COM HP VALUE BY x20+ (THIS HEADS STRAIGHT TO WIN GRAPPLE)
; MAN LESS THAN COM HP VALUE
0A:84D4:20 36 B1 JSR $B136
0A:84D7:A9 01 LDA #$01
0A:84D9:20 CB DA JSR $DACB
; We know the following code here is the Man vs Com press check from above
0A:84DC:20 4C B1 JSR $B14C
0A:84DF:A9 40 LDA #$40
0A:84E1:20 CB DA JSR $DACB
0A:84E4:A0 1D LDY #$1D ; PRESS COUNTER INDEX
0A:84E6:B1 AE LDA ($AE),Y @ $03BC ; LOAD PRESS COUNTER
0A:84E8:C9 02 CMP #$02
0A:84EA:90 0D BCC $84F9 ; LESS THAN 2 PRESSES?
; GREATER THAN OR EQUAL TO 2 PRESSES
0A:84EC:20 90 B1 JSR $B190
0A:84EF:A0 81 LDY #$81
0A:84F1:A2 85 LDX #$85
0A:84F3:20 C9 B1 JSR $B1C9
0A:84F6:4C 23 87 JMP $8723 ; EXIT
; LESS THAN 2 PRESSES
0A:84F9:20 90 B1 JSR $B190
0A:84FC:A0 22 LDY #$22
0A:84FE:A2 87 LDX #$87
0A:8500:20 C9 B1 JSR $B1C9
0A:8503:A9 01 LDA #$01
0A:8505:20 CB DA JSR $DACB
0A:8508:4C 51 85 JMP $8551 ; EXIT
Step 3. Find the Com Pointer creation
1. Add a breakpoint of Address: 3E to 3F and Write with Condition: A == #FF (From the Pointer calculation of $05FF above). We'll change A to X then Y if the most common A isn't correct.
2. Reset the Trace Logger and hit Start in the window
3. Reload before the grapple until we reach our beginning breakpoint of 84C7 then label the obvious
$832E:20 90 B1 JSR $B190 A:2D X:07 Y:03 S:39 P:nvUBdizC ; GET COM POINTER
$B190:A0 1E LDY #$1E A:2D X:07 Y:03 S:37 P:nvUBdizC ; INDEX
$B192:B1 AE LDA ($AE),Y @ $03BD = #$FF A:2D X:07 Y:1E S:37 P:nvUBdizC ; FROM MAN PLAYER
Breakpoint 5 Hit at $B194: $003E-003F:EC-W-- Condition:A == #FF
$B194:85 3E STA $003E = #$4A A:FF X:07 Y:1E S:37 P:NvUBdizC ; COM POINTER LO
$B196:C8 INY A:FF X:07 Y:1E S:37 P:NvUBdizC ; NEXT INDEX
$B197:B1 AE LDA ($AE),Y @ $03BE = #$05 A:FF X:07 Y:1F S:37 P:nvUBdizC ; FROM MAN PLAYER
$B199:85 3F STA $003F = #$B2 A:05 X:07 Y:1F S:37 P:nvUBdizC ; COM POINTER HI
$B19B:60 RTS (from $B190) ----------------- A:05 X:07 Y:1F S:37 P:nvUBdizC ; EXIT
$8331:A0 01 LDY #$01 A:05 X:07 Y:1F S:39 P:nvUBdizC
$8333:B1 AE LDA ($AE),Y @ $03A0 = #$60 A:05 X:07 Y:01 S:39 P:nvUBdizC
$8335:29 40 AND #$40 A:60 X:07 Y:01 S:39 P:nvUBdizC
$8337:F0 0C BEQ $8345 A:40 X:07 Y:01 S:39 P:nvUBdizC
$8339:B1 3E LDA ($3E),Y @ $0600 = #$80 A:40 X:07 Y:01 S:39 P:nvUBdizC
$833B:29 40 AND #$40 A:80 X:07 Y:01 S:39 P:NvUBdizC
$833D:F0 03 BEQ $8342 A:00 X:07 Y:01 S:39 P:nvUBdiZC
$8342:4C C7 84 JMP $84C7 A:00 X:07 Y:01 S:39 P:nvUBdiZC ; JUMP TO GRAPPLE ROUTINE
Breakpoint 4 Hit at $84C7: $84C7:EC--X-
Now he have the Pointer for the Man and Com players with their HP values
--------------------
GOAL: Write the Improvement Code with the knowledge we acquired
KNOW: $3B-$3D are Random Values
START: Write it in notepad
Step 1. Write the code out
0A:84C7:A0 1C LDY #$1C ; HP VALUE INDEX
0A:84C9:B1 AE LDA ($AE),Y @ $03BB ; MAN HP VALUE ($AE is MAN POINTER)
0A:84CB:38 SEC
0A:84CC:F1 3E SBC ($3E),Y @ $061B ; SUBTRACT COM HP VALUE ($3E is COM POINTER; $61B ADDRESS - #$1C INDEX = $05FF POINTER)
0A:84CE:90 04 BCC $84D4 ; MAN LESS THAN COM HP VALUE?
; MAN MORE THAN COM HP VALUE
0A:84D0:C9 20 CMP #$20
0A:84D2:B0 18 BCS $84EC ; MAN MORE THAN COM HP VALUE BY x20+ (THIS HEADS STRAIGHT TO WIN GRAPPLE)
; MAN LESS THAN COM HP VALUE
0A:84D4:20 36 B1 JSR $B136
0A:84D7:A9 01 LDA #$01
0A:84D9:20 CB DA JSR $DACB
0A:84DC:20 4C B1 JSR $B14C
0A:84DF:A9 40 LDA #$40
0A:84E1:20 CB DA JSR $DACB
A0 1C LDY #$1C ; HP INDEX
B1 AE LDA ($AE),Y ; LOAD MAN HP
4A LSR
4A LSR
4A LSR
C8 INY ; PRESS INDEX
18 CLC
71 AE ADC ($AE),Y ; HP/8 + PRESS
91 AE STA ($AE),Y ; STORE IN MAN PRESS COUNTER
20 90 B1 JSR $B190 ; LOAD COM POINTER
A0 1C LDY #$1C ; HP INDEX
B1 3E LDA ($3E),Y ; LOAD COM HP
4A LSR
4A LSR
4A LSR
C8 INY
91 3E STA ($3E),Y ; STORE HP/8 IN COM PRESS COUNTER
A5 3D LDA $003D ; RANDOM NUMBER
29 0F AND #$0F ; MAKE RANDOM x0-F
18 CLC
71 3E ADC ($3E),Y ; HP/8 + RANDOM
91 3E STA ($3E),Y ; STORE IN COM PRESS COUNTER
B1 AE LDA ($AE),Y ; LOAD MAN PRESS COUNTER
D1 3E CMP ($3E),Y ; COMPARE WITH COM PRESS COUNTER
0A:84EA:90 0D BCC $84F9 ; LESS THAN COM?
; GREATER THAN OR EQUAL TO COM PRESSES
0A:84EC:20 90 B1 JSR $B190
0A:84EF:A0 81 LDY #$81
0A:84F1:A2 85 LDX #$85
0A:84F3:20 C9 B1 JSR $B1C9
0A:84F6:4C 23 87 JMP $8723 ; EXIT
; LESS THAN COM PRESSES
0A:84F9:20 90 B1 JSR $B190
0A:84FC:A0 22 LDY #$22
0A:84FE:A2 87 LDX #$87
0A:8500:20 C9 B1 JSR $B1C9
0A:8503:A9 01 LDA #$01
0A:8505:20 CB DA JSR $DACB
0A:8508:4C 51 85 JMP $8551 ; EXIT
Step 2. Insert the Code
1. Open the Hex Editor
2. Using the debugger, Add a breakpoint with Address: 84E4 and Execute and Disable the other breakpoints
3. Reload and run until breakpoint
4. In the debugger, Seek To 9FFF and scroll up searching for empty space (not enough there)
5. In the debugger, Seek To BFFF and scroll up searching for empty space (we have room where these FFs are)
*Its usually a good idea to leave the first FF unless you know its not used but in this case I'm starting at the start of a fresh line
6. Type in our code so it fits.
At x284F4:
20 40 BF JSR $BF40 ; NEW MAN VS CPU GRAPPLING CODE
At x2BF50:
MAN VS CPU GRAPPLING:
A0 1C LDY #$1C ; HP INDEX
B1 AE LDA ($AE),Y ; LOAD MAN HP
4A LSR
4A LSR
4A LSR
C8 INY ; PRESS INDEX
18 CLC
71 AE ADC ($AE),Y ; HP/8 + PRESS
91 AE STA ($AE),Y ; STORE IN MAN PRESS COUNTER
20 90 B1 JSR $B190 ; LOAD COM POINTER
A0 1C LDY #$1C ; HP INDEX
B1 3E LDA ($3E),Y ; LOAD COM HP
4A LSR
4A LSR
4A LSR
C8 INY
91 3E STA ($3E),Y ; STORE HP/8 IN COM PRESS COUNTER
A5 3D LDA $003D ; RANDOM NUMBER
29 0F AND #$0F ; MAKE RANDOM x0-F
18 CLC
71 3E ADC ($3E),Y ; HP/8 + RANDOM
91 3E STA ($3E),Y ; STORE IN COM PRESS COUNTER
; RETURN TO NORMAL
B1 AE LDA ($AE),Y ; LOAD MAN PRESS COUNTER AS BEFORE
60 RTS
At x284E5
; RETURN HERE
EA NOP
D1 3E CMP ($3E),Y ; REPLACE CMP #$02 with COM PRESS COUNTER
Step 3. Test the game to make sure everything works and the inserted code never gets swapped out when its needed
--------------------
Repeat with a Man vs Man grapple to determine if the same code or new code but I'll leave that to you to work on your skills =)
-
jstout got a reaction from Knobbe in Passing Loft
Passing loft is just part of creating the arc you see in the game. The Arc needs to know other things like velocity to create a pass that will hit the mark. But if test or watch the video then you'll see the xFF loft is a straight line and the x01 has some upward movement but nothing that would be comical so all the x30 values will look fairly similar.
>http://www.youtube.com/watch?v=KsFvQ8MwaNc
-
jstout got a reaction from GameplayLoop in A great intro to 6502 Assembly
I was intrigued as most wanted a hacking front to back example. The grappling hack was involved with only light complications. I spent much much much longer writing this all out then actually going through the steps this morning. This definitely needs some cleanup and only you guys can tell me if I need to dumb it down more or if I was babying you too much at times but this will give an idea of the steps I followed that you can replicate. Feedback will improve this too as I tried to get this done as fast as possible without detailing every last exact button name to press (just told to do it).
The FCEUX Save State and the Code/Data logs I remembered to save are attached so you can see what I saw with them. I'm using FCEUX 2.2.1, http://www.fceux.com/web/home.html, and the original TSB rom. So here it goes hoping all this text fits and I already know my clean looking notepad format will be ripped to shreds in the post =) I'll probably created a new topic when all the other stuff is created or more ready to go than this so its easily found in one place.
ManVsGrappleFiles.zip
GOAL: Improve Man vs Com Grappling
KNOW: Pressing buttons on controller helps determines grapple winner. High HP popcorns opponent. Com can't use a controller to press buttons.
START: Find the Man Presses.
HOW:
A. Find the controller RAM storage then using the storage to count presses
B. Find when it counts presses
We'll attempt with Option B as it would be the quickest method if found.
--------------------
GOAL: Find the press counter
Step 1. Get a save state just before a grapple occurs so we can reload and test over and over again.
Step 2. Open the Code/Data Logger and hit Start.
Step 3. Run winning a grapple then pause the emulator and then run losing a grapple (no presses) then pause the emulator then pause the Code/Data Logger.
Step 4. Pause the emulator during a grapple and open the Cheats...
1. In the Cheat Search hit Reset
2. Presses could be counted up (highest value) or down (first to a certain number). Logically we expect up.
3. Hit 00 Known Value = 639 Possibilities
4. Unpause grapple then repause during grapple. (If Grapple is done then reload save state to get back into grapple)
5. Hit 00 Known Value = 636 Possibilities
6. Unpause grapple, press A Button, then repause during grapple. (If Grapple is done then reload save state to get back into grapple then hit A Button)
7. Hit Greater Than = 51 Possibilites
8. Unpause grapple, press A Button, then repause during grapple. (If Grapple is done then reload save state to get back into grapple then hit A Button twice)
9. Hit Greater Than = 3 Possibilites (only $03BC == 02 so we expect this to be the location)
Step 5. We are looking for press confirmaton. In the Debugger, Add Breakpoint with Address: 03BC and Write
1. Reload the Save State
2. Determine the breakpoints by writing down each location and hitting run to find the next until grapple finishes then pause
3. Repeat 1 and 2 hitting the A button during the grapple
At Contact: x2826A 0A:825A:91 AE STA ($AE),Y @ $03BC [A = 00] This should be the press reset
At Press: x28285 0A:8275:91 AE STA ($AE),Y @ $03BC [A = 01] This should be the press storage
Step 6. Gather some information off these breakpoints.
1. Double-click on the 3BC breakpoint to disable
2. Add Breakpoint with Address: 825A and Execute
3. Add Breakpoint with Address: 8275 and Execute
4. Open the Trace Logger and have it start logging in the window
5. Reload the Save State and enter the grapple
Trace Logger:
$DAC1:A0 07 LDY #$07 A:00 X:00 Y:05 S:39 P:nvUBdiZC
$DAC3:B1 AE LDA ($AE),Y @ $0606 = #$82 A:00 X:00 Y:07 S:39 P:nvUBdizC
$DAC5:48 PHA A:82 X:00 Y:07 S:39 P:NvUBdizC
$DAC6:88 DEY A:82 X:00 Y:07 S:38 P:NvUBdizC
$DAC7:B1 AE LDA ($AE),Y @ $0605 = #$55 A:82 X:00 Y:06 S:38 P:nvUBdizC
$DAC9:48 PHA A:55 X:00 Y:06 S:38 P:nvUBdizC
$DACA:60 RTS (from $DACB) ----------------- A:55 X:00 Y:06 S:37 P:nvUBdizC
$8256:A9 00 LDA #$00 A:55 X:00 Y:06 S:39 P:nvUBdizC ; RESET PRESS COUNTER
$8258:A0 1D LDY #$1D A:00 X:00 Y:06 S:39 P:nvUBdiZC
Breakpoint 1 Hit at $825A: $825A:EC--X-
6. Change 825A Breakpoint Addresss to 8256
7. Stop the Trace Logger
8. Copy Code from the Debugger using 8256 and 8275 and label the obvious
0A:8256:A9 00 LDA #$00 ; RESET PRESS VALUE
0A:8258:A0 1D LDY #$1D ; #$1D INDEX to PRESS COUNTER
0A:825A:91 AE STA ($AE),Y @ $03BC ; $AE = POINTER, $03BC = PRESS COUNTER
0A:825C:A0 01 LDY #$01
0A:825E:B1 AE LDA ($AE),Y @ $03A0
0A:8260:29 40 AND #$40
0A:8262:F0 16 BEQ $827A
0A:8264:A9 01 LDA #$01
0A:8266:20 CB DA JSR $DACB
0A:8269:20 08 A1 JSR $A108 ; COUNT?
0A:826C:10 F6 BPL $8264
0A:826E:A0 1D LDY #$1D ; INDEX TO PRESS COUNTER
0A:8270:B1 AE LDA ($AE),Y @ $03BC ; LOAD PRESS COUNTER
0A:8272:18 CLC
0A:8273:69 01 ADC #$01 ; ADD 1 TO PRESS COUNTER
0A:8275:91 AE STA ($AE),Y @ $03BC ; STORE PRESSES
0A:8277:4C 64 82 JMP $8264 ; REPEAT AT $8264
Step 7. Determine when the press counter is used (exluding the read to store the counter we found above)
1. Add Breakpoint with Address: 03BC and Read with Condition: P != #8270
2. Reload the Save State and enter the grapple
At End: x284F6 0A:84E6:B1 AE LDA ($AE),Y @ $03BC This should be read for the press winner
3. Reset Code/Data Logger then hit Start. Win a grapple and Lose a Grapple as above.
4. Copy Code from Debugger (with help from Code/Data Logger spotting the entry point) and label the obvious
*In the Hex Editor, using the View Menu set to ROM File (Code/Data Logger makes Data Blue, Code Gold, Code and Data Green, Unused Black)
0A:84DC:20 4C B1 JSR $B14C
0A:84DF:A9 40 LDA #$40
0A:84E1:20 CB DA JSR $DACB
0A:84E4:A0 1D LDY #$1D ; PRESS COUNTER INDEX
0A:84E6:B1 AE LDA ($AE),Y @ $03BC ; LOAD PRESS COUNTER
0A:84E8:C9 02 CMP #$02
0A:84EA:90 0D BCC $84F9 ; LESS THAN 2 PRESSES?
; GREATER THAN OR EQUAL TO 2 PRESSES
0A:84EC:20 90 B1 JSR $B190
0A:84EF:A0 81 LDY #$81
0A:84F1:A2 85 LDX #$85
0A:84F3:20 C9 B1 JSR $B1C9
0A:84F6:4C 23 87 JMP $8723 ; EXIT
; LESS THAN 2 PRESSES
0A:84F9:20 90 B1 JSR $B190
0A:84FC:A0 22 LDY #$22
0A:84FE:A2 87 LDX #$87
0A:8500:20 C9 B1 JSR $B1C9
0A:8503:A9 01 LDA #$01
0A:8505:20 CB DA JSR $DACB
0A:8508:4C 51 85 JMP $8551 ; EXIT
5. When we force to $84F9 by either NOP or JMP (refer to the 6502 opcodes for these values), quick testing shows Player 1 always loses the grapple
6. When we force to $84EC by NOP, quick testing shows Player 1 always wins the grapple
We found our grapple section we need to edit but we are lacking all the info we what to use.
--------------------
GOAL 2: We want to include HP so we need to find if its already loaded for our use
KNOW: High HP popcorns opponent. Each Player has a section containing important game info. Its well documented and easy to find regardless so my Save State player QB Bills HP: x3011 2nd Nibble
START: HP of our player
Step 1. Add a Breakpoint for HP
1. Address: 9001 and Read with Condition: $9001 == #11
2. Address: B001 and Read with Condition: $B001 == #11
*We don't know if x3011 is in the $8000 or $A000 Bank so we set both.
3. Disable prior breakpoints
4. Determine the breakpoints by writing down each location and hitting run between the play call screen and game screen
First Hit: x3DDEB >0F:DDDB:B1 3E LDA ($3E),Y @ $B001 = #$11
Second Hit: x3DDEB >0F:DDDB:B1 3E LDA ($3E),Y @ $B001 = #$11
5. Do it again but in the Debugger hit Step Into after hit to determine how its used
First Step Into:
>0F:DDDB:B1 3E LDA ($3E),Y @ $B001
0F:DDDD:B0 04 BCS $DDE3
0F:DDDF:4A LSR
0F:DDE0:4A LSR
0F:DDE1:4A LSR
0F:DDE2:4A LSR
0F:DDE3:29 0F AND #$0F
0F:DDE5:85 3E STA $003E ; FIRST NIBBLE
Second Step Into:
>0F:DDDB:B1 3E LDA ($3E),Y @ $B001
0F:DDDD:B0 04 BCS $DDE3
0F:DDE3:29 0F AND #$0F
0F:DDE5:85 3E STA $003E ; SECOND NIBBLE
6. Add Breakpoint with Address: 3E and Read and Write but disable it
7. Wait until second breakpoint and enable the 3E breakpoint then hit run
x3DE0E 0F:DDFE:65 3E ADC $003E Adding our value to something
x3DDC8 0F:DDB8:85 3E STA $003E Removes our number and quick inspection of debugger shows its creating a pointer
8. In the Debugger seek to DDFE and copy the code until the exit.
0F:DDE7:A5 45 LDA $0045
0F:DDE9:4A LSR
0F:DDEA:4A LSR
0F:DDEB:A8 TAY
0F:DDEC:28 PLP
0F:DDED:B0 06 BCS $DDF5
0F:DDEF:B9 03 65 LDA $6503,Y
0F:DDF2:4C F8 DD JMP $DDF8
0F:DDF5:B9 08 66 LDA $6608,Y
0F:DDF8:A6 45 LDX $0045
0F:DDFA:20 40 DE JSR $DE40
0F:DDFD:18 CLC
0F:DDFE:65 3E ADC $003E
0F:DE00:38 SEC
0F:DE01:E9 01 SBC #$01
0F:DE03:B0 02 BCS $DE07
0F:DE05:A9 00 LDA #$00
0F:DE07:C9 10 CMP #$10
0F:DE09:90 02 BCC $DE0D
0F:DE0B:A9 0F LDA #$0F
0F:DE0D:A8 TAY
0F:DE0E:A6 44 LDX $0044
0F:DE10:20 E3 D8 JSR $D8E3
0F:DE13:98 TYA
0F:DE14:60 RTS ------------------------------- ; EXIT
9. Add a Breakpoint at Address: DE14 and Execute but disable
10. Do 6 and 7 again but also enable the DE14 breakpoint.
11. At the DE14 breakpoint, use the debugger Step Into storing the code until values are gone then label the obvious
0F:DDE7:A5 45 LDA $0045
0F:DDE9:4A LSR
0F:DDEA:4A LSR
0F:DDEB:A8 TAY
0F:DDEC:28 PLP
0F:DDED:B0 06 BCS $DDF5
0F:DDEF:B9 03 65 LDA $6503,Y @ $6503
0F:DDF2:4C F8 DD JMP $DDF8
0F:DDF5:B9 08 66 LDA $6608,Y @ $6608
0F:DDF8:A6 45 LDX $0045
0F:DDFA:20 40 DE JSR $DE40 ; GET CONDITIONAL BOOSTS
0F:DDFD:18 CLC
0F:DDFE:65 3E ADC $003E ; ADD HP
0F:DE00:38 SEC
0F:DE01:E9 01 SBC #$01 ; SUBTRACT 1
0F:DE03:B0 02 BCS $DE07 ; NEGATIVE VALUE?
0F:DE05:A9 00 LDA #$00 ; SET TO 0 IF NEGATIVE
0F:DE07:C9 10 CMP #$10
0F:DE09:90 02 BCC $DE0D ; ABOVE MAX?
0F:DE0B:A9 0F LDA #$0F ; SET TO MAX IF TOO LARGE
0F:DE0D:A8 TAY ; FINAL HP TO Y
0F:DE0E:A6 44 LDX $0044
0F:DE10:20 E3 D8 JSR $D8E3
0F:DE13:98 TYA ; FINAL HP TO A
0F:DE14:60 RTS -------------------------------
0D:86B4:AA TAX ; FINAL HP TO X (NOTE FINAL HP IS IN A, X, Y)
0D:86B5:60 RTS -------------------------------
0D:8675:AA TAX ; SET HP AS INDEX FOR TABLE
0D:8676:BD EF DF LDA $DFEF,X @ $DFF0 ; GET HP VALUE FROM TABLE
0D:8679:A0 1C LDY #$1C ; HP VALUE INDEX
0D:867B:91 40 STA ($40),Y @ $03BB ; STORE HP VALUE
... CONTINUE ELIMINATES FINAL HP IN REGISTERS A,X,Y
Step 2. Add a breakpoint for the new HP location we found
1. Delete the 9001, B001, 3E, DE14 breakpoints
2. Add a breakpoint for Address: 03BB and Read and Write
4. Enable the breakpoints at 8256 and 8275 (We know the HP has to be checked first)
5. Pause the emulator and reset the Code/Data Logger hit Run
6. Reload our save state just before the grapple and record the breakpoints for $03BB
At Contact: x284D9 0A:84C9:B1 AE LDA ($AE),Y @ $03BB Read HP for Popcorn Check
7. Pause the Code/Data Logger
8. Reload before the grapple until breakpoint and copy Code from Debugger (with help from Code/Data Logger spotting the entry point) and label the obvious
0A:84C7:A0 1C LDY #$1C ; HP VALUE INDEX
0A:84C9:B1 AE LDA ($AE),Y @ $03BB ; MAN HP VALUE ($AE is MAN POINTER)
0A:84CB:38 SEC
0A:84CC:F1 3E SBC ($3E),Y @ $061B ; SUBTRACT COM HP VALUE ($3E is COM POINTER; $61B ADDRESS - #$1C INDEX = $05FF POINTER)
0A:84CE:90 04 BCC $84D4 ; MAN LESS THAN COM HP VALUE?
; MAN MORE THAN COM HP VALUE
0A:84D0:C9 20 CMP #$20
0A:84D2:B0 18 BCS $84EC ; MAN MORE THAN COM HP VALUE BY x20+ (THIS HEADS STRAIGHT TO WIN GRAPPLE)
; MAN LESS THAN COM HP VALUE
0A:84D4:20 36 B1 JSR $B136
0A:84D7:A9 01 LDA #$01
0A:84D9:20 CB DA JSR $DACB
; We know the following code here is the Man vs Com press check from above
0A:84DC:20 4C B1 JSR $B14C
0A:84DF:A9 40 LDA #$40
0A:84E1:20 CB DA JSR $DACB
0A:84E4:A0 1D LDY #$1D ; PRESS COUNTER INDEX
0A:84E6:B1 AE LDA ($AE),Y @ $03BC ; LOAD PRESS COUNTER
0A:84E8:C9 02 CMP #$02
0A:84EA:90 0D BCC $84F9 ; LESS THAN 2 PRESSES?
; GREATER THAN OR EQUAL TO 2 PRESSES
0A:84EC:20 90 B1 JSR $B190
0A:84EF:A0 81 LDY #$81
0A:84F1:A2 85 LDX #$85
0A:84F3:20 C9 B1 JSR $B1C9
0A:84F6:4C 23 87 JMP $8723 ; EXIT
; LESS THAN 2 PRESSES
0A:84F9:20 90 B1 JSR $B190
0A:84FC:A0 22 LDY #$22
0A:84FE:A2 87 LDX #$87
0A:8500:20 C9 B1 JSR $B1C9
0A:8503:A9 01 LDA #$01
0A:8505:20 CB DA JSR $DACB
0A:8508:4C 51 85 JMP $8551 ; EXIT
Step 3. Find the Com Pointer creation
1. Add a breakpoint of Address: 3E to 3F and Write with Condition: A == #FF (From the Pointer calculation of $05FF above). We'll change A to X then Y if the most common A isn't correct.
2. Reset the Trace Logger and hit Start in the window
3. Reload before the grapple until we reach our beginning breakpoint of 84C7 then label the obvious
$832E:20 90 B1 JSR $B190 A:2D X:07 Y:03 S:39 P:nvUBdizC ; GET COM POINTER
$B190:A0 1E LDY #$1E A:2D X:07 Y:03 S:37 P:nvUBdizC ; INDEX
$B192:B1 AE LDA ($AE),Y @ $03BD = #$FF A:2D X:07 Y:1E S:37 P:nvUBdizC ; FROM MAN PLAYER
Breakpoint 5 Hit at $B194: $003E-003F:EC-W-- Condition:A == #FF
$B194:85 3E STA $003E = #$4A A:FF X:07 Y:1E S:37 P:NvUBdizC ; COM POINTER LO
$B196:C8 INY A:FF X:07 Y:1E S:37 P:NvUBdizC ; NEXT INDEX
$B197:B1 AE LDA ($AE),Y @ $03BE = #$05 A:FF X:07 Y:1F S:37 P:nvUBdizC ; FROM MAN PLAYER
$B199:85 3F STA $003F = #$B2 A:05 X:07 Y:1F S:37 P:nvUBdizC ; COM POINTER HI
$B19B:60 RTS (from $B190) ----------------- A:05 X:07 Y:1F S:37 P:nvUBdizC ; EXIT
$8331:A0 01 LDY #$01 A:05 X:07 Y:1F S:39 P:nvUBdizC
$8333:B1 AE LDA ($AE),Y @ $03A0 = #$60 A:05 X:07 Y:01 S:39 P:nvUBdizC
$8335:29 40 AND #$40 A:60 X:07 Y:01 S:39 P:nvUBdizC
$8337:F0 0C BEQ $8345 A:40 X:07 Y:01 S:39 P:nvUBdizC
$8339:B1 3E LDA ($3E),Y @ $0600 = #$80 A:40 X:07 Y:01 S:39 P:nvUBdizC
$833B:29 40 AND #$40 A:80 X:07 Y:01 S:39 P:NvUBdizC
$833D:F0 03 BEQ $8342 A:00 X:07 Y:01 S:39 P:nvUBdiZC
$8342:4C C7 84 JMP $84C7 A:00 X:07 Y:01 S:39 P:nvUBdiZC ; JUMP TO GRAPPLE ROUTINE
Breakpoint 4 Hit at $84C7: $84C7:EC--X-
Now he have the Pointer for the Man and Com players with their HP values
--------------------
GOAL: Write the Improvement Code with the knowledge we acquired
KNOW: $3B-$3D are Random Values
START: Write it in notepad
Step 1. Write the code out
0A:84C7:A0 1C LDY #$1C ; HP VALUE INDEX
0A:84C9:B1 AE LDA ($AE),Y @ $03BB ; MAN HP VALUE ($AE is MAN POINTER)
0A:84CB:38 SEC
0A:84CC:F1 3E SBC ($3E),Y @ $061B ; SUBTRACT COM HP VALUE ($3E is COM POINTER; $61B ADDRESS - #$1C INDEX = $05FF POINTER)
0A:84CE:90 04 BCC $84D4 ; MAN LESS THAN COM HP VALUE?
; MAN MORE THAN COM HP VALUE
0A:84D0:C9 20 CMP #$20
0A:84D2:B0 18 BCS $84EC ; MAN MORE THAN COM HP VALUE BY x20+ (THIS HEADS STRAIGHT TO WIN GRAPPLE)
; MAN LESS THAN COM HP VALUE
0A:84D4:20 36 B1 JSR $B136
0A:84D7:A9 01 LDA #$01
0A:84D9:20 CB DA JSR $DACB
0A:84DC:20 4C B1 JSR $B14C
0A:84DF:A9 40 LDA #$40
0A:84E1:20 CB DA JSR $DACB
A0 1C LDY #$1C ; HP INDEX
B1 AE LDA ($AE),Y ; LOAD MAN HP
4A LSR
4A LSR
4A LSR
C8 INY ; PRESS INDEX
18 CLC
71 AE ADC ($AE),Y ; HP/8 + PRESS
91 AE STA ($AE),Y ; STORE IN MAN PRESS COUNTER
20 90 B1 JSR $B190 ; LOAD COM POINTER
A0 1C LDY #$1C ; HP INDEX
B1 3E LDA ($3E),Y ; LOAD COM HP
4A LSR
4A LSR
4A LSR
C8 INY
91 3E STA ($3E),Y ; STORE HP/8 IN COM PRESS COUNTER
A5 3D LDA $003D ; RANDOM NUMBER
29 0F AND #$0F ; MAKE RANDOM x0-F
18 CLC
71 3E ADC ($3E),Y ; HP/8 + RANDOM
91 3E STA ($3E),Y ; STORE IN COM PRESS COUNTER
B1 AE LDA ($AE),Y ; LOAD MAN PRESS COUNTER
D1 3E CMP ($3E),Y ; COMPARE WITH COM PRESS COUNTER
0A:84EA:90 0D BCC $84F9 ; LESS THAN COM?
; GREATER THAN OR EQUAL TO COM PRESSES
0A:84EC:20 90 B1 JSR $B190
0A:84EF:A0 81 LDY #$81
0A:84F1:A2 85 LDX #$85
0A:84F3:20 C9 B1 JSR $B1C9
0A:84F6:4C 23 87 JMP $8723 ; EXIT
; LESS THAN COM PRESSES
0A:84F9:20 90 B1 JSR $B190
0A:84FC:A0 22 LDY #$22
0A:84FE:A2 87 LDX #$87
0A:8500:20 C9 B1 JSR $B1C9
0A:8503:A9 01 LDA #$01
0A:8505:20 CB DA JSR $DACB
0A:8508:4C 51 85 JMP $8551 ; EXIT
Step 2. Insert the Code
1. Open the Hex Editor
2. Using the debugger, Add a breakpoint with Address: 84E4 and Execute and Disable the other breakpoints
3. Reload and run until breakpoint
4. In the debugger, Seek To 9FFF and scroll up searching for empty space (not enough there)
5. In the debugger, Seek To BFFF and scroll up searching for empty space (we have room where these FFs are)
*Its usually a good idea to leave the first FF unless you know its not used but in this case I'm starting at the start of a fresh line
6. Type in our code so it fits.
At x284F4:
20 40 BF JSR $BF40 ; NEW MAN VS CPU GRAPPLING CODE
At x2BF50:
MAN VS CPU GRAPPLING:
A0 1C LDY #$1C ; HP INDEX
B1 AE LDA ($AE),Y ; LOAD MAN HP
4A LSR
4A LSR
4A LSR
C8 INY ; PRESS INDEX
18 CLC
71 AE ADC ($AE),Y ; HP/8 + PRESS
91 AE STA ($AE),Y ; STORE IN MAN PRESS COUNTER
20 90 B1 JSR $B190 ; LOAD COM POINTER
A0 1C LDY #$1C ; HP INDEX
B1 3E LDA ($3E),Y ; LOAD COM HP
4A LSR
4A LSR
4A LSR
C8 INY
91 3E STA ($3E),Y ; STORE HP/8 IN COM PRESS COUNTER
A5 3D LDA $003D ; RANDOM NUMBER
29 0F AND #$0F ; MAKE RANDOM x0-F
18 CLC
71 3E ADC ($3E),Y ; HP/8 + RANDOM
91 3E STA ($3E),Y ; STORE IN COM PRESS COUNTER
; RETURN TO NORMAL
B1 AE LDA ($AE),Y ; LOAD MAN PRESS COUNTER AS BEFORE
60 RTS
At x284E5
; RETURN HERE
EA NOP
D1 3E CMP ($3E),Y ; REPLACE CMP #$02 with COM PRESS COUNTER
Step 3. Test the game to make sure everything works and the inserted code never gets swapped out when its needed
--------------------
Repeat with a Man vs Man grapple to determine if the same code or new code but I'll leave that to you to work on your skills =)
-
jstout got a reaction from bruddog in QB and Punt Returner Ball Control
I've learned more about the code since then. The original code is below:
x2869E: LDY #$08 ; PLAYER ID INDEX LDA ($AE),Y ; PLAYER ID TAX LDA $70 AND #$1C CMP #$10 BCS @TACKLED CMP #$08 BCS @KR_PR ; KR/PR TXA EOR $70 BMI @QB_OL_PR TXA AND #$0F ; PLAYER # BEQ @QB_OL_PR ; QB CMP #$06 BCS @QB_OL_PR ; OL TXA JSR L_DD8D JMP @SKILL ; SKILL PLAYER@KR_PR: CMP #$0A BCS @QB_OL_PR ; PR EXIT ORA #$10 ; GET KR ID STA $45 TXA AND #$80 ORA $45 JSR L_DD98@SKILL: LDY #$86 ; GET PLAYER BALL CONTROL JSR L_DDAA TAY LDA $3D ; RANDOM CMP BALL_CONTROL_VALUES,Y ; BALL CONTROL SKILL BCS @TACKLED ; TACKLED? JMP @FUMBLED ; FUMBLED@QB_OL_PR: LDA $3D ; RANDOM CMP #$0C ; 44 SKILL BCS @TACKLED ; TACKLED?@FUMBLED: ; FUMBLE ROUTINE LDY #$01 LDA ($AE),Y AND #$DF STA ($AE),Y JSR L_21_BA47 JMP L_21_85A6@TACKLED: ; TACKLED ROUTINE LDA $71 ORA #$80 STA $71 JMP L_21_85A6BALL_CONTROL_VALUES:.BYTE $12,$11,$10,$0F,$0E,$0D,$0C,$0B,$0A,$09,$08,$07,$06,$05,$04,$03The hack posted here uses the first lines LDY #$08 as the PRs skill index (which was 56 skill) for the CMP BALL_CONTROL_VALUES,Y line. The QB kept the branch listed about for the skill value.
Its quite possible to hack this using tables for a team's QB and PR ball control value. Or even to have the PR use their own ball control skill.
-
jstout got a reaction from quince3800 in QB and Punt Returner Ball Control
I've learned more about the code since then. The original code is below:
x2869E: LDY #$08 ; PLAYER ID INDEX LDA ($AE),Y ; PLAYER ID TAX LDA $70 AND #$1C CMP #$10 BCS @TACKLED CMP #$08 BCS @KR_PR ; KR/PR TXA EOR $70 BMI @QB_OL_PR TXA AND #$0F ; PLAYER # BEQ @QB_OL_PR ; QB CMP #$06 BCS @QB_OL_PR ; OL TXA JSR L_DD8D JMP @SKILL ; SKILL PLAYER@KR_PR: CMP #$0A BCS @QB_OL_PR ; PR EXIT ORA #$10 ; GET KR ID STA $45 TXA AND #$80 ORA $45 JSR L_DD98@SKILL: LDY #$86 ; GET PLAYER BALL CONTROL JSR L_DDAA TAY LDA $3D ; RANDOM CMP BALL_CONTROL_VALUES,Y ; BALL CONTROL SKILL BCS @TACKLED ; TACKLED? JMP @FUMBLED ; FUMBLED@QB_OL_PR: LDA $3D ; RANDOM CMP #$0C ; 44 SKILL BCS @TACKLED ; TACKLED?@FUMBLED: ; FUMBLE ROUTINE LDY #$01 LDA ($AE),Y AND #$DF STA ($AE),Y JSR L_21_BA47 JMP L_21_85A6@TACKLED: ; TACKLED ROUTINE LDA $71 ORA #$80 STA $71 JMP L_21_85A6BALL_CONTROL_VALUES:.BYTE $12,$11,$10,$0F,$0E,$0D,$0C,$0B,$0A,$09,$08,$07,$06,$05,$04,$03The hack posted here uses the first lines LDY #$08 as the PRs skill index (which was 56 skill) for the CMP BALL_CONTROL_VALUES,Y line. The QB kept the branch listed about for the skill value.
Its quite possible to hack this using tables for a team's QB and PR ball control value. Or even to have the PR use their own ball control skill.
-
jstout got a reaction from quince3800 in Possible to "swap" PC and PA?? (NES TSB)
Change x29FEC from x87 to x88 and change the x88 to x87 in the PC/PA hack to reverse the values. Or you can flip the ratings for all the QBs.
-
jstout got a reaction from GameplayLoop in Possible to "swap" PC and PA?? (NES TSB)
Change x29FEC from x87 to x88 and change the x88 to x87 in the PC/PA hack to reverse the values. Or you can flip the ratings for all the QBs.
-
jstout got a reaction from buck in Possible to "swap" PC and PA?? (NES TSB)
Change x29FEC from x87 to x88 and change the x88 to x87 in the PC/PA hack to reverse the values. Or you can flip the ratings for all the QBs.
-
jstout got a reaction from Knobbe in A great intro to 6502 Assembly
I thought about all the common topics/issues with the NES and created the list below with the | being related and/or advanced topics. The 6502 section is general assembly knowledge allowing people to read and write code. The NES Programming section is a how and why things are done (could create a game, low-level hacking is limited but might explain how things are stored, high-level hacking will understand reasoning and allow practical applications outside of code snippets) and likely contain code examples. The FCEUX Hacking section would describe how to use the various features in the emulator and likely contain simple examples (the problem here is sometimes things just aren't simple to find or change).
Did I miss anything people want to know about? Is this overkill of what people want to know about? And more importantly are there more than 2-3 people even interested in this?
6502:
NUMBER FORMATS
REGISTERS
ADDRESSING MODES
PROCESSOR STATUS FLAGS
OPCODES
BASIC MATH | 16-BIT OPERATIONS, FIXED POINT
NES PROGRAMMING:
MEMORY MAPS
PPU REGISTERS
SKELETON ROM
GAME LOOP | GAME STATES, MULTITASK
PALETTE | FADE
SPRITES | METASPRITES, ANIMATION, COLLISION DETECTION
CONTROLLER
BACKGROUND | METATILES, COMPRESSION
SCROLL | CAMERA
SPRITE 0 HIT
MMC3 MEMORY MAPPER
SOUND | DMC, SOUND ENGINE
FCEUX HACKING:
HEX EDITOR | CORRUPTION, FONT TABLES, CODE INSERTION
PPU VIEWER
NAME TABLE VIEWER
CODE/DATA LOGGER | FILE COMPARE
CHEAT SEARCH
DEBUGGER | CONDITIONS
TRACE LOGGER
SAVE STATES
-
jstout got a reaction from GameplayLoop in sorting Receiving stats by yards instead of catches
Try changing x304F1 from 08 to 09
-
jstout got a reaction from buck in sorting Receiving stats by yards instead of catches
Try changing x304F1 from 08 to 09
-
jstout got a reaction from buck in Text Editing Alphabet
xXX = %76543210 (Listing Bit Numbers)
x55 = %01010101
(%00 = Palette 0, %01 = Palette 1, %10 = Palette 2, %11 = Palette 3)
An attribute byte = 4x4 Tiles (32 pixels x 32 pixels) with each Palette Block = 2x2 Tiles (16 pixels x 16 pixels)
[ ][ ][ ][ ]
[ ][ ][ ][ ]
[ ][ ][ ][ ]
[ ][ ][ ][ ]
The Top Left 2x2 uses bits 10
The Top Right 2x2 uses bits 32
The Bottom Left 2x2 uses bits 54
The Bottom Right 2x2 uses bits 76
So x55 has all 4 Palette Blocks %01 = Palette 1
-
jstout got a reaction from DFM in TSBm 1.3: Making your own FACES
I wouldn't say that is entirely right. The high 2 bits control mirroring and the low 6 bits control the row as %VHRRRRRR (V = Vertical Mirror, H = Horizontal Mirror, R = Row).
So:
x00-x3F = Set Tile Normally (Row 00 to 3F)
x40-x7F = Set Tile with Horizontal Mirror (Row 00-3F)
x80-xBF = Set Tile with Vertical Mirror (Row 00-3F)
xC0-xFF = Set Tile with Horizontal and Vertical Mirror (Row 00-3F)
-
jstout got a reaction from Knobbe in TSBm 1.3: Making your own FACES
I wouldn't say that is entirely right. The high 2 bits control mirroring and the low 6 bits control the row as %VHRRRRRR (V = Vertical Mirror, H = Horizontal Mirror, R = Row).
So:
x00-x3F = Set Tile Normally (Row 00 to 3F)
x40-x7F = Set Tile with Horizontal Mirror (Row 00-3F)
x80-xBF = Set Tile with Vertical Mirror (Row 00-3F)
xC0-xFF = Set Tile with Horizontal and Vertical Mirror (Row 00-3F)
-
jstout got a reaction from keithisgood in TSBm 1.3: Making your own FACES
Here is an example of how the faces are done:
Frank Reich:
x1C054 $A064 (POINTER) = B9A3
x1C3C9 $A3B9 (DESIGN) = CC10 CF60 CDCC CEBD CF97 B074
x1CC20 $AC10 (HAIR) = 700088 704090 710888 710890 7A0080 7A4098 FE
x1CDDC $ADCC (EARS) = 7A0080 7A4098 380800 384818 3A1000 3A5018 FE
x1CECD $AEBD (MOUTH) = 221408 225410 FE
x1CF70 $AF60 (EYES) = 1B0988 1B4990 FE
x1CFA7 $AF97 (LOWER HEAD) = 021008 025010 071808 075810 FE
x1D084 $B074 (UPPER HEAD) = 210008 214010 000808 004810 FF
Format: TILE ROW COLUMN
*ROW = +00 = NORMAL, +40 = HORIZONTAL MIRROR, +80 = VERTICAL MIRROR, +C0 = HORIZONTAL AND VERTICAL MIRROR
*COLUMN = +00 = PALETTE 0, +40 = PALETTE 01, +80 = PALETTE 02, +C0 = PALETTE 03
FE = NEXT
FF = END
-
jstout got a reaction from DFM in TSBm 1.3: Making your own FACES
Here is an example of how the faces are done:
Frank Reich:
x1C054 $A064 (POINTER) = B9A3
x1C3C9 $A3B9 (DESIGN) = CC10 CF60 CDCC CEBD CF97 B074
x1CC20 $AC10 (HAIR) = 700088 704090 710888 710890 7A0080 7A4098 FE
x1CDDC $ADCC (EARS) = 7A0080 7A4098 380800 384818 3A1000 3A5018 FE
x1CECD $AEBD (MOUTH) = 221408 225410 FE
x1CF70 $AF60 (EYES) = 1B0988 1B4990 FE
x1CFA7 $AF97 (LOWER HEAD) = 021008 025010 071808 075810 FE
x1D084 $B074 (UPPER HEAD) = 210008 214010 000808 004810 FF
Format: TILE ROW COLUMN
*ROW = +00 = NORMAL, +40 = HORIZONTAL MIRROR, +80 = VERTICAL MIRROR, +C0 = HORIZONTAL AND VERTICAL MIRROR
*COLUMN = +00 = PALETTE 0, +40 = PALETTE 01, +80 = PALETTE 02, +C0 = PALETTE 03
FE = NEXT
FF = END
-
jstout got a reaction from buck in TSBm 1.3: Making your own FACES
Here is an example of how the faces are done:
Frank Reich:
x1C054 $A064 (POINTER) = B9A3
x1C3C9 $A3B9 (DESIGN) = CC10 CF60 CDCC CEBD CF97 B074
x1CC20 $AC10 (HAIR) = 700088 704090 710888 710890 7A0080 7A4098 FE
x1CDDC $ADCC (EARS) = 7A0080 7A4098 380800 384818 3A1000 3A5018 FE
x1CECD $AEBD (MOUTH) = 221408 225410 FE
x1CF70 $AF60 (EYES) = 1B0988 1B4990 FE
x1CFA7 $AF97 (LOWER HEAD) = 021008 025010 071808 075810 FE
x1D084 $B074 (UPPER HEAD) = 210008 214010 000808 004810 FF
Format: TILE ROW COLUMN
*ROW = +00 = NORMAL, +40 = HORIZONTAL MIRROR, +80 = VERTICAL MIRROR, +C0 = HORIZONTAL AND VERTICAL MIRROR
*COLUMN = +00 = PALETTE 0, +40 = PALETTE 01, +80 = PALETTE 02, +C0 = PALETTE 03
FE = NEXT
FF = END
-
jstout got a reaction from DFM in Trying to explain the concept of RS RP and MS to malferds...
Here is the straight up data and how it works.
Here is the default skill chart:
Skill RS RP MS*
6 0E 0D 15/25
13 0F 0C 16/26
19 10 0B 17/27
25 11 0A 18/28
31 12 09 19/29
38 13 08 1A/2A
44 14 07 1B/2B
50 15 06 1C/2C
56 16 05 1D/2D
63 17 04 1E/2E
69 18 03 1F/2F
75 19 03 20/30
81 1A 02 21/31
88 1B 02 22/32
94 1C 01 23/33
100 1D 01 24/34
*Offense/Defense
When a player is standing still he has zero speed. Once he moves his speed is equal to RS and his RP starts. Every player cycle, RP is decreased by 1 and when his RP is equal to 0 then his RS is increased by 1 and RP restarts. With each RS increase the player will speed up. Once RS is equal or greater to MS then the player stops accelerating.
RS Chart is x2BE84 to x2BE93
RP Chart is x2BE74 to x2BE83
MS Chart is x3DFDF to x3DFEE (Offense)
MS Chart is x3DFEF to x3DFFE (Defense)
-
jstout got a reaction from tiredtonsofclay in Editing Large Helmets
I didn't see any documentation on editing the large helmets in Tecmo Super Bowl for the NES so here is some basic info. Some knowledge of hexidecimal is helpful here.
I'll start with the locations of where the logos are told to be placed.
Team Offset Pointer
Buffalo x1008C C0A6
Indianapolis x1008A B2A6
Miami x1008E CEA6
New England x10090 DCA6
NY Jets x10072 F3A5
Cincinnati x10074 01A6
Cleveland x10076 0FA6
Houston x10078 1DA6
Pittsburgh x1007A 2BA6
Denver x1007C 39A6
Kansas City x1007E 47A6
LA Raiders x10092 EAA6
San Diego x10094 F8A6
Seattle x10084 88A6
Washington x1009A 22A7
NY Giants x10088 A4A6
Philadelphia x10096 06A7
Phoenix x10098 14A7
Dallas x10086 96A6
Chicago x1009C 30A7
Detroit x1009E 3EA7
Green Bay x100A0 4CA7
Minnesota x100A2 5AA7
Tampa Bay x100A4 68A7
San Francisco x100AC A0A7
LA Rams x100A8 84A7
New Orleans x100AA 92A7
Atlanta x100A6 76A7
Example: Lets swap Buffalo and Indianapolis. At x1008A, put C0 A6 B2 A6. The Buffalo and Indianapolis logos should have been switched. Go ahead and put it back now.
Thats not really what we are looking for so lets move on to what is being pointed to.
I'll use Cleveland and Houston for later examples so lets calculate their offset. Cleveland 0FA6, ("0F" + 10) ("A6" + 60) = 1F 06, then swap and add a x1 for x1061F. Same for Houston and you get x1062D.
Cleveland points to the line:
F6 70 FF FF FF FC 08 F8 36 42 92 22 AB 17
Houston points to the line:
F6 70 FF FF FF FC 09 F8 37 3A 92 2B AB 17
From here what we are interested in is Cleveland's "36 42 92 22" and Houston's "37 3A 92 2B". The first hex moves the teams logo up and down. The second hex moves the teams logo left and right. The final two hexes direct us to the design of the logo.
Example: Lets move Houston's logo. Change "37 3A 92 2B" to 30 30 92 2B. Houston's logo should be almost off the helmet now. Go ahead and put it back now.
Thats a little useful but we want the actual design so lets find that location. For Cleveland 92 22, ("92" + 90) ("22" + 10) = 1232, add a x1 to that a we have x11232. Same for Houston and we get x1123B.
Houston's logo has more data so lets check that out. The line directed from above will be:
9F 39 1E 3D 34 01 36 05 3C 80 39 1F 3D 35 01 37 05 3D 81 05 39 FF
Now the helmets are drawn on a grid, main columns are 9E 9F 80 81 82 but a few logos have been moved so far right like Cleveland that 9B 9C 9D could be used. The main rows are 39 3D 01 05 09 0D 11 or by using 79 7D 41 45 49 4D 51 the tiles will be mirrored. Now we know the grid numbers lets read Houston's logo.
Column 9F Row 39 Place Tile 1E, Row 3D Place Tile 34, Row 01 Place Tile 36, Row 05 Place Tile 3C, Column 80 Row 39 Place Tile 1F, Row 3D Place Tile 35, Row 01 Place Tile 37, Row 05 Place Tile 3D, Column 81 Row 05 Place Tile 39 and Stop using FF
Looking at a more advanced design like:
9E 3D 00 01 02 05 08 9F 3D 01 01 03 05 09 80 3D 04 01 06 05 0C FC 36 81 3D 0A FF
Everything is going smooth until you reach the FC. FC tells it the following locations (Column 81 Row 3D Tile 0A) will be shifted to place 36. I haven't tested the shifts thoroughly yet.
Example: Lets change Houston's logo. Replace their line with:
9E 3D 1E 01 34 05 36 9F 3D 1F 01 35 05 37 80 3D 39 01 3C 05 3D FF. The logo should have the base legs to the right of the upper section. Go ahead and put it back after you looked.
Ok, that was great but many of you now want to know if you can use tiles from other teams especially if they go unused.
Example: Lets take a tile away from Cleveland and give the rom space to Houston and at the same time use a tile from Indianapolis. At x11232, change the line to:
9F 3D 3B 80 3D 3E FF 9F 09 1E 39 09
Those paying real attention would have noticed that the location of Houston's starting point changed. We need to go back above to x1062D and edit our direction spot to "92 29". Go ahead and put it back when done.
Now to edit the colors. Starting at x23D79 is 30 16 12 10 30 30 12 26 which is the colors of Buffalo. The first three colors are the helmet palette, the next two are the facemask palette, and the final three are the logo palette. Teams will be in order from Buffalo to Atlanta.
Well thats the basics on editing the large helmets. The big trick seems to be planning the rom space and selecting the proper tiles to get placed.
Unfortunately, since I've been busy I've yet to find how some teams like Cincinnati and the LA Rams get the background objects on their helmets (Cincinnati's stripes for example) or how the tiles get numbered for the helmets. But I'm sure this is enough info for now.