12 June 2015, 14:25 | #1 |
old bearded fool
Join Date: Jan 2010
Location: Bangkok
Age: 56
Posts: 779
|
non-system startup code time/clock problem
I've been using StingRay's excellent Non-System StartUp Code while tinkering with some old cracktro assembler source code.
The problem I have is that the system time freezes while running the code, so when you check with 'date' after exiting it is off (slow) by a few minutes (equal to the time you spent running the code). This can be fixed at the shell prompt with 'setclock load', then the time is correct again when checking with 'date' (loaded from RTC), but would prefer something nicer than using System() to call a dos command when exiting the program. My question is if there is some way to either mask out the interrupt (or other hardware register) which handles time and let that run, or if the problem is when restoring the registers when exiting the code (that you actually overwrite the clock when restoring old values). Maybe I just need to comment out some line in the code. Here is the part of the code which I suspect is causing the system to freeze the time/clock. Code:
*** Store Custom Regs *** lea $dff000,a6 ; base address move.w $10(a6),.ADK-.VARS_HW(a5) ; Store old ADKCON move.w $1C(a6),.INTENA-.VARS_HW(a5) ; Store old INTENA move.w $02(a6),.DMA-.VARS_HW(a5) ; Store old DMA move.w #$7FFF,d0 bsr WaitRaster move.w d0,$9A(a6) ; Disable Interrupts move.w d0,$96(a6) ; Clear all DMA channels move.w d0,$9C(a6) ; Clear all INT requests move.l $6c(a0),.OldVBI-.VARS_HW(a5) lea .NewVBI(pc),a1 move.l a1,$6c(a0) move.w #INTENASET!$C000,$9A(a6) ; set Interrupts+ BIT 14/15 move.w #DMASET!$8200,$96(a6) ; set DMA + BIT 09/15 bsr MAIN *************************************************** *** Restore Sytem Parameter etc. *** *************************************************** .END lea .VARS_HW(pc),a5 lea $dff000,a6 clr.l VBIptr-.VARS_HW(a5) move.w #$8000,d0 or.w d0,.INTENA-.VARS_HW(a5) ; SET/CLR-Bit to 1 or.w d0,.DMA-.VARS_HW(a5) ; SET/CLR-Bit to 1 or.w d0,.ADK-.VARS_HW(a5) ; SET/CLR-Bit to 1 subq.w #1,d0 bsr WaitRaster move.w d0,$9A(a6) ; Clear all INT bits move.w d0,$96(a6) ; Clear all DMA channels move.w d0,$9C(a6) ; Clear all INT requests move.l .VBRptr(pc),a0 move.l .OldVBI(pc),$6c(a0) move.l .OldCop1(pc),$80(a6) ; Restore old CL 1 move.l .OldCop2(pc),$84(a6) ; Restore old CL 2 move.w d0,$88(a6) ; start copper1 move.w .INTENA(pc),$9A(a6) ; Restore INTENA move.w .DMA(pc),$96(a6) ; Restore DMAcon move.w .ADK(pc),$9E(a6) ; Restore ADKcon |
13 June 2015, 15:14 | #2 |
Natteravn
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,510
|
The system time lives and is updated in a timeval structure of timer.device. This is what the dos.library/DateStamp() function and the C/date command read, when calling timer.device/GetSysTime().
As far as I understand the system time is updated every 4096 ticks by a CIA-A ALARM interrupt, which then adds the current TOD value and resets the TOD to zero. Calls to GetSysTime() will use the internal system time value and add the current TOD value to it. Which means, when you don't stop the CIA-A TOD, by writing to one of its registers, the system time should still be correct after running a program which disabled all interrupts. Even a lost CIA-A ALARM interrupt (level 2) shouldn't be a big problem, as the TOD just continues counting past 4096. So I would check if anything in your program writes to $bfe801, $bfe901 or $bfea01. Anybody please correct me if I am wrong, because I am not 100% sure either. |
13 June 2015, 18:11 | #3 |
old bearded fool
Join Date: Jan 2010
Location: Bangkok
Age: 56
Posts: 779
|
Checked the code, at first glance nothing accessing $bfexxx (except the mouse button bit being read at $bfe001) unless it is some cryptic offset.
I'm using this ugly workaround for now when exiting the code (todo; reverse 'setclock' to figure what it calls to "load from RTC"). Code:
move.l $4.w,a6 lea doslibname(pc),a1 ; dos.library moveq #0,d0 jsr -552(a6) ; Openlibrary() tst.l d0 beq.s .df move.l d0,a6 move.l #cmdexec,d1 ; restore time moveq #0,d2 moveq #0,d3 jsr -222(a6) ; Execute() move.l a6,a1 move.l $4.w,a6 jsr -414(a6) ; Closelibrary() .df movem.l (a7)+,d0-a6 moveq #0,d0 rts .... cmdexec dc.b 'setclock load',0 doslibname dc.b 'dos.library',0 http://www.flashtro.com/index.php?e=...=crack8&id=609 I've converted the source a bit further to work with Devpac. Last edited by modrobert; 13 June 2015 at 18:21. Reason: Added link. |
13 June 2015, 19:17 | #4 |
Registered User
Join Date: Oct 2009
Location: Germany
Posts: 3,305
|
Did you ask Stingray?
|
13 June 2015, 19:43 | #5 |
old bearded fool
Join Date: Jan 2010
Location: Bangkok
Age: 56
Posts: 779
|
No, but he is welcome to reply here (in this thread).
I've seen this happen with other code as well, even commercial games, but never bothered to figure out the reason then. This time there is source code, and the objective is to disable the system in a friendly way. |
13 June 2015, 20:28 | #6 |
Junior Member
Join Date: Aug 2001
Location: France
Posts: 1,385
|
perhaps you can check https://files.scene.org/view/resourc...olchain5v3.zip
Last edited by Frog; 15 June 2015 at 10:10. |
13 June 2015, 23:20 | #7 |
Registered User
Join Date: Oct 2009
Location: Germany
Posts: 3,305
|
I`ve seen/noticed that also on a few software (demos, games, tools). In A500 days it was no problem because in most cases a reset was needed after usage. Today, the coder forgot about it, don`t know how or just don`t care. Currently example is Copper-rulez-AGAin.lha (Aminet). I agree that a program what returns to WB shouldn`t affect RTC. StingRay knows the problem and if I remember right he wrote that he doesn`t care. That might be the reason why his source code don`t support it but I`m sure he will tell you how to solve it.
|
14 June 2015, 01:42 | #8 |
Natteravn
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,510
|
By writing a small test program you can easily find out that it is caused by the disabled level 2 (CIA-A) interrupt. Once you did "move.w #$0008,$dff09a" the system time stops.
But I cannot explain it. Would be interesting to find the exact reasons. The CIA-A TOD should run, no matter if interrupts are handled or not. |
14 June 2015, 06:21 | #9 | |
old bearded fool
Join Date: Jan 2010
Location: Bangkok
Age: 56
Posts: 779
|
Quote:
I tried editing startup.i like this now (also commented out my workaround), seems to work. Code:
move.w #$7FF7,d0 ; %0111111111110111 (#$8 bit not set) bsr WaitRaster move.w d0,$9A(a6) ; Disable Interrupts ($dff09a) move.w #$7FFF,d0 ; %0111111111111111 move.w d0,$96(a6) ; Clear all DMA channels move.w d0,$9C(a6) ; Clear all INT requests EDIT: Found this while searching. http://amiga-dev.wikidot.com/hardware:intenar Bit 3 (starting from zero) "I/O Ports and timers". Last edited by modrobert; 14 June 2015 at 06:45. |
|
14 June 2015, 19:00 | #10 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,534
|
Please, don't do it! Either you take over whole system or stay fully system friendly. Trying to do both will only cause trouble. For example if you leave PORTS active, any expansion that uses PORTS interrupt can now crash or hang the system. (Drivers of course assume fully functional system)
I don't think TOD interrupt was designed to handle multiple 4096 tick "overflows", it was probably kept as simple as possible to keep interrupt handlers from stealing too much CPU time. |
15 June 2015, 07:33 | #11 | |
old bearded fool
Join Date: Jan 2010
Location: Bangkok
Age: 56
Posts: 779
|
Quote:
I have mixed feelings about this problem. I'm doing this for fun, just tinkering, as opposed to releasing important code everybody relies on. When using real hardware disabling the system for a long period of time pretty much screws up networking and other stuff in my running OS anyway (AmIRC times out, iBrowse bugs out, SMBFS hangs which includes DOPUS due to directory refresh, etc.) no matter how hard you try to restore to previous state when exiting the code, so even if it seems correct in theory it still compromises the running OS unless you do it briefly. The goal here for me is to be able to to test code without rebooting my A1200 when doing code changes during development, and StingRay's startup code works well as long as I keep it under a minute or so (except for the system time problem). While thinking about this a bit more, I realized that those who care about the time/clock probably have the C:setclock command binary installed, and there is one other benefit of doing it this way, if you have an older OS version, the installed setclock binary will most likely be compatible with the booted OS. Still, I guess the best way is to use the proper function call to load time from RTC (to mimic 'setclock load'). I'm still trying to figure out how to do that, any pointers would be appreciated. Last edited by modrobert; 15 June 2015 at 08:10. Reason: Grammar and general confusion. |
|
15 June 2015, 16:58 | #12 |
ex. demoscener "Bigmama"
Join Date: Jun 2012
Location: Fyn / Denmark
Posts: 1,630
|
|
15 June 2015, 17:35 | #13 | |
old bearded fool
Join Date: Jan 2010
Location: Bangkok
Age: 56
Posts: 779
|
Quote:
Epoch! Unix time works better on 64bit systems, it needs a lot of bits. Just read this by Olaf Barthel, a can of worms: http://obligement.free.fr/articles_t..._an2000_en.php |
|
15 June 2015, 20:54 | #14 | |
Amigan
Join Date: Feb 2012
Location: London
Posts: 1,311
|
Quote:
|
|
16 June 2015, 01:47 | #15 |
old bearded fool
Join Date: Jan 2010
Location: Bangkok
Age: 56
Posts: 779
|
I was thinking of "4.4 SetClock stops working in the year 2000" and this section "4.3 The battery backed up clock can count only to 99" which is due to bad RTC hardware design. There is a patch for 'setclock' at least, but it will not help if you use WB 1.2 or 1.3 installation based on original floppies.
I'm currently disassembling 'setclock' (y2k fixed) to figure out how to set system time after reading the RTC (the loading part was explained in the BattClock documents/includes, but not how to set the current time, only print it out), also want to see how the Amiga developers did it. Last edited by modrobert; 16 June 2015 at 02:23. |
16 June 2015, 10:53 | #16 |
Natteravn
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,510
|
|
16 June 2015, 12:29 | #17 |
old bearded fool
Join Date: Jan 2010
Location: Bangkok
Age: 56
Posts: 779
|
Thanks again, but think I got it sorted...
Here is the disassembled setclock binary with comments. Phx, you are mentioned in the first part of the comments. Code:
; setclock disassambled using: adis -d0 -o -v setclock setclock.s ; comments by modrobert in 2015-06-16 ; Compile on Amiga with: vasm setclock.s -Fhunkexe -nosym -o foo ; Bit for bit perfect output thanks to 'adis' by Matt Hey and 'vasm' by phx! ; Comparing binary files sha256 checksums, original and compiled: ; setclock 740baa5e0eebd14c2357434e5205a8d720a1533bb6e1439e35be8e1e4af1153c ; foo 740baa5e0eebd14c2357434e5205a8d720a1533bb6e1439e35be8e1e4af1153c SECTION hunk_0,CODE lab_0: link a5,#-$28 ; save a5 on stack, new stack pointer in a5 (40 bytes) movem.l d2-d3/d6-d7/a2-a3/a6,-(sp) movea.w #4,a0 movea.l (a0),a3 ; execbase to a3 moveq #$14,d7 clr.l -$14(a5) moveq #-1,d6 lea lab_188(pc),a1 ; "dos.library" moveq #$24,d0 movea.l a3,a6 jsr -$228(a6) ; -552 Openlibrary() move.l d0,-$c(a5) ; store pointer to dos library on stack tst.l d0 beq.w lab_16e moveq #$b,d0 moveq #0,d1 lea -$20(a5),a1 lab_34: move.b d1,(a1)+ dbra d0,lab_34 lea lab_194(pc),a1 ; display options/flags and version move.l a1,d1 lea -$20(a5),a6 move.l a6,d2 moveq #0,d3 movea.l -$c(a5),a6 jsr -$31e(a6) ; -798 ReadArgs() move.l d0,-$28(a5) bne.b lab_66 jsr -$84(a6) ; -132 IoErr() move.l d0,d1 move.l d3,d2 jsr -$1da(a6) ; -474 PrintFault() bra.w lab_130 lab_66: lea lab_1ca(pc),a1 ; "battclock.resource" movea.l a3,a6 ; a3 holds execbase jsr -$1f2(a6) ; -498 OpenResource() movea.l d0,a2 move.l a2,d0 bne.b lab_84 pea lab_1de(pc) ; "Can't find battery-backed up clock" bsr.w lab_22e addq.w #4,sp bra.w lab_130 lab_84: moveq #$28,d0 ; want 40 bytes allocated move.l #$10001,d1 ; MEMF_ANY, MEMF_CLEAR? movea.l a3,a6 ; a3 holds execbase jsr -$c6(a6) ; -198 AllocMem() move.l d0,-$14(a5) ; store pointer for mem on stack tst.l d0 beq.w lab_130 movea.l d0,a1 lea lab_202(pc),a0 ; "timer.device" moveq #0,d0 move.l d0,d1 jsr -$1bc(a6) ; -444 OpenDevice() move.l d0,d6 ext.w d6 ; byte to word ext.l d6 ; word to long, if d6 still equals 0? beq.b lab_be ; ...go here pea lab_210(pc) ; "Could not open timer.device" bsr.w lab_22e addq.w #4,sp bra.b lab_130 lab_be: moveq #0,d7 moveq #0,d0 movea.l -$14(a5),a0 move.b d0,8(a0) move.b d0,9(a0) suba.l a1,a1 move.l a1,$a(a0) move.l a1,$e(a0) clr.l $24(a0) tst.l -$20(a5) beq.b lab_100 movea.l a2,a6 ; a2 holds battclockbase jsr -$c(a6) ; ReadBattClock() movea.l -$14(a5),a0 ; pointer to allocated memory move.l d0,$20(a0) ; d0 holds unix time from RTC move.w #$b,$1c(a0) ; io_Command = TR_SETSYSTIME movea.l a0,a1 ; IORequest structure in allocated mem movea.l a3,a6 ; execbase in a3 jsr -$1c8(a6) ; -456 DoIO() bra.b lab_130 lab_100: tst.l -$18(a5) beq.b lab_10e movea.l a2,a6 ; a2 holds battclockbase jsr -6(a6) ; -6 ResetBattClock() bra.b lab_130 lab_10e: tst.l -$1c(a5) beq.b lab_130 move.w #$a,$1c(a0) ; io_Command = TR_GETSYSTIME movea.l a0,a1 movea.l a3,a6 ; execbase in a3 jsr -$1c8(a6) ; -456 DoIO() movea.l -$14(a5),a0 move.l $20(a0),d0 movea.l a2,a6 ; a2 holds battclockbase jsr -$12(a6) ; -18 WriteBattClock() lab_130: tst.l -$28(a5) beq.b lab_142 move.l -$28(a5),d1 movea.l -$c(a5),a6 ; dos library pointer in -$c(a5) jsr -$35a(a6) ; -858 FreeArgs() lab_142: tst.l d6 bne.b lab_150 movea.l -$14(a5),a1 movea.l a3,a6 ; execbase in a3 jsr -$1c2(a6) ; -450 CloseDevice() lab_150: tst.l -$14(a5) beq.b lab_162 movea.l -$14(a5),a1 moveq #$28,d0 movea.l a3,a6 ; execbase in a3 jsr -$d2(a6) ; -210 FreeMem() lab_162: movea.l -$c(a5),a1 movea.l a3,a6 ; execbase in a3 jsr -$19e(a6) ; -414 CloseLibrary() bra.b lab_17e lab_16e: movea.w #4,a0 movea.l (a0),a1 movea.l $114(a1),a0 moveq #$7a,d0 move.l d0,$94(a0) lab_17e: move.l d7,d0 movem.l (sp)+,d2-d3/d6-d7/a2-a3/a6 unlk a5 ; restore a5 from the stack rts lab_188: dc.b "dos.library",0 lab_194: dc.b "LOAD/S,SAVE/S,RESET/S",0 dc.b "$VER: setclock 37.1 (10.1.91)",$a,$d,0 lab_1ca: dc.b "battclock.resource",0 dc.b 0 lab_1de: dc.b "Can't find battery-backed up clock",$a,0 lab_202: dc.b "timer.device",0 dc.b 0 lab_210: dc.b "Could not open timer.device",$a,0 dc.b 0 lab_22e: link a5,#-8 movem.l d2-d3/a2-a3/a6,-(sp) movea.l 8(a5),a3 movea.w #4,a0 movea.l (a0),a2 lea lab_188(pc),a1 ; "dos.library" moveq #$24,d0 movea.l a2,a6 ; execbase in a2 jsr -$228(a6) ; -552 OpenLibrary() move.l d0,-8(a5) beq.b lab_26e movea.l d0,a6 ; dosbase to a6 jsr -$3c(a6) ; -60 Output() move.l d0,d1 move.l a3,d2 lea $c(a5),a0 move.l a0,d3 jsr -$162(a6) ; -354 VFPrintf() movea.l a6,a1 movea.l a2,a6 ; execbase to a6 jsr -$19e(a6) ; -414 CloseLibrary() lab_26e: movem.l (sp)+,d2-d3/a2-a3/a6 unlk a5 ; restore a5 from the stack rts dc.w 0 Last edited by modrobert; 16 June 2015 at 15:18. Reason: Spelling. |
16 June 2015, 14:05 | #18 |
move.l #$c0ff33,throat
Join Date: Dec 2005
Location: Berlin/Joymoney
Posts: 6,863
|
|
16 June 2015, 14:17 | #19 |
Natteravn
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,510
|
|
16 June 2015, 14:29 | #20 | ||
old bearded fool
Join Date: Jan 2010
Location: Bangkok
Age: 56
Posts: 779
|
StingRay,
I understand your logic, hope you understand mine. Quote:
EDIT: I think you are wrong about the "setclock save" and "setclock load" part, that is decided by the system calls; WriteBattClock(), ReadBattClock(), but the part about setting the booted system time (as opposed to RTC) is correct? Or maybe it's just me misunderstanding, in my mind there are two separate entities handling the time in Amiga hardware, one is the system time (ticks converted to epoch seconds using interrupt handling), the other one is RTC (aka the battery backed clock). EDIT2: Hard to explain, trying again... 'setclock load' = ReadBattClock()= load time from RTC and save it to system time. 'setclock save' = WriteBattClock() = save system time to RTC. 'setclock reset' = ResetBattClock() = clear buggy RTC by setting everything to zero? (not sure about that one) EDIT3: Third time is the charm... Quote:
Last edited by modrobert; 16 June 2015 at 15:34. Reason: Three edits, getting tired. My internal clock reads; Zzz |
||
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
startup/system takeover | sidewinder | Coders. General | 15 | 28 February 2016 16:33 |
time clock prob a2000 | source | Hardware mods | 11 | 07 August 2011 13:16 |
A1200 Real Time Clock | Eclipse | support.Hardware | 4 | 22 March 2011 02:18 |
App to update Amiga System time from web time?? | DDNI | request.Apps | 2 | 31 December 2007 07:21 |
Reading the Real Time Clock | girv | Coders. General | 5 | 04 September 2007 18:30 |
|
|