PeteD Posted September 14, 2009 Share Posted September 14, 2009 If you time it right they don't flicker It just takes up the whole line of cpu but if it only happens a few times a frame its not so bad. Pete Quote Link to comment Share on other sites More sharing options...
TMR Posted September 14, 2009 Share Posted September 14, 2009 If you time it right they don't flicker It just takes up the whole line of cpu but if it only happens a few times a frame its not so bad. Depends on where they try to place themselves as well though, too close together horizontally and it's going to break anyway... Quote Link to comment Share on other sites More sharing options...
PeteD Posted September 14, 2009 Share Posted September 14, 2009 True but the occasional one on the other side of the screen should be ok. Pete Quote Link to comment Share on other sites More sharing options...
TMR Posted September 14, 2009 Share Posted September 14, 2009 What's the shortest distance it's possible to reassign two sprites in though...? Quote Link to comment Share on other sites More sharing options...
PeteD Posted September 14, 2009 Share Posted September 14, 2009 I saw someone had worked this out in another thread and it was surprisingly short, like almost next to each other. You've got to use the GRAFPn registers to reload the data, change the X and of course it'd save some clocks if you manage to get 2 the same colour Pete Quote Link to comment Share on other sites More sharing options...
andym00 Posted September 14, 2009 Share Posted September 14, 2009 I saw someone had worked this out in another thread and it was surprisingly short, like almost next to each other. You've got to use the GRAFPn registers to reload the data, change the X and of course it'd save some clocks if you manage to get 2 the same colour And you'd probably spend more cycles checking if it was the same then just setting the damn thing Quote Link to comment Share on other sites More sharing options...
andym00 Posted September 14, 2009 Share Posted September 14, 2009 If you time it right they don't flicker It just takes up the whole line of cpu but if it only happens a few times a frame its not so bad. You're a braver man than me on this subject then if you want to try it That's a subject I don't even want to consider right now.. I just can't see how you'd feasibly work the logic into the multiplexer, and woe betide you if there's any DLIs floating around as that'll basically make parts of the screen inaccessible to your horizontal splitter, or at the very best lines will vanish from sprites in those regions.. How would you do it ? Prepare a jump table for each line of the screen where there's multiple horizontal splits, jump in, set HPOS0, then do a variable cycle jump ? But you're then at the mercy of the NMIs killing you if that have happened, or do happen in your fancy horizontal code.. Maybe you an old C64 trick might help If you can set the joystick port data direction to out, and hit the fire button line, and trigger the light-pen button, you can read back your horizontal line position from the light pen register, which might make the loop a bit simpler, at least more stable, and some chance of recovering sensibly from an IRQ murdering you, or even from interrupt jitter.. But I don't know how often you can hit do the lightpen conversion on an A8.. Maybe there's other resources the A8 can use to figure out the horizontal scanline position.. Just a thought Quote Link to comment Share on other sites More sharing options...
PeteD Posted September 14, 2009 Share Posted September 14, 2009 I suppose, but that could be offscreen, do some self modifying code for the lines with more than 4. I'm just spurting stuff from my brain really cuz I was thinking about exactly this the other day. It would make some of my Fist backgrounds a lot easier to be able to repeat PMGs. I'd done some tests with a DLI per line and its surprising how wasteful that is in some modes. All I was doing was storing A, doing a wsync then changing a register, getting A back and RTI. I ran a full screens worth and did a trace (tron filename hehe tron) in Atari800Win and I was getting about 18 cycles free per line. Doing 1 DLI and then NOPs till it went wonky, removing a nop, then changing the last nop to a wsync gave me 48 cycles of nops per line. So the overhead of a DLI and a wsync can be really hefty. I think as I'm already using a timer on Fist I'd be better going for a timing it to trigger in the middle (or just before) of the screen, that way I can change some PMG stuff on that line then wsync for the next one. Pete Quote Link to comment Share on other sites More sharing options...
analmux Posted September 14, 2009 Share Posted September 14, 2009 Don't forget about the DRAM refresh cycles: They also steal CPU cycles. Every scanline contains 9 refresh cycles, and they happen when the 'left part' of the scanline is written to TV. So, There's barely enough time to multiplex 2 (or maybe 3) players (shape AND x). Quote Link to comment Share on other sites More sharing options...
PeteD Posted September 14, 2009 Share Posted September 14, 2009 If you time it right they don't flicker It just takes up the whole line of cpu but if it only happens a few times a frame its not so bad. You're a braver man than me on this subject then if you want to try it That's a subject I don't even want to consider right now.. I just can't see how you'd feasibly work the logic into the multiplexer, and woe betide you if there's any DLIs floating around as that'll basically make parts of the screen inaccessible to your horizontal splitter, or at the very best lines will vanish from sprites in those regions.. How would you do it ? Prepare a jump table for each line of the screen where there's multiple horizontal splits, jump in, set HPOS0, then do a variable cycle jump ? But you're then at the mercy of the NMIs killing you if that have happened, or do happen in your fancy horizontal code.. Maybe you an old C64 trick might help If you can set the joystick port data direction to out, and hit the fire button line, and trigger the light-pen button, you can read back your horizontal line position from the light pen register, which might make the loop a bit simpler, at least more stable, and some chance of recovering sensibly from an IRQ murdering you, or even from interrupt jitter.. But I don't know how often you can hit do the lightpen conversion on an A8.. Maybe there's other resources the A8 can use to figure out the horizontal scanline position.. Just a thought erm ok, I'll just keep quiet eh? Was after all just an idea following on from Heaven's post about more than 4 per line. No need to be facetious. Pete Quote Link to comment Share on other sites More sharing options...
Heaven/TQA Posted September 14, 2009 Author Share Posted September 14, 2009 I ment "standard" flickering... no reuse of the sprites horizontal. Simple thing like in Joust. Quote Link to comment Share on other sites More sharing options...
andym00 Posted September 14, 2009 Share Posted September 14, 2009 (edited) I suppose, but that could be offscreen, do some self modifying code for the lines with more than 4. I'm just spurting stuff from my brain really cuz I was thinking about exactly this the other day. It would make some of my Fist backgrounds a lot easier to be able to repeat PMGs. I'd done some tests with a DLI per line and its surprising how wasteful that is in some modes. All I was doing was storing A, doing a wsync then changing a register, getting A back and RTI. I ran a full screens worth and did a trace (tron filename hehe tron) in Atari800Win and I was getting about 18 cycles free per line. Doing 1 DLI and then NOPs till it went wonky, removing a nop, then changing the last nop to a wsync gave me 48 cycles of nops per line. So the overhead of a DLI and a wsync can be really hefty. I think as I'm already using a timer on Fist I'd be better going for a timing it to trigger in the middle (or just before) of the screen, that way I can change some PMG stuff on that line then wsync for the next one. Pete In wide mode I'm finding myself excessively short of cycles for some reason.. I mean way shorter than I would expect to be, so maybe it's time to roll out this tron contraption then Actually now I think about it, it's not so bad to split the sprites horizontally I guess.. If you prepared single line kernels ahead that just did lda #(max_delay-desired_delay) lsr sta .br +1 .br bcc * nop nop nop (nops for max_delay - 3 cycles) lda #xpos sta HPOS0n lda #colour sta COLPMn lda #gfx sta GRAFPn That'd give you a nice simple point to write the delay and data, and it's not a huge chunk of code, then you can prepare one for each line without much cost.. Chain them automagically for the full height of the screen, and break the chain when you need.. Yeah, there's 11 cycles or so overhead at the start.. Hmmm.. Though they'd be faster in the NMIs since you don't seem to have to ACK them like the timer IRQs which is painfully slow with lda/sta/lda sta for each one.. But I guess you want the NMIs for DLI faffing ? You can shift the tick point of 15Khz timer over into the centre of the screen (well anywhere along the line infact)[1], well probably earlier to allow interrupt entry and other shenanigans dead easily, except it doesn't work in Atari800WinPlus.. Just Set lower 3 bit of SKCTL to 0, hit STIMER, the SKCTL to 3 so you could very easily align you interrupts once per frame to the split point you want.. Maybe it'd actually be more manageable with interrupts in reality [1] Though there's some issues with IRQs occuring at the same time as DLIs and the IRQ being ignored (or was it the other way around?) Pretty sure it was IRQs.. Check the thread about this in this sub-forum for all of it.. I can't remember the ins and outs exactly, but you should read it if you're even thinking about that I guess Edited September 14, 2009 by andym00 Quote Link to comment Share on other sites More sharing options...
analmux Posted September 14, 2009 Share Posted September 14, 2009 I suppose, but that could be offscreen, do some self modifying code for the lines with more than 4. I'm just spurting stuff from my brain really cuz I was thinking about exactly this the other day. It would make some of my Fist backgrounds a lot easier to be able to repeat PMGs. I'd done some tests with a DLI per line and its surprising how wasteful that is in some modes. All I was doing was storing A, doing a wsync then changing a register, getting A back and RTI. I ran a full screens worth and did a trace (tron filename hehe tron) in Atari800Win and I was getting about 18 cycles free per line. Doing 1 DLI and then NOPs till it went wonky, removing a nop, then changing the last nop to a wsync gave me 48 cycles of nops per line. So the overhead of a DLI and a wsync can be really hefty. I think as I'm already using a timer on Fist I'd be better going for a timing it to trigger in the middle (or just before) of the screen, that way I can change some PMG stuff on that line then wsync for the next one. Pete That's why maybe it's the best solution to use 1 timer IRQ, which is already synced to an offscreen cycle. Then no wsyncs are needed. Redefine $fffe vector for a faster IRQ handler etc. During a piece of vblank code one can 'prepare' the interrupts for the actual screen building up. Sometimes one needs a timer IRQ, and when a regchange coincides with the top rasterline of a charmode display line, we dissable the IRQ and handle the task by DLI instead. But, this flexibility might need precomputed stuff. So, that's why we do a 'prepare' routine during VBL Quote Link to comment Share on other sites More sharing options...
andym00 Posted September 14, 2009 Share Posted September 14, 2009 I ment "standard" flickering... no reuse of the sprites horizontal. Simple thing like in Joust. Too late Quote Link to comment Share on other sites More sharing options...
PeteD Posted September 14, 2009 Share Posted September 14, 2009 (edited) That's why maybe it's the best solution to use 1 timer IRQ, which is already synced to an offscreen cycle. Then no wsyncs are needed. Redefine $fffe vector for a faster IRQ handler etc. During a piece of vblank code one can 'prepare' the interrupts for the actual screen building up. Sometimes one needs a timer IRQ, and when a regchange coincides with the top rasterline of a charmode display line, we dissable the IRQ and handle the task by DLI instead. But, this flexibility might need precomputed stuff. So, that's why we do a 'prepare' routine during VBL Yeah, atm I've just got the 1 timer going for Fist, I was just messing with the DLI stuff last night when I began to wonder about the same thing Andy is doing of changing the timer count and if it's really going to screw any sound routines. eg If I want a timer to trigger in 8 lines time, then another in 5, then the next in 15, how reliable will that timer be? Does the counter get loaded into an internal counter and just ignore the one we have access to until it triggers or you force it to reset with STIMER? I really need to get an sio2pc or something so I can check this stuff on hardware because it's kind of guesswork with the emulators. I know they're not "bad" but if they're not 100% like the C64 ones pretty much are then I'm writing code that isn't going to work again. Pete Edited September 14, 2009 by PeteD Quote Link to comment Share on other sites More sharing options...
PeteD Posted September 14, 2009 Share Posted September 14, 2009 (edited) I ment "standard" flickering... no reuse of the sprites horizontal. Simple thing like in Joust. Too late lol Would be very nice if someone could incorporate it. As you say if you've got contentious interrupts happening it can all go to pot but if your DLI/timer code takes both into account you can always drop any DLI stuff into the timer irq or vice versa. Pete Edited September 14, 2009 by PeteD Quote Link to comment Share on other sites More sharing options...
andym00 Posted September 14, 2009 Share Posted September 14, 2009 Too late lol Would be very nice if someone could incorporate it. As you say if you've got contentious interrupts happening it can all go to pot but if your DLI/timer code takes both into account you can always drop any DLI stuff into the timer irq or vice versa. We'll see, I'll have a bash at it, but right now I've got other things on my mind, though I had written the idea off until just thinking about it now and a kind of solution formulating.. The plexer easily hands out missed sprites anyway, so without any extra effort I know which need to be horizontally split.. Though I'd much rather put these into DLIs and lose the time when a sprite is horizontally split since it'd be a pain to incorporate this into the normal multiplexer code, much more so than just biting the cost of the interrupt overhead each line for the DLI, which at 19 cycles I don't see being so big for the occasions you'd need this.. But I think it'll make regular multiplexing 'iffy' in those zones where horizontal splits are occuring.. Quote Link to comment Share on other sites More sharing options...
PeteD Posted September 14, 2009 Share Posted September 14, 2009 I wouldn't be in any rush to do it anyway apart from "because" hehe probably nobody would use it if you uploaded the source so unless its for something specific you were doing or because you fancy having a go there's no point. It's one of the things on my list of "to do" for A8 once Exploding Fist is done. But then like most coders that's a pretty big list and it's just the A8 one lol I keep looking at CPC and going, apart from if it was limited to 64k ram there's no reason Fist should be that crap on there..... Pete Quote Link to comment Share on other sites More sharing options...
andym00 Posted September 14, 2009 Share Posted September 14, 2009 I wouldn't be in any rush to do it anyway apart from "because" hehe probably nobody would use it if you uploaded the source so unless its for something specific you were doing or because you fancy having a go there's no point. It's one of the things on my list of "to do" for A8 once Exploding Fist is done. But then like most coders that's a pretty big list and it's just the A8 one lol I keep looking at CPC and going, apart from if it was limited to 64k ram there's no reason Fist should be that crap on there..... I'd only do it because I want as many sprites as possible.. I've just added P5 stuff and god it hurts having to do lda/sta/adc/sta/adc/sta/adc/sta just to set it's X position!! I think I'll probably keep the missiles seperate and just use PF3 for them and multiplex them seperately from the players for lots of little things flying around But sounds like me wanting to do Street Fighter with walloping big sprites and backgrounds on the 64, all very doable, except the distinct lack of ram, and I feel like I'm cheating if I use the REU Out of curiousity, how much memory does of the Fist player images take up ? Quote Link to comment Share on other sites More sharing options...
PeteD Posted September 14, 2009 Share Posted September 14, 2009 (edited) Not sure on the ram usage for all the Fist sprite frames yet simply because I haven't grabbed them all. The C64 ones take up around 24k, so far the few I've grabbed while faffing with different softsprite routines are coming out as less per frame than the c64 one but only just as it's a runlength routine. There's lots of clear bytes in the Fist sprites but that tends to get eaten up by any mask data. THEN the problem is I really kind of want another set with a 2 pixel offset to save having to shift the data at runtime so fitting it all in 64k may end up being a problem The good thing about Fist is the anims only run at about 12fps so apart from maybe effecting gameplay if a game was to drop to that (Paradroid afaik runs about that speed) with not triggering actions fast enough I could get away with maybe making the masks and doing the shifting. It shouldn't drop anywhere near that anyway (he says hehe). Pete Edited September 14, 2009 by PeteD Quote Link to comment Share on other sites More sharing options...
andym00 Posted September 14, 2009 Share Posted September 14, 2009 Not sure on the ram usage for all the Fist sprite frames yet simply because I haven't grabbed them all. The C64 ones take up around 24k, so far the few I've grabbed while faffing with different softsprite routines are coming out as less per frame than the c64 one but only just as it's a runlength routine. There's lots of clear bytes in the Fist sprites but that tends to get eaten up by any mask data. THEN the problem is I really kind of want another set with a 2 pixel offset to save having to shift the data at runtime so fitting it all in 64k may end up being a problem The good thing about Fist is the anims only run at about 12fps so apart from maybe effecting gameplay if a game was to drop to that (Paradroid afaik runs about that speed) with not triggering actions fast enough I could get away with maybe making the masks and doing the shifting. It shouldn't drop anywhere near that anyway (he says hehe). I'd always assumed from looking at it (and playing it loads when I was a young lad) that the animations were like Barbarian, in that they animated within the frame and didn't require proper shifting, just byte aligned drawing, but it's interesting to know how much memory they take up.. I'd imagined they'd be bigger than that.. Quote Link to comment Share on other sites More sharing options...
analmux Posted September 14, 2009 Share Posted September 14, 2009 ...I was just messing with the DLI stuff last night when I began to wonder about the same thing Andy is doing of changing the timer count and if it's really going to screw any sound routines. Why should it? If we restrict music & sound to channel 1,2 & 3, then timer 4, used by channel 4, is still free for other usage. The fact is, to sync the FIRST ever needed timer IRQ to a certain display event we need to do a write to STIMER, but this is ONLY ONCE. After that, when handled properly, i.e. writing the right values to AUDF4 at certain moments, we don't need to resync timer 4 anymore. eg If I want a timer to trigger in 8 lines time, then another in 5, then the next in 15, how reliable will that timer be? No problems of reliability here! When one IRQ is running, the timer has already started with its new cycle. It is indeed an internal timer, only reloading to its (maximum) value when reaching zero. It is just a countdown timer. In the meantime we write a new value to AUDF4, and this value determines the EXACT duration of the next timer cycle. In 15khz mode, one rasterline takes one tick of the timer. Now a PAL frame is 312 rasterlines, so using 15khz mode on AUDCTL and only ONE timer, we're restricted to 8 bit. Thus, we'll never reach 312 after counting down a 8bit timer. That's why we need to split up the frame into multiple IRQs. As long as the list of N consecutive timer values written to AUDF4 adds up to 312 and starting the whole interrupt cycle again after the N'th, we're sure the situation is the same during the next frame. The other timers of the first 3 registers aren't interfered / interrupted /disturbed at all. The only thing changing is the global clocking of all voices, from 64 (standard) to 15 khz. But, using some hardsynth / other techniques, there are solutions for 'music problems'. Channel 1 and 3 can be clocked separately, that's why we don't want to use timer 1 (or 2). Quote Link to comment Share on other sites More sharing options...
PeteD Posted September 14, 2009 Share Posted September 14, 2009 Well, I understand all that and did already I'm not trying to say that using a timer in general is going to screw up everything, I got that weeks ago, I'm just saying I can't see how to do what I want without the STIMER trigger. If I do say a DLI to init he timers to the cycle I want them to trigger, set say 15 in AUDF4 I can be sure I'll get an IRQ in 15 lines. If it triggers and then begins to count down again, how do I then change it to say 5 before it triggers again? If it only reloads when it triggers does it give you any time at all to put a new value in AUDF4? It's this I don't quite understand. "When one IRQ is running, the timer has already started with its new cycle. It is indeed an internal timer, only reloading to its (maximum) value when reaching zero. It is just a countdown timer. In the meantime we write a new value to AUDF4, and this value determines the EXACT duration of the next timer cycle." If the timer is already running but I want to change it, can I? That's basically the question posed by the whole of my post on the subject. eg I have a timer of value 5, it goes 5,4,3,2,1,IRQ,5,4,3,2,1,IRQ2 ? but If I want the 2nd one to be 10 will putting 10 into AUDF4 at any point during that 2nd countdown change the internal countdown or will it only fetch my 10 when it hits IRQ2. Not sure I can explain it any better than that. Pete Quote Link to comment Share on other sites More sharing options...
analmux Posted September 14, 2009 Share Posted September 14, 2009 ...but If I want the 2nd one to be 10 will putting 10 into AUDF4 at any point during that 2nd countdown change the internal countdown or will it only fetch my 10 when it hits IRQ2. That's clear. The answer is positive. When writing to any AUDFn you're 'buffering' the new countdown value. So, every channel n has an AUDFn register and an internal timer n register. We can change the content of the AUDFn register any time. Quote Link to comment Share on other sites More sharing options...
atariksi Posted September 14, 2009 Share Posted September 14, 2009 I haven't followed or read this thread, but just from reading last few messages, I wanted to point out that you can just write the next delta scanline value (minus 1) into the frequency register without hammering STIMER. And you can basically guarantee you have one scanline time (including overheads). But unless I run with timer values of 0, once I enter the timer interrupt, the timer has already reset itself to it's AUDFx value and begun counting again ? No ? So me reseting it to a known value won't take effect until the *current* timer period has elapsed, which means you have to stick the correct AUDFx value in one interrupt ahead of where it's actually needed.. That's the impression I got from reading the docs and running on Altirra ? It only reloads from AUDFx when it underflows ? Which means that an interrupt can't instantly change the timer value, until the current period has elapsed.. Unless you hit STIMER.. It sounds like what you're saying is that once the Timer underflows and generates an interrupt the internal counter isn't reloaded until the next 15Khz tick, during which time I can reload it without needing to write to STIMER ? Which isn't the behaviour I saw in Altirra.. But I guess I can't take anything for granted until I get running on real hardware.. I have always restarted timers (15Khz) to new values without using STIMER strobe. The 15Khz timer is at a fixed value until you go past a scanline worth of time. You can reload AUDFx anytime. Here's code that works perfectly find on real A8 hardware (also has code to initialize 15Khz timer at different points on scanline and some calorie-free (cycle free) sprites to serve as rulers so you can see at which point IRQ is taking place): ;*** ATIRQ.asm: Atari Timer IRQs for raster-type interrupts by Krishna Software Inc. (XL/XE). This places ;*** IRQ at exact point on screen using a 15Khz interrupt. ;*** There are three CLKs which can be used by either 8 or 16 bit divisors as controlled by 53768. ;*** The 15.6999Khz CLK and 63.921Khz CLK can be turned off via 53775 but 1.78979Mhz CLK is always on. ;*** The 15.6999Khz CLK is 1.78979Mhz/114 and gives the scanline interrupt at same cycle on scanline. ;*** The 63.921Khz CLK is 1.78979Mhz/28 and does not divide evenly into 29868 cycles/frame so cannot be used ;*** for color clock accurate or scanline accurate interrupts. This program also attempts to write IRQ vector ;*** directly at 65534/65535 by disabling ROM for XL/XE series (should have no effect on Atari 400/800). TIMERFREQLSB = 53760 TIMERFREQMSB = 53762 WSYNC = 54282 VCOUNT = 54283 DOSVEC = 10 CASINI = 2 WARMSTART = 58484 VMIRQ = 534 ;hardware irq ptr ORG = 600h ;DW 0FFFFh ;DW StartAdr ;DW LastOffset-1 DB 0,3 ;# of sectors to load 1..255 DW ORG DW StartAdr Rts StartAdr: Lda #MyReset,L Sta CASINI Lda #MyReset,H Sta CASINI+1 Lda #0 Sta 580 Lda #2 Sta 9 Jmp WARMSTART MyReset: Lda #2 Sta 9 Lda #MyReset,L Sta CASINI Lda #MyReset,H Sta CASINI+1 Sei Lda #0 ;no VBIs nor DLIs for maximum performance Sta 54286 Sta 54287 Sta 53774 ;disable all IRQs Sta 54272 ;turn off screen Lda #0 ;turn off serial/KB/15&63Khz CLK Sta 53775 ; 1.79Mhz CLK is always on Nop Sta WSYNC Lda 54287 Lda 54287 Lda 54287 Lda 54287 Lda 54287 Lda 54287 Lda 54287 ;7*4 = 28 cycles so far Lda 0 ;3 cycle delay Nop Nop Nop ;rem above 3 NOPs to get IRQ trigger point to left of screen Nop Nop Lda #3 Sta 53775 ;turn on clocks with 15Khz/63Khz clock at new phase at cycle #9 Lda #254 Sta 54017 ;disable ROM and BASIC for XL/XE series via PORTB Lda #TimerIRQ,L ;general IRQ routine but we use only for timer #2 Sta VMIRQ Ldy #TimerIRQ,H Sty VMIRQ+1 Sta 65534 Sty 65535 Cpy 65535 Beq ROMVectorSet Lda #IdleLoop,L Sta SelfModifyThis+1 ;Remove 5 cycles from background task (for Jmp [534]) Lda #IdleLoop,H Sta SelfModifyThis+2 ROMVectorSet: ROMVectorSet: ;Lda #64 ;Bit 6 = channel 1 @1.79Mhz, bit 5 = channel 3 @1.79Mhz ;Sta 53768 ;bit 4 = channel 1+2 to 16-bit divisor, bit 3 = channel 3+4 to 16-bit Lda #1 Sta 53768 ;bit 0=1 for 15.6999Khz clock else it uses 1.79Mhz/28 (64Khz) Lda #0 Sta 53760 Lda #1 ;1,2,4=timer interrupts Sta 53774 ;enable IRQ #1 Sta 16 ;shadow Lda #80 Sta 53248 ;unrem to show sprite using 0 CPU cycles and 0 DMA cycles Lda #90 Sta 53249 Lda #100 Sta 53250 Lda #$AA Sta 53261 Sta 53262 Sta 53263 Sta 53264 Lda #0 Sta 53256 Sta 53257 Sta 53258 Sta 53259 Lda #32 Sta 53275 Lda #10 Sta 53266 Lda #12+80 Sta 53267 Lda #14+160 Sta 53268 ALN 8 Lda #65 NotMidScreen: Cmp VCOUNT Bne NotMidScreen ;CF=1 when A=65 Sta WSYNC Sta WSYNC Nop CLI Sta 53769 ;start timer counter ;CLI ;Nop ;delay does NOT affect 15.699Khz IRQ ;Nop ;Nop ;Nop ;Inc 54278 ;Inc 54278 ;Lda #34 ;Sta 54272 Sec IdleLoop: Jmp IdleLoop ;(29868 cycles in NTSC frame - 9*262 for Refresh = 27510 cycles so to keep the IRQ ; stable, cycles must be aligned to 27510 including IRQ routine). For PAL frame, use ; 312*114 = 35568 - 312*9 = 32760 cycles.) ;(27510 factors to 2*5*7*3*131) ;Lda 53767 ;Sta 53274 ;Lda 53767 ;Sta 53274 ;Lda 53767 ;Sta 53274 ;Lda 53767 ;Sta 53274 ;Lda 53767 ;Sta 53274 ;Lda 53767 ;Sta 53274 ;Lda 53767 ;Sta 53274 ;Nop ;Jmp IdleLoop Lda 53764 Sta 53274 Lda #48 Sta 53274 Lda #80 Sta 53274 Lda #128 Sta 53274 Lda #144 Sta 53274 Lda #160 Sta 53274 Lda #176 Sta 53274 SelfModifyThis: Jmp Idle1 Idle1: Nop Jmp IdleLoop ;*** H/W does jmp [65534] (7 cycles) and OS does a CLD, and JMP [534] for 2+5 = 7 cycles. ;*** Below routine 47 cycles+7 = 54 cycles. On Old OS (like on Atari 800), there's no CLD so unrem the NOP. ;*** 53774 has bit set to 0 for that particular interrupt that occurred. TimerIRQ: Pha ;3 cycles Lda #255 Sta 53274 Asl 53774 Lda #1 Sta 53774 ;send ack to timer irq Sta 53274 ;change register (like color for example) NxtIRQ: Lda #130 Sta 53760 ;Ror NxtIRQ+1 Pla ;4 cycle restore of A Rti ;6 cycles ;LastOffset: DW 2e0h,2e1h,ORG 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.