Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

TI-83+ Timer and Battery Funkyness

By: a guest on Sep 9th, 2010  |  syntax: Z80 Assembler  |  size: 10.87 KB  |  views: 81  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. <BrandonW> I think I'm witnessing something crazy.
  2. <i_c-Y> yourself?
  3. <BrandonW> I think I understand.
  4. <i_c-Y> i bet when BrandonW does acid he sees calculators.
  5. <BrandonW> When you pull the battery from OS2 it actually keeps running for a fraction of a second and then it fades away.
  6. <BrandonW> But when you pull it from the TI-OS, it immediately shuts off.
  7. <BrandonW> I think the OS actually shuts itself down when it detects the battery has been pulled.
  8. <BrandonW> Based on the backup battery.
  9. <BrandonW> There's code in the interrupt to do it.
  10. <BrandonW> And it backs up the evidence I'm seeing on a real 84+.
  11. <BrandonW> It sets the RAM checksum to 0.
  12. <sir_lewk> neat
  13. <BrandonW> Or, well, Calcsys it's zero by the time I turn it back on.
  14. <BrandonW> The OS sets it to A55A and then when the calculator turns back on, it sets itself to 0.
  15. <BrandonW> Calcsys says*
  16. <BrandonW> That is wicked...
  17. <BrandonW> The OS actually running for a second after pulling the battery...
  18. <BrandonW> So the backup battery is actually really important.
  19. <BrandonW> If you pull the battery without the backup battery, RAM does reset, as it should.
  20. <BrandonW> It's holding a charge just long enough for the first interrupt timer to fire and run that code.
  21. <BrandonW> The real question is why I can't run a RAM program and get the same thing to happen.
  22. <BrandonW> Hm...
  23. <BrandonW> That's the purpose of the second hardware timer.
  24. <BrandonW> It sets a flag which enables/disables that behavior.
  25. <BrandonW> And the second hardware timer polls bit 0 of port 2 (battery status).
  26. <BrandonW> And the flag that enables that is only set in _getKey.
  27. <BrandonW> Which explains why it never resets in _getKey.
  28. <BrandonW> HAHAHAHAAAA
  29. <BrandonW> Simply setting 0,(iy+16h) in that ei \ halt loop stops the RAM reset on battery pull.
  30. <BrandonW> Wicked.
  31. <BrandonW> That is awesome.
  32. <BrandonW> That's exactly what it is.
  33. <Kurttank> no way.
  34. <DrDnar> Can you change duplicate the behavior without using the same address?
  35. <Kurttank> We can sto RAM resets?
  36. <Kurttank> *stop
  37. * bsparks\_ is now known as bsparks
  38. <DrDnar> -change
  39. <BrandonW> What do you mean by without using the same address?
  40. <Kurttank> I would have killed for that option back in the day
  41. <BrandonW> This behavior happens in the interrupt, so if you're using interrupts, you can set that and forget it.
  42. <BrandonW> The interrupt handler looks at that flag to determine whether to enable the second hardware timer.
  43. <BrandonW> I had no idea the OS was doing so much to make that happen.
  44. <BrandonW> Amazing.
  45. <DrDnar> So the interrupt detects that the battery has been removed and turns the calculator off safely?
  46. <BrandonW> Yes.
  47. <BrandonW> It's also what disables the USB controller.
  48. <DrDnar> So you could have the OS2 interrupt handler do that, but make it so it never resets RAM unless things are really, really screwed up.
  49. <BrandonW> So now we know, to shut off USB, all you need is: xor a \ out (57h),a \ out (5Bh),a \ in a,(54h) \ bit 1,a \ jr nz,$F \ ld a,2 \ out (54h),a \ xor a \ out (4Ch),a \ $$:
  50. <BrandonW> We know 5B controls USB interrupts, 57 has to do with acknowledging pending interrupts somehow, and 54 and 4C have to do with power.
  51. <BrandonW> set 0,(iy+16h) \ $$: ei \ halt \ bit 2,(iy+18h) \ jr nz,$B That's a battery-safe ei \ halt loop.
  52. <BrandonW> It makes so much sense now...
  53. <DrDnar> Great, now we can put it in our favorite password protection program.
  54. <TheStorm> so now shells should use that in their loops?
  55. <BrandonW> This would imply that ONSCRPT fires on battery re-insert, but I haven't tested it.
  56. <BrandonW> _getKey is doing that, but if you're not using _getKey, then yes, that's how you duplicate it.
  57. <BrandonW> loop: \ ei \ set 0,(iy+16h) \ halt \ jr loop Do that in a small program, pull a battery, re-insert it, and watch the cursor blink on the homescreen. I almost squealed.
  58. <BrandonW> It uses a flag to skip every other execution of the second timer, too.
  59. <BrandonW> So apparently whatever speed the second timer fires at, that's too fast or too slow or something.
  60. <BrandonW> For efficient battery checking.
  61. <BrandonW> This stuff is right at the beginning of the interrupt handler, easy to disassemble.
  62. <DrDnar> If you pull a battery during that loop, it always goes back the homescreen? Couldn't that be bad?
  63. <DrDnar> Memory leak?
  64. <BrandonW> Yes, it could be, but that's what the OS always does, boot to the homescreen context.
  65. <BrandonW> It's the "default" context if you will.
  66. <BrandonW> It really ought to be keeping track of whether a program is executing and clean it up or resume it if it can.
  67. <BrandonW> Ten years I have not known what the point of the second hardware timer was..
  68. <BrandonW> And this is it.
  69. <DrDnar> If you're running an IM 2 interrupt, can you check for a battery pull and shutdown safely?
  70. <BrandonW> I see no reason why you can't, as long as you use TI's interrupt.
  71. <DrDnar> I guess there's no way to ensure your program resumes.
  72. <DrDnar> Once the battery goes back in, the PC is reset.
  73. <BrandonW> You're just going to have to clean up the leak at the start of your program.
  74. <BrandonW> You COULD set hooks or even ONSCRPT to resume that way.
  75. <BrandonW> I have no doubt there's a way to trick the OS into it.
  76. <DrDnar> I think ONSCRPT is the day to go.
  77. <BrandonW> APDWarmStart,(iy+APDFlags) has to be set for that. I'm not sure it will be.
  78. <BrandonW> It all requires research.
  79. <BrandonW> This also confirms a couple of things...
  80. <BrandonW> One, the calculator always boots from the boot code.
  81. <BrandonW> It always boots from the boot code when it first gets power.
  82. <BrandonW> Low power mode, ei \ halt and turning the LCD on and off are what it normally does.
  83. <BrandonW> And in that situation, it does update the RAM checksum.
  84. <BrandonW> OH!
  85. <BrandonW> And of course it has to.
  86. <BrandonW> If you pull the battery while it's on, then it doesn't have time to update the RAM checksum and it sets that special case.
  87. <BrandonW> If you pull the battery while it's off (from _PowerOfF), then the checksum has been updated.
  88. <BrandonW> It all makes perfect sense...
  89. <DrDnar> It's seems like a lot of trouble for TI to go through to protect the unit from a RAM reset during an event that people shouldn't be causing anyway.
  90. <BrandonW> It happens...people are stupid, pull the batteries out for fun and play with them during class, whatever.
  91. <BrandonW> And in pre-Flash days, it was even more important.
  92. <DrDnar> Ohh! What if you drop the unit?
  93. <BrandonW> That, too.
  94. <DrDnar> That must be it. So if you drop the unit it doesn't reset.
  95. <DrDnar> So if you reset bit 2 of port 3, this no longer works?
  96. <BrandonW> The end of TI's interrupt handler will set port 3 to what it thinks it needs to be. It uses 0,(iy+16h) to determine whether to set that or not.
  97. <DrDnar> So TI sometimes disables the second timer?
  98. <BrandonW> The code for the second timer actually disables itself.
  99. <BrandonW> So it's important that you keep setting that flag in your loop.
  100. <BrandonW> It's right there in _getKey plain as day.
  101. <DrDnar> This would still be safe from within a flash application though.
  102. <BrandonW> It's safe anywhere you use _getKey.
  103. <Merthsoft> i always use _getKey
  104. <BrandonW> It's the same reason why 2ND+ON in _getKey is bad for a RAM program.
  105. <DrDnar> As long as the application doesn't have any state that needs to be specially saved.
  106. <BrandonW> Flash applications have the monitor vectors for that.
  107. <BrandonW> That's the purpose of _cxPutAway and so on.
  108. <BrandonW> I haven't even started digging into those yet.
  109. <DrDnar> The flash application will be notifed of the putaway.
  110. <DrDnar> If it wants that.
  111. <BrandonW> The backup battery will keep RAM intact. When the battery is re-inserted, the boot code gets control and passes control to you. The TI-OS always boots to the homescreen, and I'm doing the same thing. The RAM checksum being bad just determines whether you're going to reset RAM in the middle of all that.
  112. <Merthsoft> hrm
  113. <BrandonW> It's the safest thing to do...if the RAM loses power and part of it becomes corrupted, the RAM checksum can tell you it's time to start over. If you don't reset RAM, you might be in for a nasty crash because there's no telling what the state of everything is.
  114. <BrandonW> The calculator has no ability to resume from wherever it left off, there's always a single entry point for booting, and that's 0053h.
  115. <BrandonW> This is the core of what makes your calculator RAM reset from a program crash.
  116. <BrandonW> If we didn't have this, a program going bad could ruin you.
  117. <Merthsoft> So how is OS2 impervious to battery pulls?
  118. <BrandonW> The RAM checksum is actually just user RAM, from userMem to 0FE70h.
  119. <BrandonW> Merthsoft, I now have what I need to be able to tell the difference between an initial boot, and just turning back on.
  120. <BrandonW> The initial boot is for setting up user memory, variables, all that stuff.
  121. <BrandonW> The initial boot is for setting up user memory, variables, all that stuff.
  122. <BrandonW> Turning back on lets it boot right into where it needs to be on the homescreen, like if you have half an expression typed in, you pull a battery, re-insert it, and you're back where you left off.
  123. <BrandonW> This is what makes that work, if you've ever noticed in the TI-OS.
  124. <BrandonW> I'm just glad I finally understand how the thing boots.
  125. <BrandonW> And in what situations you start back at 0053h.
  126. <BrandonW> If you ever wanted to know where the code was that rebuilds the VAT from archived variables, it's at 07:58FCh on OS 2.41.
  127.  
  128. DrDnar> When you call DelMem, does the OS move stuff around?
  129. <DrDnar> Nevermind,
  130. <BrandonW> Yes, it updates an absolute ton of pointers.
  131. <BrandonW> I'm pretty sure it even updates pointers that aren't used.
  132. <BrandonW> asm_data_ptr1 and asm_data_ptr2, I think they're for you to use.
  133. <BrandonW> So you can be notified of how offset things get from a call to _DelMem or _InsertMem.
  134. <DrDnar> Once you delete yourself, you're deleted.
  135. <BrandonW> It's truly amazing what I'm learning by studying how the OS does things.
  136. <BrandonW> There's all kinds of stuff for us to use.
  137. <BrandonW> Fortunately you're just deleting the copy of yourself that the OS created, when you do it from a nostub program.
  138. <DrDnar> You could copy code to appData, jump there, delete yourself, do ti ei \ halt loop, and then if the loop returns, copy yourself back.
  139. <BrandonW> The OS stores the size of your program in RAM, you can just modify that to be 0 or whatever and then it has nothing to delete.
  140. <BrandonW> So you can still return the same way.
  141. <DrDnar> And safely survive battery pulls without causing a memory leak.
  142. <BrandonW> Yes.
  143. <BrandonW> Recalculating the checksum and either a key or app change hook should be enough to regain control even after ON+DEL.
  144. <BrandonW> The boot code doesn't reset RAM, it just sees a valid OS and jumps to 0053h. The OS makes the decision to reset or not, and we can now manipulate that with the RAM checksum.
  145. <BrandonW> So I think you could create a password program that actually can't be broken without resending the OS.