17 July 2021, 22:49 | #1 |
Newbie Amiga programmer
Join Date: Jun 2012
Location: Front of my A500+
Age: 38
Posts: 372
|
Periodical code call, if level 2, 3 and 6 interrupts are occupied?
I have a small code snippet which i would like to run periodically during a (non-system-friendly) game, but the game uses all the interrupts i know they can be used for cyclical code calling. Is there any way to do this? Or the only way is to modify the game itself?
Edit: It seems, the game does not use level 7 interrupts, but even if i write my code's entry address into $7c, nothing happens. Can NMI be disabled? Last edited by TCH; 17 July 2021 at 23:01. Reason: Level 7 |
17 July 2021, 23:06 | #2 |
This cat is no more
Join Date: Dec 2004
Location: FRANCE
Age: 52
Posts: 8,162
|
level 7 interrupts can only be triggered by extra hardware (Action Replay, HRTMon extra button...). It seems that you have a lot to learn sorry to say it like this.
Just hook on the interrupt that interests you (level 3 check INTREQ for bit 5 set means vblank) and you have a 20ms (PAL) periodic routine. We do that all the time in whdload slaves to poll joypad buttons periodically. Another idea is (68010+ only) set the VBR to non-zero and handle interrupts from there, then call the regular zero page interrupts (as the program cannot know the VBR base and assumes zero unless it sets it which is rare) |
17 July 2021, 23:21 | #3 |
Newbie Amiga programmer
Join Date: Jun 2012
Location: Front of my A500+
Age: 38
Posts: 372
|
Notice the label below my name...
Level 3 interrupts are used by the game. I've checked the Level 3 interrupt subroutine and it has fix jsr-s, so i managed to inject my address there and then from my subroutine i jump to the original address. But for this, i need the WinUAE debugger. It's an AGA game, so VBR is present and indeed it is zero, according to the WinUAE debugger, but if i try to set it to anything, then the entire system is crashing which is not a surprise. How can this be done, before the game starts? Level 1 seems to be unoccupied. Can i cause a Level 1 interrupt manually? I tried to copy the VBR table and then set VBR in supervisor mode, but i get GURU $80000008: Code:
move.l #$1ffb00,a2 movea.l #$0,a0 move.l a2,a1 move.l #$100,d0 VBRCopyLoop: move.l (a0)+,(a1)+ dbra d0,VBRCopyLoop move.l #$1fff00,$1ffb6c move.w sr,-(a7) ori.w #$2700,sr movec.l a2,vbr move.w (a7)+,sr Last edited by TCH; 18 July 2021 at 00:23. Reason: Level 3 expanded, Level 1, VBR |
18 July 2021, 00:56 | #4 |
Natteravn
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,496
|
I'm not sure what you are trying to do, but when you get a Privilege Violation exception then you are certainly in user mode while writing to SR.
When the OS is still alive, use Supervisor()to call your VBR-setting code. Otherwise write the pointer to your supervisor code into any free trap-vector, like $80. Then run it with trap #0and return with rte. |
18 July 2021, 01:33 | #5 |
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,408
|
Yes, you can do that. Easiest way to do this is probably by setting bit 2 in the INTREQ register (and of course setting INTENA to the proper mask and setting up the corresponding interrupt vector).
|
18 July 2021, 01:40 | #6 | |
Newbie Amiga programmer
Join Date: Jun 2012
Location: Front of my A500+
Age: 38
Posts: 372
|
Quote:
Supervisor()from Assembly? Just write a subroutine, leait's address into a5and then jsr Supervisor(a4)? I am using vasm ( -m68020 -Fhunkexe), is Exec opened automatically into a4or i have to do that manually?The problem is, that i lose the control, when the game starts; it's not a system-friendly game. How can i trigger that Level 1 interrupt afterwards, for example from keyboard? |
|
18 July 2021, 01:59 | #7 | |
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,408
|
Quote:
So in effect, you'd have to create some sort of hook into the existing code that triggers the level 1 interrupt. But if you're doing that, you may as well just change the code so that f.ex. the level 3 interrupt jumps to your code at some point. Honestly, I have little experience in changing existing games, but my guess would be that putting some sort of JSR or JMP (or even branch) into an existing interrupt would be best. You'd basically just have to find some space to put your code and then patch the address where your code resides at runtime into the pre-existing code (i.e. in the JSR/JMP you'd have to add). |
|
18 July 2021, 09:40 | #8 |
Newbie Amiga programmer
Join Date: Jun 2012
Location: Front of my A500+
Age: 38
Posts: 372
|
In the meantime i've found that Exec is always open, but not at
(a4), but 4...it was late and i confused it. :P I wrote the following code: Code:
move.l #$1ffb00,a2 movea.l #$000,a0 move.l a2,a1 move.l #$100,d0 VBRCopyLoop: move.l (a0)+,(a1)+ dbra d0,VBRCopyLoop move.l #$1fff00,$1ffb6c movea.l $4,a3 lea SetVBR(pc),a5 jsr -$1e(a3) moveq #0,d0 rts SetVBR: movec a2,vbr rte $4, not #4. /o\ Now it fails with GURU 80000004, which is division by zero. @roondar: That was i tried to do, inject my subroutine's address into the game's Level 3 interrupt subroutine which starts at $119d48 and has a jsr $00118782at $119d4c. With WinUAE i can do that (W 119d4e 1fff00) and then it will call my subroutine (which will do the overridden jsr $00118782manually at it's end), but for this, i have to do this manually in WinUAE. The question is, how can i set up something which either can do a simple move.l #$001fff00,$00119d4cor do something else which call my subroutine after the game loaded (and took over all Level 2, 3 and 6 interrupts). Either by automatically, or manually, like triggering via a keystroke. If i am able to call my subroutine at least once after the game loaded, then the problem is solved. Or is it impossible and i have to alter the game? Last edited by TCH; 18 July 2021 at 11:52. Reason: #->$ |
18 July 2021, 10:01 | #9 |
move.l #$c0ff33,throat
Join Date: Dec 2005
Location: Berlin/Joymoney
Posts: 6,863
|
When calling library functions, the library base has to be in a6. Supervisor() may not work correctly when that is not the case.
|
18 July 2021, 10:16 | #10 |
Newbie Amiga programmer
Join Date: Jun 2012
Location: Front of my A500+
Age: 38
Posts: 372
|
It's still 80000004. I've checked the registers in the debugger.
a5contains the address of SetVBR, a6the address which was under $4and a2has $1ffb00. It should work? Edit: Never mind, it seems, that now the VBR is also set to the proper value, so the error now lies in the subroutine itself. Edit 2: Or, maybe not in the subroutine, because even if it is only a single jsr ($6c)or a simple infinite loop, it is still 80000004. If i do not alter the new L3I vector at $1ffb6c, then the game works, although there is no music and sound. (Since nothing copies the L2 and L6 interrupt vectors and nothing calls the L3 one.) Edit 3: The game seems to store data under the L6 interrupt vector ( $109688), it's full of zeros and if i write something there, garbage pixels appear and after a while the location gets zeroed again. Last edited by TCH; 18 July 2021 at 10:52. Reason: VBR too, set |
18 July 2021, 11:53 | #11 | |
Natteravn
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,496
|
I have the feeling you are overcomplicating things. As I understand you already found the solution, here:
Quote:
Otherwise, please explain again in detail what you are trying to achieve. |
|
18 July 2021, 12:39 | #12 |
Newbie Amiga programmer
Join Date: Jun 2012
Location: Front of my A500+
Age: 38
Posts: 372
|
But which interrupt? AFAIK, only L2, L6 (CIA Timers) and L3 (VBlank) can be used for periodically called interrupts, which i can control and the rest are generated by events which will never happen during the game. And L2, L3 and L6 are used by the game.
The code i cannot change so easily, as it's a trackloader game using a HD loader and some kind of compression. I have no idea where is the actual code or how it is packed, but even if i would know and could decompress it, i also have to repack it afterwards and if the packed length will change (because i've changed the entropy with the changed address), then data consistency is annihilated. Writing a loader which patches that address is what i am trying to do, but the code is periodically loaded and erased from the memory, so it can be only patched when the game is already running and it has to be patched periodically, but when the game is already running, then it has already occupied all the L2, L3 and L6 interrupts. The question is, can i hook my code to an L1, L4 or L5 interrupt in a way it will be called either periodically or manually via keystroke, joystick/mouse event or any kind of user action. |
18 July 2021, 12:53 | #13 | |
move.l #$c0ff33,throat
Join Date: Dec 2005
Location: Berlin/Joymoney
Posts: 6,863
|
Quote:
|
|
18 July 2021, 13:11 | #14 |
Natteravn
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,496
|
I see your problem. The optimal solution would be to analyze the decompression algorithm and the file structure, so you would be able to write the patched file back to disk.
What StingRay suggests is that there must be a resident piece of code, which loads and decrunches other code loaded from disk, like the one you're interrested in. You should have a better chance to patch this loader instead, which is hopefully only loaded once the game is booted from disk. Do that by finding a kind of signature which identifies your file. Like a start address and/or the first bytes of the file. Maybe there is even a kind of file-index in the trackloader based custom file system. When it matches, patch the code after loading and decrunching. |
18 July 2021, 13:15 | #15 |
Newbie Amiga programmer
Join Date: Jun 2012
Location: Front of my A500+
Age: 38
Posts: 372
|
@StingRay:
The decruncher which is responsible for putting the code onto it's place is itself on one of the disk images, compressed. There are four NDOS disk images and a 2.4 kB loader which only does load the main program/intro from disk0. I don't know where is the actual code stored. Just to test it, i made a snapshot of the ChipRAM ( S dump.map 0 200000), then tried to find anything which references the L3 interrupt vector ($00119d48). I found only one at $1170AE. Disassembly ( dg 1170ae) and i got the code move.l #$00119d48,$0000006c, so it is just the one which moves the address to the vector table. There are no more references to this address, so the decrunching starts from another address. Edit: (The forum really should alert on quick posting, if another post arrived since i started writing...) @phx: The loader only loads the main program, not the actual code needed to be patched. The code at $119d48 is loaded in the options, but replaced during in game. I have no idea how to find the decruncher. Edit 2: I made a snapshot during the intro/loading, but no references of $119d48 are found. The bytes of $00 $11 $9d $48 are not exists in the memory during loading. Last edited by TCH; 18 July 2021 at 13:23. Reason: new post, answer |
18 July 2021, 13:34 | #16 |
Registered User
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,408
|
It can get tricky, depending on how the loader works. It's not that unlikely they may have implemented some form of relocation instead of relying on fixed addresses.
|
18 July 2021, 15:22 | #17 | |
move.l #$c0ff33,throat
Join Date: Dec 2005
Location: Berlin/Joymoney
Posts: 6,863
|
Quote:
|
|
18 July 2021, 15:31 | #18 |
Newbie Amiga programmer
Join Date: Jun 2012
Location: Front of my A500+
Age: 38
Posts: 372
|
Okay, so, the answer to the original question: no, it's not possible to do periodical calls without L2, L3 or L6 interrupts, i have to modify the game itself. Thanks.
|
18 July 2021, 18:53 | #19 | |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
|
Quote:
1) similar to what jotd suggested to you: move your vector table somewhere and insert your own timed routine (the easiest way is with VBI IRQ3) At that point, however, you have to monitor at each call the changes that are made in the table of vectors at location $0 by the game (not only for the IRQs but also for all the others!*) and report the changes in your relocated table (logically by chaining the game IRQ3 to your code since you cannot 'substitute' yourself, otherwise you lose control of your routine) 2) use MMU to 'grab' the changes to the IRQ3 vector and hook your routine to it *EDIT: there is a big flaw here. Suppose the game modifies a trap vector and calls it immediately: you notice the change only in VBI and the code probably crashes. Many games only change the IRQ vectors and rarely their call is immediate or must be perfectly synchronized, but also in this case it could happen. So in any case it is absolutely recommended to modify the game code, even if only to understand what actually happens. Last edited by ross; 18 July 2021 at 19:40. |
|
18 July 2021, 22:11 | #20 |
Newbie Amiga programmer
Join Date: Jun 2012
Location: Front of my A500+
Age: 38
Posts: 372
|
I tried to move the vector table. It worked, but the game lost sound and whenever i tried to supersede the original L3 routine the system has crashed.
MMU is not present. I have no idea how to modify the game's code. The way the loader access the files and loads the data requires heavy Amiga related knowledge. Perhaps i can debug where the program unpacks stuff, but i cannot patch the live code, if the game occupies all usable interrupts. |
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
Wizzy's Quest (PD) Level codes - and [Request] for Level editor | Dan | support.Games | 30 | 25 August 2023 00:30 |
Interrupts, doing it low level, but properly. | deimos | Coders. General | 7 | 25 September 2019 19:45 |
WinUAE Bug/Issue Source Code Function Call | Audiorulz4u | support.WinUAE | 6 | 11 October 2017 17:40 |
New Independent Periodical "in the style of" Amiga Power | Anakirob | Retrogaming General Discussion | 14 | 29 June 2017 12:58 |
Akira's periodical quest for Amiga hardware | Amiga1992 | MarketPlace | 10 | 02 February 2005 01:10 |
|
|