swapd0 Posted February 23, 2021 Share Posted February 23, 2021 (edited) This is driving me crazy. I have the GPU running into a tight loop waiting, here is the code: ... .wait_list: load (list_ptr),events cmpq #0,events jr EQ,.wait_list moveq #0,r0 ; don't f*ck parameters address at first iteration ... After that code I've inserted an infinite loop that changes the BG register. When I run the program it works ok because I'm not writing anything into list_ptr (== 0 always), but when I put a GPUOB the GPU interrupt is executed and I leave it with this code (same as docs). And then the background color start to change (returns after the tight loop), this means that the last addqt (???) it's not needed? It's a must because without it, some times it hangs. ... ; rte bclr #3,flags ; serviced bset #12,flags ; clear interrupt flag load (stack),rts addqt #4,stack addqt #2,rts ; ??? jump (rts) store flags,(flagsAddr) ; restore interrupt I don't know why this doesn't work, I've changed the way I was creating the OP list, and now I've a lot of problems when I've a GPU Object and some GPU code running. Memory dump for the OP list without GPUOB. Quote OP list 240 bytes, start at 0000eb10 0000eb00 : 00000000 00000004 STOP 0000eb08 : 55555555 55555555 0000eb10 : 0000001d 600041c3 Jump if VC < top_line 0000eb18 : 0000001d 60008f33. Jump if VC > bottom_line 0000eb20 : 01f4081d 663201c0. Bitmap 0000eb28 : 00000002 80a0b00c 0000eb30 : 00c1581d 680001c0. Bitmap 0000eb38 : 00008000 2008806c 0000eb40 : 00c2081d 6a000340. Bitmap 0000eb48 : 0000a000 200880eb 0000eb50 : 00c3101d 6c040440. Bitmap 0000eb58 : 00008000 2008906c 0000eb60 : 00c2101d 6e004540. Bitmap 0000eb68 : 0000a000 200890ab 0000eb70 : 00c4b81d 70000640. Bitmap 0000eb78 : 00008000 4010a06c 0000eb80 : 00c5181d 72040740 Bitmap 0000eb88 : 0000a000 4010a0ab 0000eb90 : 00c5201d 74040840. Bitmap 0000eb98 : 00008000 8020b06c 0000eba0 : 00c5201d 7600c940. Bitmap 0000eba8 : 0000a000 8020b0ab 0000ebb0 : 00caa81d 78000a40. Bitmap 0000ebb8 : 00008001 0040c06c 0000ebc0 : 00d1281d 7a040b40. Bitmap 0000ebc8 : 0000a001 0040c0ab 0000ebd0 : 0113681d 7c228000. Bitmap 0000ebd8 : 00000000 2000414c 0000ebe0 : 00000000 00000004. STOP 0000ebe8 : 55555555 55555555 Memory dump OP List with GPUOB OP list 240 bytes, start at 0000eb08 0000eb00 : 00000000 00000004 STOP 0000eb08 : 0000001d 600041c3 Jump if vc < top_line 0000eb10 : 0000001d 60008f33 Jump if vc > bottom_line 0000eb18 : 00000000 00000002 GPUOB 0000eb20 : 0115881d 663201c0 Bitmap 0000eb28 : 00000002 80a0b00c 0000eb30 : 00c1081d 68040290 Bitmap 0000eb38 : 00008000 2008806c 0000eb40 : 00c1081d 6a040410 Bitmap 0000eb48 : 0000a000 200880eb 0000eb50 : 00c2101d 6c040510 Bitmap 0000eb58 : 00008000 2008906c 0000eb60 : 00c2101d 6e040610 Bitmap 0000eb68 : 0000a000 200890ab 0000eb70 : 00c3181d 70040710 Bitmap 0000eb78 : 00008000 4010a06c 0000eb80 : 00c3181d 72040810 Bitmap 0000eb88 : 0000a000 4010a0ab 0000eb90 : 00c5201d 74040910 Bitmap 0000eb98 : 00008000 8020b06c 0000eba0 : 00c5201d 76040a10 Bitmap 0000eba8 : 0000a000 8020b0ab 0000ebb0 : 00c9281d 78040b10 Bitmap 0000ebb8 : 00008001 0040c06c 0000ebc0 : 00c9281d 7a040c10 Bitmap 0000ebc8 : 0000a001 0040c0ab 0000ebd0 : 0113681d 7c400000 Bitmap 0000ebd8 : 00000000 2000414c 0000ebe0 : 00000000 00000004 STOP 0000ebe8 : 55555555 55555555 Edited February 23, 2021 by swapd0 1 Quote Link to comment Share on other sites More sharing options...
swapd0 Posted February 23, 2021 Author Share Posted February 23, 2021 (edited) Also, I've checked and I don't smash any register, the interrupt runs in the alternative register bank and the main GPU code runs in the other. Edit: IMO the bug is when I return from the interrupt, the GPU doesn't return to the correct address. Edited February 23, 2021 by swapd0 Quote Link to comment Share on other sites More sharing options...
SCPCD Posted February 23, 2021 Share Posted February 23, 2021 There is not enough informations about how the interrupts routine is written to give a solution but, this is what i have done for my FACTS demo : Main code use BANK1 Interrupt service code use BANK0 Initialisation routine : GPU_STACK .equ $F04000 ; BANK0 : ;-------- OBJ_FLAGS .equr r22 vbl_counter .equr r26 vbl_interrupts .equr r27 pGflags .equr r28 cGflags .equr r29 cGstack .equr r30 pGstack .equr r31 ;GPU initialisation gpu_init: movei #G_FLAGS,pGflags ;Flags GPU load (pGflags),cGflags bclr #3,cGflags bset #7,cGflags ;enable op interrupt bset #12,cGflags ;clear pending interrupt bclr #14,cGflags ;select bank0 store cGflags,(pGflags) ;mise a jour des flags nop nop ;Stack Pointer movei #GPU_STACK,pGstack ;adresse SP movei #VblInterrupt,vbl_interrupts movei #OBF,OBJ_FLAGS moveq #0,vbl_counter Service routine at slot 3 (GPU Object Interrupts): gpu_int_3: jump (vbl_interrupts) nop nop nop nop nop nop nop GPU Object interrupt routine : .long VblInterrupt: storew r0,(OBJ_FLAGS) ; Rr0 Rr22 | - | - load (pGflags),cGflags ; Rr28 | Cr22 | - addq #1,vbl_counter ; #1 Rr26 | Cr29 | W(r22) load (pGstack),cGstack ; Rr31 | Cr26 | Wr29 bclr #3,cGflags ; #3 Rr29 | Cr30 | Wr26 addq #2,cGstack ; #2 Rr30 | Cr29 | Wr30 addq #4,pGstack ; #4 Rr31 | Cr30 | Wr29 bset #12,cGflags ; #12 Rr29 | Cr31 | Wr30 jump T,(cGstack) ; T Rr30 | Cr29 | Wr31 store cGflags,(pGflags) ; Rr29 Rr28 | - | Wr29 ; - | Cr28 | - ; - | - | W(r28) In this exemple, I do those steps : write to the OBF register as soon as possible to allow the OP to continue his process read the GPU Flags register increase the vbl counter read the stack clear the IMASK bit correct the address of the instruction that will be executed after jumping increase the stack pointer clear the interrupt flag jump to the new address write back flags to register 1 Quote Link to comment Share on other sites More sharing options...
swapd0 Posted February 23, 2021 Author Share Posted February 23, 2021 Ok, this is my interrupt code. I'll have a look at your code to see what I'm doing wrong. .gpu stack .equr r31 flagsAddr .equr r29 flags .equr r28 rasterAddr .equr r0 colors .equr r1 clut .equr r2 op .equr r3 col .equr r4 .org G_RAM .macro EMPTY_IRQ .rept 8 nop .endr .endm ; this is the entry point of the GPU code cpu_interrupt: ; IRQ 0 movei #init_raster,r0 ; 3 movei #G_ENDRAM,stack ; 3 jump t,(r0) ; 1 moveta stack,stack ; 1 dsp_interrupt: EMPTY_IRQ timer_interrupt: EMPTY_IRQ op_interrupt: load (flagsAddr),flags ; GPU_FLAGS load (rasterAddr),colors movei #CLUT,clut ; 0, 1, 2, 3 loadp (colors),col addqt #8,colors storep col,(clut) addqt #8,clut storew op,(op) ; restore op store colors,(rasterAddr) ; rte bclr #3,flags ; serviced bset #12,flags ; clear interrupt flag load (stack),r30 addqt #4,stack addqt #2,r30 jump (r30) store flags,(flagsAddr) ; restore interrupt .long _raster_ptr:: dc.l 0 init_raster: movei #G_FLAGS,flagsAddr movei #OBF,op movei #_raster_ptr,rasterAddr load (flagsAddr),flags bset #7,flags store flags,(flagsAddr) moveta rasterAddr,rasterAddr moveta op,op moveta flagsAddr,flagsAddr subqt #4,stack ; fall to next included file (must be gpu_events.s) Quote Link to comment Share on other sites More sharing options...
swapd0 Posted February 23, 2021 Author Share Posted February 23, 2021 (edited) if I put this bset #14,flags instead of bclr #14,flags it works... I think that my jaguar init code it's wrong, I must something missing because sometimes it works, and other times it doesn't. init_jag: move.w #$2700,sr ; disable all interrups move.w #$7fff,VI ; vbi off lea stack_top,sp lea dummy_irq,a0 move.l a0,LEVEL0.w lea _BASE,a0 move.l #$070007,d0 ; big endian move.l d0,G_END-_BASE(a0) move.l d0,D_END moveq #0,d0 move.l d0,G_CTRL-_BASE(a0) ; stop gpu move.l d0,D_CTRL ; stop dsp move.l #1<<14|%11111<<9,G_FLAGS-_BASE(a0) ; disable GPU-IRQs, bank #1 ; move.l #1<<14|%11111<<9,D_FLAGS ; disable DSP-IRQs, bank #1 move.l d0,D_FLAGS move.l #%11111100000000,J_INT ; clear and disable IRQs move.l #list,d0 swap d0 move.l d0,OLP-_BASE(a0) ; set OP to STOP-OBJECT moveq #0,d0 move.w d0,R_DAC move.w d0,L_DAC move.w d0,OBF-_BASE(a0) ; clear OP-Flag move.l d0,BORD1-_BASE(a0) ; border black move.w d0,BG-_BASE(a0) ; background black move.l d0,PIT0-_BASE(a0) ; stop PIT move.l d0,JPIT1 ; stop JPIT1 move.l d0,JPIT3 ; stop JPIT2 move.w #$1F01,INT1-_BASE(a0) ; clear pending irqs & enable vbl ; blitter init lea A1_BASE,a0 lea B_CMD,a1 .cb0: move.l d0,(a0)+ cmp.l a0,a1 bne.s .cb0 lea 4(a0),a0 ; skip B_CMD lea B_Z0+4,a1 .cb1: move.l d0,(a0)+ cmp.l a0,a1 bne.s .cb1 ; video init move.w CONFIG,d0 ; Also is joystick register andi.w #VIDTYPE,d0 ; 0 = PAL, 1 = NTSC beq.s .pal move.w #NTSC_HMID,d2 move.w #NTSC_WIDTH,d0 move.w #NTSC_VMID,d6 move.w #NTSC_HEIGHT,d4 bra.s .calc_values .pal: move.w #PAL_HMID,d2 move.w #PAL_WIDTH,d0 move.w #PAL_VMID,d6 move.w #PAL_HEIGHT,d4 .calc_values: move.w d0,d1 asr.w #1,d1 ; Width/2 sub.w d1,d2 ; Mid - Width/2 add.w #4,d2 ; (Mid - Width/2)+4 sub.w #1,d1 ; Width/2 - 1 ori.w #$400,d1 ; (Width/2 - 1)|$400 move.w d1,HDE move.w d2,HDB1 move.w d2,HDB2 move.w d6,d5 sub.w d4,d5 move.w d5,VDB move.w #$FFFF,VDE move.l #0,BORD1 ; Black border move.w #0,BG ; Init line buffer to black move.w #PWIDTH4|CSYNC|BGEN|RGB16|VIDEN,VMODE-_BASE(a0) ; Configure Video rts dummy_irq: move.w #$101,INT1 ; clear vbl interrupt and enable it move.w #0,INT2 ; restore interrupts *** rte Edited February 23, 2021 by swapd0 Quote Link to comment Share on other sites More sharing options...
+CyranoJ Posted February 23, 2021 Share Posted February 23, 2021 You are only changing CLUT colours, so use VI instead. You'll hammer the bus a lot less and won't have to argue with the GPU. Quote Link to comment Share on other sites More sharing options...
swapd0 Posted February 23, 2021 Author Share Posted February 23, 2021 I'm using GPU interrupt to make a raster with a 4bits bitmap, but also I've a routine to change colors in the VI because if you do it in the middle of a frame you can get a wrong color. What I don't understand it's that some times it works, and later it doesn't. Quote Link to comment Share on other sites More sharing options...
swapd0 Posted February 24, 2021 Author Share Posted February 24, 2021 (edited) Small update, I'm using this code instead of bset & bclr to initialize the GPU and it's more stable, at least it works always the same way but it crashes when I draw the sprites with the GPU, but never if I use de 68000 with GPUOBJ. movei #G_FLAGS,gpuFlagsPtr ; init gpu movei #(1<<7)+(1<<14),r1 ; enable OBJ, reg page 1 store r1,(gpuFlagsPtr) Edited February 24, 2021 by swapd0 Quote Link to comment Share on other sites More sharing options...
swapd0 Posted February 24, 2021 Author Share Posted February 24, 2021 (edited) Another small update. I have a test program that draws several sprite with different bitmap depth, also I can scale some sprites. This is the part of the routine that check the sprite scale. if I remove this code, it it's more stable (It doesn't crash so often). So I think that with the GPUOBJ/OP Interrupts enabled, if there are some kind of pipeline stall it can break the code. ... movei #$2020,r0 cmp r0,scale jr EQ,continue_build_sprite moveq #31,tmp ; branch op ; check alignment and dst,tmp ; check 32bytes alignment movei #align_last_sprite,r20 jump NE,(r20) bset #SCALE_BIT,fields ; branch op continue_build_sprite: ... Edited February 24, 2021 by swapd0 Quote Link to comment Share on other sites More sharing options...
matmook Posted February 24, 2021 Share Posted February 24, 2021 I won't do that but add a nop between both opcodes: moveq #31,tmp and dst,tmp Quote Link to comment Share on other sites More sharing options...
matmook Posted February 24, 2021 Share Posted February 24, 2021 And not that too (add a nop too). I may be wrong but you can't be sure r20 is written before jumping? movei #align_last_sprite,r20 jump NE,(r20) Quote Link to comment Share on other sites More sharing options...
swapd0 Posted February 24, 2021 Author Share Posted February 24, 2021 I've done a few more test and it looks that every time a sprite is culled the list can be "corrupted", it works ok without a GPUOBJ and I have no glitches, also I've dumped the list and looks ok, but with a GPUOBJ the code crashes, no time to dump the sprite list Quote Link to comment Share on other sites More sharing options...
swapd0 Posted February 25, 2021 Author Share Posted February 25, 2021 (edited) Nope, OP list is right but crashes... this is so frustrating ? Edited February 25, 2021 by swapd0 Quote Link to comment Share on other sites More sharing options...
SCPCD Posted February 25, 2021 Share Posted February 25, 2021 Can you provide to me the source code of your test program ? I will look at it. Quote Link to comment Share on other sites More sharing options...
swapd0 Posted February 25, 2021 Author Share Posted February 25, 2021 (edited) The code is a mix of C/68000 asm/GPU ams, without the toolchain you won't be able to compile it and it's a bit big. Although I'm doing the test with a small program, not the game, the library it's big. Tomorrow I'll try something different, run the sprite engine with the 68000 with GPUOB interrupt and execute some "random" code in the GPU. Edited February 25, 2021 by swapd0 Quote Link to comment Share on other sites More sharing options...
swapd0 Posted February 26, 2021 Author Share Posted February 26, 2021 (edited) Ok, I got an event system running on the GPU, when I write an address into a GPU RAM location, starts to execute the functions written in that array, it's something like. gpu_queue[0] = gpu_draw_sprite; gpu_queue[1] = x; gpu_queue[2] = y; gpu_queue[3] = sprite_frame; gpu_queue[4]; run_gpu_queue(); // something like gpu_queue_ptr = gpu_queue If I load this code (gnu_shit_code) into the GPU and call it, it works fine without the GPUOB interrupts, but when I insert a GPUOB into the sprite list it hangs, sometimes very quickly sometimes it takes a while, I've to move the sprites with the joypad or it never hang. If I don't tell the GPU to execute this code, it works (it's in a busy wait). So I think that my event system that I've been using in all my projects (4 in total) has some bugs. Looking at the code it could be done in a better way, more simple and without move pc, rx... , maybe this instruction is messing around. _gpu_shit_code:: ; movei #$a0000,r0 ; load (r0),r0 .loop: nop nop nop nop nop nop nop nop nop nop nop nop ;rts moveq #4,r0 ; skip 1 parameter load (r31),r1 jump (r1) addqt #4,r31 Edited February 26, 2021 by swapd0 Quote Link to comment Share on other sites More sharing options...
+CyranoJ Posted February 26, 2021 Share Posted February 26, 2021 This is like trying to complete a jigsaw puzzle with the person with all the pieces sending a FAX of a single square every day, and the original complete image only viewable through an obscured glass window 50 meters away. 1 3 Quote Link to comment Share on other sites More sharing options...
Zerosquare Posted February 27, 2021 Share Posted February 27, 2021 Isn't it basically how you wrote Jagtopia? Quote Link to comment Share on other sites More sharing options...
+CyranoJ Posted February 27, 2021 Share Posted February 27, 2021 Yes. It is. I suspect the problem swap is having is a register being trashed in the isr. 1 Quote Link to comment Share on other sites More sharing options...
swapd0 Posted February 27, 2021 Author Share Posted February 27, 2021 3 hours ago, CyranoJ said: Yes. It is. I suspect the problem swap is having is a register being trashed in the isr. No because the event code and the interrupt routines uses different registers, there are no registers overlap. Quote Link to comment Share on other sites More sharing options...
swapd0 Posted February 27, 2021 Author Share Posted February 27, 2021 (edited) My even dispatcher code: ; GPU events queue ; ptr to function [data]* ; ptr to function [data]* ; 0 ; if a function has data, it must be read from r0 pointer ; .include "jaguar/jaguar.inc" .globl _gpu_events_list .gpu list_ptr .equr r19 event_list .equr r18 event .equr r17 return .equr r16 _gpu_events:: movei #_gpu_events_list,list_ptr moveq #0,event ; store event,(list_ptr) ; clear event list .wait_list: load (list_ptr),event_list or event_list, event_list jr EQ,.wait_list nop ; execute events .execute_event: load (event_list),event or event,event ; ptr == null, end of list, go to wait event list jr EQ,_gpu_events addqt #4,event_list ; point to next event or data store event_list,(list_ptr) ; save for next event move event_list,r0 ; parameters address ; jsr to routine movei #.l0,return subqt #4,r31 jump (event) store return,(r31) .l0: ; r0 will have number of words to skip movei #_gpu_events_list,list_ptr movei #.execute_event,event load (list_ptr),event_list jump (event) add r0,event_list ; skip parameters .long _gpu_events_list:: dc.l 0 ; pointer to events list My gpu interrupt code: ; include "jaguar/jaguar.inc" .gpu gpuFlagsPtr .equr r29 flags .equr r28 rasterAddr .equr r1 colors .equr r2 clut .equr r3 opFlags .equr r4 col .equr r5 .org G_RAM .macro EMPTY_IRQ .rept 8 nop .endr .endm cpu_interrupt: ; IRQ 0 movei #init_raster,r0 ; 3 jump t,(r0) ; 1 nop ; 1 nop ; 1 nop ; 1 nop ; 1 dsp_interrupt: EMPTY_IRQ timer_interrupt: EMPTY_IRQ op_interrupt: load (gpuFlagsPtr),flags ; GPU_FLAGS load (rasterAddr),colors movei #CLUT,clut ; 0, 1 load (colors),col addqt #8,colors store col,(clut) addqt #4,clut storew r0,(opFlags) ; resume OP store colors,(rasterAddr) ; rte bclr #3,flags ; serviced bset #12,flags ; clear interrupt flag load (r31),r30 addq #2,r30 addqt #4,r31 jump (r30) store flags,(gpuFlagsPtr) ; restore interrupt .long _raster_ptr:: dc.l 0 init_raster: movei #G_FLAGS,gpuFlagsPtr ; init gpu movei #OBF,opFlags movei #_raster_ptr,rasterAddr moveta rasterAddr,rasterAddr moveta opFlags,opFlags moveta gpuFlagsPtr,gpuFlagsPtr ; fall to next included file (must be gpu_events.s) Test code that does nothing. _gpu_shit_code:: nop nop nop nop nop nop nop nop nop nop nop nop ;rts moveq #0,r0 ; skip 0 parameter load (r31),r1 jump (r1) addqt #4,r31 Main code that tells the GPU to execute something. wait_gpu_idle(); for ( int i = 0; i < 10; ++i ) { wait_gpu_idle(); gpu_queue[0] = (uint32_t)&gpu_shit_code; // fn gpu_queue[1] = 0; // gpu_queue[2] = 0; // with this uncommented takes more time to crash the code... run_gpu_queue(); wait_gpu_idle(); } If I uncomment the gpu_queue[2] it takes more time to hang the jaguar, this means that r0 got some weird values so the event loop code fails? No, I'm testing the value of r0 after the execution of the event and is always 0. Maybe I can try to port this code to a small 100% asm test code. Edited February 27, 2021 by swapd0 Quote Link to comment Share on other sites More sharing options...
matmook Posted February 27, 2021 Share Posted February 27, 2021 That looks very complicated (and I can see some missing nop again) but what are you exactly trying to do (which effect) ? Quote Link to comment Share on other sites More sharing options...
swapd0 Posted February 27, 2021 Author Share Posted February 27, 2021 (edited) Ok, I think that I've found the bug. I call the GPU code from 6800 like this way. It hangs the Jaguar even if the loop it's executed only one time, but If I remove the last wait_gpu_idle(), it looks that never crashes. Looks like you can't hammer a gpu address from the 68000 and the GPU at the same time, isn't it? for ( int i = 0; i < 10; ++i ) { wait_gpu_idle(); gpu_queue[0] = (uint32_t)&gpu_shit_code; // fn gpu_queue[1] = 0; // gpu_queue[2] = 0; run_gpu_queue(); wait_gpu_idle(); } _run_gpu_queue:: move.l #_gpu_queue,_gpu_events_list rts _wait_gpu_idle:: lea _gpu_events_list,a0 .wait: moveq #127,d0 divu #3,d0 move.l (a0),d0 bne.s .wait rts .long _gpu_queue:: ds.l 128 Edited February 27, 2021 by swapd0 Quote Link to comment Share on other sites More sharing options...
+CyranoJ Posted February 28, 2021 Share Posted February 28, 2021 The 68000 writes to the GPU RAM in 16-bit segments, so two writes for a longword. The GPU reads as 32bit, and is clocked higher. It's reading only half the address (the high half) You should be setting a sempahore flag, and checking that, not the actual pointer value. .wait_list: load (list_ptr),event_list or event_list, event_list jr EQ,.wait_list nop That is your problem. 2 Quote Link to comment Share on other sites More sharing options...
matmook Posted February 28, 2021 Share Posted February 28, 2021 8 hours ago, CyranoJ said: That is your problem. Well, one of them... 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.