Jump to content
IGNORED

PM multiplexor


Heaven/TQA

Recommended Posts

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...

Link to comment
Share on other sites

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 ;)

Link to comment
Share on other sites

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 ;)

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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 by andym00
Link to comment
Share on other sites

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

Link to comment
Share on other sites

 

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 by PeteD
Link to comment
Share on other sites

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 by PeteD
Link to comment
Share on other sites

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..

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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 ?

Link to comment
Share on other sites

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 by PeteD
Link to comment
Share on other sites

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..

Link to comment
Share on other sites

...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).

Link to comment
Share on other sites

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

Link to comment
Share on other sites

...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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...