This tutorial describes howto create a 'registered' version of Mail+. Use this tutorial to try the program without anoying nag-screens. If you like the program, you should buy it so that the developer can continue the developing of it.
What do you need for this tutorial?
  • The previous tutorials from Palmwarez
  • Pilotdis
  • PRCedit or any other HEX editor
  • Mail+ 1.0, download it here: http://www.ecamm.com/
  • A good brain :-)

    First step into patching is to explore all the limitations of the program. So let's see: after starting the program you'll see a nag-screen with the message: Please support shareware, register Mail+ online at: www.palmgear.com. After that you'll see an unregistered label in the main screen.

    If you try to register the program with the help, register menu option, you'll get the same nag-screen as before. So there's no way to enter a serial.

    That should be enough for now. Let's fire up PRCedit!

    The nag-screens pop-up alot so let's skip that for now. We'll focus on the UNREGISTERED label on the main screen. We'll do a search in the disassembled source and find it at position 00004664. It has the label L572. We'll see that it's loaded just above the string at line 0000463e. So what do we see here? At line 0000462a we'll see a TST.B -11(A5) and we'll see a BEQ L571 at line 00004632. So what can we get out of all this? The program checks if the global variable -11(A5) is set and if it is, it skips writing the unregistered label. So if we change the BEQ into a JMP, it won't display the unregistered label.
    If we do that, we'll also have to remove all nag-screens this way so it is better to find out where the global variable is set!

    0000462a 4a2dfff5			 TST.B	-11(A5)  ; Check global var -11(A5)
    0000462e 4fef002a			 LEA	42(A7),A7
    00004632 6718				 BEQ	L571  ; Jump to L571 if it's 1
    00004634 3f3c0002			 MOVE.W	#2,-(A7)
    00004638 2f3c000c002b			 MOVE.L	#786475!$c002b,-(A7)
    0000463e 41fa0024			 LEA	L572,A0  ; Load String UNREGISTERED 
    00004642 4850				 PEA	(A0)
    00004644 4e4fa220			 TRAP	#15  ; Draw it on the screen
    00004648					 DC.W	sysTrapWinDrawChars
    00004648 4fef000a			 LEA	10(A7),A7
    0000464c 4e5e			L571	 UNLK	A6
    0000464e 4e75				 RTS
    00004650 91				 DC.B	#145
    00004651 4d61696e566965774472		 DC.B 'MainViewDrawIcons'
    0000465b 617749636f6e73			
    00004662 000e				 DC.W #14
    00004664 554e5245474953544552	L572	 DC.B	'UNREGISTERED'
    0000466e 4544					
    00004670 0000				 DC.W	#0

    If we look in the Global Cross Reference we'll see that the variable -11(A5) is set at position 000066ec.

    -11(A5)               -11 :  000024b2(R)  00003522(R)  0000394e(R)  0000462a(R)
                                 000051de(R)  0000522a(R)  00005264(R)  000052ba(R)
                                 00005474(R)  000062e8(R)  00006350(R)  00006376(R)
                                 000066ec(W)  000066f0(R)

    Take a look at these lines:

    000066e8 4eba0bdc			 JSR	L914
    000066ec 1b40fff5			 MOVE.B	D0,-11(A5)
    000066f0 4a2dfff5			 TST.B	-11(A5)
    000066f4 670a				 BEQ	L821
    000066f6 3f3c06a4			 MOVE.W	#1700!$6a4,-(A7)
    000066fa 4e4fa192			 TRAP	#15
    000066fe 					DC.W sysTrapFrmAlert
    000066fe 544f				 ADDQ.W	#2,A7
    00006700 3f3c0003		L821	 MOVE.W	#3,-(A7)

    We'll see a subroutine L914, Move the result (D0) to -11(A5), test the global variable and if it's not set a call to our nag-screen. Let's see what's in the subroutine L914..

    000072c6 4e560000		L914	 LINK	A6,#0
    000072ca 2f04				 MOVE.L	D4,-(A7)
    000072cc 2f03				 MOVE.L	D3,-(A7)
    000072ce 7600				 MOVEQ	#0,D3
    000072d0 41fa003e			 LEA	L917,A0
    000072d4 4850				 PEA	(A0)
    000072d6 4267				 CLR.W	-(A7)
    000072d8 4e4fa045			 TRAP	#15
    000072dc 					DC.W sysTrapDmFindDatabase
    000072dc 3800				 MOVE.W	D0,D4
    000072de 5c4f				 ADDQ.W	#6,A7
    000072e0 6604				 BNE	L915
    000072e2 7001				 MOVEQ	#1,D0  ; Registered is true
    000072e4 6002				 BRA	L916
    000072e6 7000			L915	 MOVEQ	#0,D0 ; Registered is false
    000072e8 1600			L916	 MOVE.B	D0,D3
    000072ea 1003				 MOVE.B	D3,D0
    000072ec 261f				 MOVE.L	(A7)+,D3
    000072ee 281f				 MOVE.L	(A7)+,D4
    000072f0 4e5e				 UNLK	A6
    000072f2 4e75				 RTS
    000072f4 98				 DC.B #152
    000072f5 52656756616c69645265		 DC.B	'RegValidRegistrationCode'

    That's a nice name for a subroutine. We'll see here a routine that checks for a database and if it find's it, it set's D0 to 1. If not, it set's D0 to 0. On line 000066ec we'll see that D0 is moved to our global variable so we'll make sure that D0 is always set to one by replacing the MOVEQ #0,D0 (7000) to MOVEQ #1,D0 (7001). That's it.