;Wormy v1.0 ; (C) 2009 by Brandon Wilson. All rights reserved. ; ;Known Issues: ; Erasing the certificate sector will crash this: ; Because the boot page is now on 0x3F (part of a 64KB sector), an attempt to erase sector 0x7E will erase the boot code. ; The boot page image could be patched to restore the boot page when that happens, but ick. ; To use, you must (for now): ; Erase ALL memory via Mem menu ; Transfer Wormy.8xk and 16KB BOOT1/BOOT2 boot page image AppVars ; Run Wormy ;Portions in util.asm, equates.inc (C) Dan Englender. include "settings.inc" ;Specific settings for this application NOLIST include "ti83plus.inc" LIST include "equates.inc" ;Equates and macros to be used include "header.asm" GLOBALS ON SEGMENT MAIN EXTERN UnlockFlash,DispHexA,IGetKey,DispHexHL,IPutS,BPutS,IPutC ;----------------------------------------------------------------------------- Init: set appAutoScroll,(iy+appFlags) B_CALL ClrLCDFull B_CALL HomeUp in a,(21h) and 3 jr nz,$F ld hl,sNotSE jr DisplayErrorExitApp $$: in a,(2) bit 5,a jr nz,$F ld hl,sNot84P jr DisplayErrorExitApp $$: ld hl,sBoot1 rst 20h B_CALL ChkFindSym jr nc,$F ld hl,sBoot1NotFound jr DisplayErrorExitApp $$: ld hl,sBoot2 rst 20h B_CALL ChkFindSym jr nc,$F ld hl,sBoot2NotFound jr DisplayErrorExitApp $$: ld hl,sAreYouSure call IPutS call IGetKey cp kEnter jr nz,ExitApp ;Unlock Flash (it will stay unlocked from here on out) ld hl,sConverting call IPutS call UnlockFlash ld hl,sUnlocked call IPutS ;Copy this entire page to RAM page 83h di ld a,83h out (7),a ld hl,4000h ld de,8000h push hl pop bc ldir ld a,81h out (7),a ;Run from RAM page 83h ld a,83h out (6),a ld hl,sRunningFromRAM call IPutS ; B_CALL FindSwapSector ; push af ; B_CALL EraseFlashPage ;Erase our scratch space for the boot page images ld hl,sPreparingBootImageSpace call IPutS ld a,28h B_CALL EraseFlashPage ld a,2Ch B_CALL EraseFlashPage ld hl,sGettingBoot1 call IPutS ; pop af ; push af ld hl,sBoot1 ld a,2Ah call GetBootDataToPage ld hl,sGettingBoot2 call IPutS ; pop af ; push af ; inc a ld hl,sBoot2 ld a,2Bh call GetBootDataToPage ;TODO: Figure out why this doesn't work... ;Erase our scratch space for the boot page images ; ld hl,sPreparingBootImageSpace ; call IPutS ; ld a,28h ; B_CALL EraseFlashPage ; ld a,2Ch ; B_CALL EraseFlashPage ;Copy boot images to our scratch space ; pop af ; push af ; ld b,2Ah ; B_CALL CopyFlashPage ; pop af ; push af ; inc a ; ld b,2Bh ; B_CALL CopyFlashPage ; pop af ; ;Erase swap sector ; push af ; B_CALL EraseFlashPage ; pop af ;Mark sector as swap again ; ld de,4000h ; ld b,0FEh ; B_CALL WriteAByte ;Do any boot page specific patches ld hl,sPatchingImages call IPutS ;HACK: Remove last period from "Waiting..." so we know we're running the new boot code ld a,2Ah ld de,4829h ld b,0 B_CALL WriteAByte ;HACK: Patch out call to _MarkOSInvalid in the OS-receiving code (this is very bad for us right now...) ld hl,appData ld bc,3 B_CALL MemClear ld a,2Ah ld hl,appData ld de,5AA4h ld bc,3 B_CALL WriteFlash ;HACK: Patch out erasing of OS sectors (we'll manually erase them ourselves, since this is very bad for us right now...) ld a,2Ah ld hl,appData ld de,639Ch ld bc,3 B_CALL WriteFlash ;Patch any "ld a,7Fh" instructions in the boot code to "ld a,3Fh" ld de,7F3Eh call TranslateBootPageValues ;Patch any "cp 7Fh" instructions in the boot code to "cp 3Fh" ld de,7FFEh call TranslateBootPageValues ;Erase everything from Flash page 8 to page 3Fh (!) ld a,8 ld b,14 ;sectors 08h, 0Ch, 10h, 14h, 18h, 1Ch, 20h, 24h, 28h, 2Ch, 30h, 34h, 38h, 3Ch eraseAllLoop: push af push bc cp 28h ;HACK: skip 28h, already did it and is now holding our boot page data jr z,$F cp 2Ch jr z,$F B_CALL EraseFlashPage $$: pop bc pop af add a,4 djnz eraseAllLoop ld hl,sLowerSectorsErased call IPutS ;Copy OS/boot pages 70h-7Dh to 30h-3Dh ld a,70h ld b,30h ld c,14 $$: push af push bc B_CALL CopyFlashPage ;NOTE: this won't do the certificate pop bc pop af inc a inc b dec c jr nz,$B ld hl,sCopiedUpperPages call IPutS ;Copy pages 7Eh and 7Fh to 3Eh and 3Fh ld a,7Eh ld b,3Eh call CopyFlashPage ld a,2Ah ld b,3Fh call CopyFlashPage ;Copy the second boot page ld a,2Bh ld b,2Fh call CopyFlashPage ld hl,sCopiedFinalPages call IPutS ;Put ourselves at page 29h (the new last Flash application page) ld hl,4000h push hl pop de $$: ld b,(hl) ld a,29h push hl push de B_CALL WriteAByte pop de inc de pop hl inc hl bit 7,d jr z,$B ld hl,sClonedTo29h call IPutS ;See if we've already patched the OS to include our routine di ld ix,ModifyModelPort ld hl,pageTable findBlockLoop: ld de,8000h ld b,(hl) ld a,b out (7),a $$: bit 6,d jr nz,findNextBlock ld a,(de) inc de cp (ix+0) jr nz,$B ld a,(de) inc de cp (ix+1) jr nz,$B ld a,(de) inc de cp (ix+2) jr nz,$B ld a,(de) inc de cp (ix+3) jr nz,$B or a jr $F findNextBlock: inc hl ld a,(hl) cp 0FFh jr nz,findBlockLoop scf $$: ld a,81h out (7),a ld a,b ex de,hl res 7,h set 6,h jr nc,storeBlockLocation ;Can't find it, so patch it ld hl,sSearchingForEmptySpace call IPutS ld hl,ModifyModelPort ld bc,ModifyModelPortEnd-ModifyModelPort ld ix,pageTable call EmbedCodeBlock jr nc,$F ld hl,sNoFreeSpace jr DisplayErrorExitApp $$: ld hl,4 add hl,de bit 7,h jr z,$F res 7,h set 6,h inc a storeBlockLocation: $$: ld (hookExecTemp+2),a ld (hookExecTemp),hl ld hl,sBlockEmbedded call IPutS ;Patch the OS to jump to page 3Fh instead of 7Fh ; (apparently TI thinks it's safe to assume SE ; even when running on 84+ hardware with regards ; to port 6...I don't like it, and it makes this ; potentially unstable if TI does this elsewhere) ld hl,sPatchingBootJump call IPutS ld hl,0000h $$: ld a,(hl) cp 0C3h inc hl jr nz,$B ld e,(hl) inc hl ld d,(hl) ex de,hl ld de,7F3Eh ld bc,100 $$: dec bc ld a,b or c jr z,$F ld a,e cp (hl) inc hl jr nz,$B ld a,d cp (hl) inc hl jr nz,$B dec hl ex de,hl xor a ld b,3Fh B_CALL WriteAByte $$: ld hl,sComplete call IPutS ld hl,sEnterToQuit call IPutS call IGetKey cp kEnter jr nz,$F rst 00h $$: ld a,83h out (6),a ;Erase all the OS sectors ;NOTE: We will be OS-less from this point forward! di ld hl,BootStart ld de,appData ld bc,BootEnd-BootStart ldir call appData ;Change the model ports (NOTE: this edit locks 0x3F!!!) ld hl,ExecuteCodeStart ld de,ramCode ld bc,ExecuteCodeEnd-ExecuteCodeStart ldir call ramCode ;Jump into the boot code ld hl,DoBoot ld de,appData ld bc,DoBootEnd-DoBoot ldir jp appData BootStart: ;Erase all the OS pages in a,(6) push af ld a,7Fh out (6),a ld hl,(4084h) ;_EraseFlashPage xor a push hl call jpHL-BootStart+appData pop hl ld a,4 push hl call jpHL-BootStart+appData pop hl ld a,30h push hl call jpHL-BootStart+appData pop hl ld a,34h push hl call jpHL-BootStart+appData pop hl ld a,38h push hl call jpHL-BootStart+appData pop hl ;Now copy the boot page back ld a,3Ch call jpHL-BootStart+appData ld de,4000h copyBootBackLoop: ld a,2Ah out (6),a ld a,(de) ld b,a ld a,7Fh out (6),a ld hl,(4021h) ;_WriteAByte push de ld a,3Fh call jpHL-BootStart+appData pop de inc de bit 7,d jr z,copyBootBackLoop ld a,7Fh out (6),a ld hl,(4084h) ;_EraseFlashPage ld a,28h call jpHL-BootStart+appData pop af out (6),a ret jpHL: jp (hl) BootEnd: DoBoot: ld a,3Fh out (6),a jp 412Ch DoBootEnd: TranslateBootPageValues: xor a out (5),a ld a,81h out (7),a di ld hl,8000h $$: ld a,2Ah ;3Fh out (7),a bit 6,h jr nz,$F ld a,e cp (hl) inc hl jr nz,$B ld a,d cp (hl) inc hl jr nz,$B dec hl ld a,81h out (7),a push hl push de ex de,hl ld a,3Fh ld b,a res 7,d set 6,d B_CALL WriteAByte pop de pop hl bit 6,h jr z,$B $$: ld a,81h out (7),a ret DisplayErrorExitApp: call IPutS call IGetKey ExitApp: B_JUMP JForceCmdNoChar sAreYouSure: DB "Are you SURE you" DB "want to proceed?" DB " " DB "Press ",LlBrack,"ENTER] to" DB "continue or any " DB "other key to " DB "quit. ",0 sEnterToQuit: DB "PRESS ENTER TO " DB " QUIT OR ANY " DB " OTHER KEY TO " DB " ERASE OS AND " DB " REBOOT!!!",0 sBoot1: DB AppVarObj,"BOOT1",0 sBoot2: DB AppVarObj,"BOOT2",0 sGettingBoot1: DB "Getting BOOT1...",0 sGettingBoot2: DB "Getting BOOT2...",0 sBoot1NotFound: DB "BOOT1 AppVar not" DB " found! ",0 sBoot2NotFound: DB "BOOT2 AppVar not" DB " found! ",0 sConverting: DB "Converting... ",0 sComplete: DB "Conversion " DB " complete! ",0 sNotSE: DB "Not SE! ",0 sNot84P: DB "Not 84+ series! ",0 sUnlocked: DB "Flash unlocked ",0 sRunningFromRAM: DB "Running from RAM",0 sLowerSectorsErased: DB "Lower sectors " DB " erased ",0 sCopiedUpperPages: DB "Copied upper " DB " pages ",0 sCopiedFinalPages: DB "Copied final " DB " pages ",0 sRunningFromFlash: DB "Running from " DB " Flash ",0 sNoFreeSpace: DB "No free space! ",0 sClonedTo29h: DB "Cloned to 0x29 ",0 sBlockEmbedded; DB "Block embedded ",0 sPatchingBootJump: DB "Patching boot " DB " jump... ",0 sSearchingForEmptySpace: DB "Searching for " DB " empty space ",0 sPreparingBootImageSpace: DB "Preparing boot " DB " image area... ",0 sPatchingImages: DB "Patching boot " DB " images... ",0 pageTable: DB 7Ch,7Dh,0FFh GetBootDataToPage: ld (asm_ram),a rst 20h B_CALL ChkFindSym ret c ex de,hl ld a,b or a jr z,$F ld de,9 call BHL_plus_DE call myLoadCIndPaged ld d,0 ld e,c call BHL_plus_DE $$: call myLoadDEIndPaged ;get past size bytes ld de,4000h bootCopyLoop: ;BHL points to data push de push bc push hl ld a,b ld de,appData ld bc,256 push bc B_CALL FlashToRam pop de pop hl pop bc call BHL_plus_DE ;BHL points to next data pop de ;DE points to destination push bc push hl ld a,(asm_ram) ld hl,appData ld bc,256 push de push bc B_CALL WriteFlash pop bc pop hl add hl,bc ex de,hl ;DE points to new data pop hl pop bc bit 7,d jr z,bootCopyLoop ret myLoadDEIndPaged: B_CALL LoadDEIndPaged jr inc_BHL myLoadCIndPaged: B_CALL LoadCIndPaged inc_BHL: inc hl $$: bit 7,h ret z inc b res 7,h set 6,h ret BHL_plus_DE: add hl,de jr $B ExecuteCodeStart: ;Call code at (hookExecTemp) ld (appData),a in a,(6) push af ld a,(hookExecTemp+2) out (6),a ld a,(appData) ld ix,execReturnPoint-ExecuteCodeStart+ramCode push ix ld ix,(hookExecTemp) jp (ix) execReturnPoint: ld (appData),a ld (appData+1),bc pop bc ld a,b out (6),a ld a,(appData) ld bc,(appData+1) ret ExecuteCodeEnd: ModifyModelPort: DB 0DEh DB 0ADh DB 0BEh DB 0EFh ; ld b,1 ; ld c,14h ; call ramCode ;unlock Flash ld a,1 nop nop im 1 di out (14h),a ; ld b,0 ; ld c,21h ; call ramCode ;write zero to port 21h (model: 84+) xor a nop nop im 1 di out (21h),a ; ld b,08h ; ld c,22h ; call ramCode ;set Flash upper bound (end of lower OS space) ld a,8 nop nop im 1 di out (22h),a ; ld b,29h-1 ; ld c,23h ; call ramCode ;set Flash lower bound (just beyond the first app page (this app)) ld a,29h-1 nop nop im 1 di out (23h),a ; ld b,10h ; ld c,25h ; call ramCode ;set port 25h to default (not sure if this is necessary) ld a,10h nop nop im 1 di out (25h),a ; ld b,20h ; ld c,26h ; call ramCode ;set port 26h to default (not sure if this is necessary) ld a,20h nop nop im 1 di out (26h),a ret ModifyModelPortEnd: CopyFlashPage: ;Copies from Flash page A to Flash page B. ld hl,8000h ld de,4000h $$: push af push bc out (7),a ld b,(hl) ld a,81h out (7),a pop af push af push hl push de B_CALL WriteAByte pop de inc de pop hl pop bc pop af inc hl bit 7,d jr z,$B ret EmbedCodeBlock: ;Embed a block of code into a free spot of the OS. ;Inputs: ; HL => code block. (4000h-7FFFh range) ; BC: size of code block. ; IX => table of OS Flash pages, 0FFh-terminated (7Ch,7Dh,0FFh to store on a privileged page, for example) ;Outputs: ; Returns carry flag set if empty block could not be found ; DE: address of where code was placed. ; A: Flash page of where code was placed. push hl push ix pop hl push bc call FindEmptyBlock ld a,l pop bc pop hl ret c push af push de ;Copy BC bytes from HL to ADE $$: push bc push hl ld b,(hl) push af B_CALL WriteAByte pop af pop hl inc hl pop bc dec bc inc b dec b jr nz,$B inc c dec c jr nz,$B pop de pop bc ld a,b ret FindEmptyBlock: ;Inputs: ; HL => table of Flash pages to check ; BC: size of empty block to find ;Outputs: ; Returns carry flag set if block could not be found ; DE => empty block address ; L: Flash page of empty block in a,(6) push af push hl push bc ld hl,emptyBlockCode ld de,ramCode ld bc,emptyBlockCodeEnd-emptyBlockCode ldir pop bc pop hl jp ramCode emptyBlockCode: ld a,(hl) call myTranslatePage-emptyBlockCode+ramCode out (6),a inc a scf jr z,blockNotFound ld de,7FFEh+1 $$: dec de ld a,(de) inc a jr z,$B inc de ex de,hl add hl,bc ex de,hl inc de bit 7,d jr nz,skipNextPage ;HACK: all this is awful, re-do it dec de or a ex de,hl sbc hl,bc ex de,hl in a,(6) ld l,a blockNotFound: pop bc ld a,b out (6),a ret skipNextPage: pop af out (6),a push af inc hl jr emptyBlockCode myTranslatePage: push bc ld b,a in a,(2) and 80h jr z,$F in a,(21h) and 3 ld a,b pop bc ret nz and 3Fh pop bc ret $$: ld a,b and 1Fh pop bc ret emptyBlockCodeEnd: ;------------------------------------------------------------------------------