It is currently Mon Sep 16, 2019 1:45 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 116 posts ]  Go to page Previous  1 ... 4, 5, 6, 7, 8
Author Message
PostPosted: Mon Aug 26, 2019 6:20 pm 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 1003
I've released a wifiboot update, more on that here: viewtopic.php?f=23&t=18065&start=60#p242088 I hope it's working better with existing 3DS bootloaders now. Reconnection on warmboot should be now also faster.

The diag3ds tool is also updated,
Attachment:
diag3ds.ZIP [70.41 KiB]
Downloaded 16 times
the RW test currently doesn't work well, but the Initial Values test does check some more memory mapped registers, and some non-memory mapped ones (like CPSR and P15 registers). It's possible that a handful of values are wrong or unstable and show errors when they shouldn't, but most should be correct. It's now also testing a few New3DS registers (which will probably trigger many errors on Old3DS). The source code with the register values lists is also inclulded, maybe that lists can be useful for emulators or bootloaders.

_________________
homepage - patreon


Top
 Profile  
 
PostPosted: Thu Aug 29, 2019 1:06 pm 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 1003
The New3DS has something called "MVD" (my current theory is that that stands for Movie Decoder or so).
The value 67312398h in register [10207000h] appears to be known as "HW_ID" for linux/android "VPU SERVICES".
Searching for that two strings gives this source code http://git.jp.linux-rockchip.org/cgit/r ... 0dc086a0d1 which in turn contains 6731h (the upper 16bit of the 67312398h value).
So I guess the "MVD" is identical to that Rockchip hardware (whatever that is). Could that be right? Or are there already other details or datasheets known for that hardware?

_________________
homepage - patreon


Top
 Profile  
 
PostPosted: Sat Sep 07, 2019 11:52 am 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 1003
I am currently examining the GPU framebuffer setup registers. They consist of several 12bit H/V position settings for the usual things like sync/left/right border/display start/end, plus some control/status registers.

The difficult part is the interrupt feature, there are 7-8 interrupt modes. The default mode is simple: It does just trigger one IRQ per frame (at a selected horizontal location).
The other modes can trigger multiple IRQs per frame (somewhere within the IRQ start/end positions; if they are setup properly, or fail to work; if the IRQ position settings are wrong).
I haven't really figured out how to use those special IRQ modes, at best I get them to trigger some IRQs in a wanted range (and then followed by either no further IRQs at all, or endless IRQs in an unwanted/unstoppable range).

Official datasheet or other docs would be nice to have. Is there anything available?
The registers should look about as shown below - does that I/O map look familar to anybody?.
Caution: Horizontal and Vertical may be swapped in datasheets (because the 3DS screens are mounted rotated by 90).

Code:
  10400400h 100h Framebuffer Setup "PDC0" (top screen)
  10400500h 100h Framebuffer Setup "PDC1" (bottom screen)
  PDC = "PICA Display Control" or so?

  10400400h/10400500h - V-total-1                 ;1C2h       ;\
  10400404h/10400504h - V-lower-border-end        ;0D1h       ;
  10400408h/10400508h - V-irq?                    ;1C1h       ;
  1040040Ch/1040050Ch - V-upper-border-end        ;1C1h       ; V
  10400410h/10400510h - V-sync-start (?)          ;000h/0CDh  ;
  10400414h/10400514h - V-sync-end                ;0CFh       ;
  10400418h/10400518h - V-lower-border-start      ;0D1h       ;
  1040041Ch/1040051Ch - V-irq?                    ;1C1h       ;
  1040041Eh/1040051Eh - V-irq?                    ;1C5h       ;/
  10400420h/10400520h - V-prepadd?                ;000h       ;-V
  10400422h/10400522h - V-?                       ;001h       ;-V
  10400424h/10400524h - H-total-1                 ;19Dh       ;\
  10400428h/10400528h - H-left border end         ;002h/052h  ;
  1040042Ch/1040052Ch -    ?                      ;192h       ;
  10400430h/10400530h - H-right border end        ;192h       ; H
  10400434h/10400534h - H-SYNC start              ;192h/04Fh  ;
  10400438h/10400538h - H-SYNC end?               ;001h/050h  ;
  1040043Ch/1040053Ch - H-left border start       ;002h/052h  ;
  10400440h/10400540h - H-IRQ-1 end               ;192h       ;
  10400442h/10400542h - H-IRQ-2 start             ;193h       ;/
  10400444h/10400544h - V-irq??                   ;000h       ;-V?
  10400448h/10400548h - Screen Vsync/Hsync type?
  1040044Ch/1040054Ch - Screen Border color
  10400450h/10400550h - Vertical current position (R)
  10400454h/10400554h - Horizontal current position (R)
  10400458h/10400558h - Unused (0)
  1040045Ch/1040055Ch - V-display area size       ;0F0h       ;-V
  1040045Eh/1040055Eh - H-display (no effect)     ;190h/140h  ;-H
  10400460h/10400560h - V-lower-border-middle?    ;0D1h       ;\V
  10400462h/10400562h - V-upper-border-start      ;1C1h       ;/
  10400464h/10400564h - H-left border middle?     ;002h/052h  ;\H
  10400466h/10400566h - H-right border start      ;192h       ;/
  10400468h/10400568h - Framebuffer A first address (Left eye, or both eyes)
  1040046Ch/1040056Ch - Framebuffer A second address (Left eye, or both eyes)
  10400470h/10400570h - Framebuffer format
  10400474h/10400574h - Interrupt type
  10400478h/10400578h - Framebuffer select
  1040047Ch/1040057Ch - Readonly flags? maybe hblank/vblank/etc
  10400480h/10400580h - Color Lookup Table index (R/W)
  10400484h/10400584h - Color Lookup Table data (R/W)
  10400488h/10400588h - Unused (0)
  1040048Ch/1040058Ch - Unused (0)
  10400490h/10400590h - Framebuffer Horizontal Address Step
  10400494h/10400594h - Framebuffer B first address (Right eye, or unused)
  10400498h/10400598h - Framebuffer B second address (Right eye, or unused)
  1040049Ch/1040059Ch - V-IRQ?                    ;000h       ;-V?
  1040049Eh/1040059Eh - H-IRQ-1 start             ;192h       ;-H
  104004A0h/104005A0h - Unused (0's)

_________________
homepage - patreon


Top
 Profile  
 
PostPosted: Tue Sep 10, 2019 12:29 am 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 1003
If you want to have a good laugh, here is my description of the eight interrupt modes. If that description makes perfect sense to you then you have a much better understanding of the hardware than myself.
Code:
10400474h/10400574h - Interrupt Type
  0      Display Enable (should be 1) (0=Off/screen fades out, 1=On/normal)
  1-7    Unused (0)
  8-10   Interrupt Mode (5=OncePerFrame, 7=None, 0..4,6=Special) (see below)
  7-11   Unused (0)
  16     Unknown...?    (0=???, 1=Normal)
  17-31  Unused (0)
The default is Interrupt Mode 5 (which acts as normal framerate interrupt). The
other modes are barely useful and kinda confusing (and seem to require manually
resurrecting IRQs in case of oneshot/multishot IRQs, or manually stopping IRQs
in case of unwanted endless repeating IRQs).

Interrupt Mode 0,1,2,3 in "oneshot" variant:
  - Works only when V settings are [10400504h]<=[1040059Ch]
  - If so, triggers once at V=[10400520h] and H=[1040059Eh]
  - Thereafter, no further IRQs occur (unless/until setting request.bit18)
Interrupt Mode 0,2 in "multishot" variant:
  - Works only when [1040051Ch]<[1040051Eh] and [1040059Eh]<[10400528h]
  - If so, triggers at V=[1040051Ch] and H=[1040059Eh]..[10400528h]
  - Thereafter, no further IRQs occur (unless/until setting request.bit18)
Interrupt Mode 1,3 in "multishot/other" variant:
  - Unknown, Mode 1 was also observed to have "multishot" (don't remember how)
  - (and Mode 3 might have something similar, too)
  - Mode 3 was also observed "oneshot" at V=[10400544h],and H=[10400528h]
  - And/or Mode 3 at [1040059Eh]+2(!) ;or H=[10400540h]?
Interrupt Mode 4 (endless with exclusion)
  - Same as Mode 6, but EXCLUDING triggering at H=[10400540h]..[10400542h]
Interrupt Mode 5 (framerate interrupt)
  - Triggers at V=[10400544h] and H=[10400540h] (usually H should be at Hblank)
Interrupt Mode 6 (endless)
  - Triggers at V=[1040051Ch], and H=[1040059Eh]..and up
  - IRQ's are endless repeated at all further H's (up to including next frame)
  - One way to prevent endless repeats is to set [1040051Ch]=1FFh (invalid)
  - Note: [1040051Ch] is latched somewhere (internally?)
  - (that latched value is NOT updated if [1040059Eh] is invalid)
Interrupt Mode 7 (interrupts disabled)
  - Doesn't trigger any IRQs.

For all IRQ H/V timings, mind that the display is drawn from left to right
(unlike normal top-to-bottom displays).
Note: Most of the V positions do actually trigger at V+1 (and perhaps similar
for H positions, though those are more difficult to measure).

But, one of the more recent findings might solve that mess: I was trying to set two registers to invalid values, [1040059Eh]=1FFh and [1040051Ch]=1FFh, hoping that that would stop endless repeating IRQs - and the results did depend on the write-order, ie. on which of the two registers was written first.
The new theory is that [1040059Eh] is the latch-point where changes to other registers are copied to internal registers. If that's right then IRQ modes may turn out to be much more straightforward (and all IRQs that had seemed to occur at [1040059Eh] were merely dirt effects caused by the latching).

PS. Are the Framerate and Dotclock already known for 3DS?
Asking especially because the upper screen can be used in horizontal hiresolution mode...
So I guess it must support double dotclock (or otherwise it would drop to half framerate).

_________________
homepage - patreon


Top
 Profile  
 
PostPosted: Wed Sep 11, 2019 3:22 am 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 1003
Yes, [1040059Ch] and [1040059Eh] is the "H/V-latching-position" where most or all other registers are latched into internal registers. When setting that position to an invalid location (exceeding htotal/vtotal) then the latching will never occur - and then one can overwrite all other H/V registers (and border color, and maybe some others) by garbage values, and the screen will netherleless keep showing an intact picture (using the old latched settings).

Knowing that, I could make a bit more sense of the interrupt modes
Code:
  Interrupt Mode 0:
  - Triggers here or there depending on H/V settings
  Interrupt Mode 1:
  - Triggers at V=[10400544h], H=[10400540h]               ;irq point
  - Triggers at V=[10400504h], H=[10400528h]..[10400566h]  ;picture area
  Interrupt Mode 2:
  - Triggers here or there depending on H/V settings
  Interrupt Mode 3:
  - Triggers at V=[10400504h], H=[10400528h]..[10400566h]  ;picture area
  Interrupt Mode 4 (in selected H's)
  - Triggers at V=[1040051Ch], and H=[10400542h]..[10400540h]
  Interrupt Mode 5 (framerate interrupt, usually at H=Hblank)
  - Triggers at V=[10400544h] and H=[10400540h]
  Interrupt Mode 6 (once on every H)
  - Triggers at V=[1040051Ch], and H=any
  Interrupt Mode 7 (interrupts disabled)
  - Doesn't trigger any IRQs.
Mode 4,5,6,7 are now looking right (and do no longer require manual tweaking for stopping unwanted interrupts).
Mode 0,1,2,3 do require manually ack/request next IRQ via bit18 (or bit17) in [10400578h], of those four modes, mode 1 and 3 are looking more or less right. But I have given up on mode 0 and 2.
Mode 0-3 can have the weirdest (dirt) effects when setting "parameter A>=B in relation to C with D<E and flag X=0", making it difficult to guess what those modes were supposed to be used for.

The specs for GPU screen setup registers at 104004xxh/104005xxh are now looking okay & and I am confident that the 3ds specs in gbatek are looking better and better than some months ago; if anybody is interested: I could upload a gbatek update - or otherwise I'll keep working and upload it some months later after more findings.
Hmmmm, next it might make sense to look at the "LCD screen" registers at 10202xxxh as they are somewhat related to the above "GPU screen" registers... and maybe one of them does allow to configure the dotclock.

_________________
homepage - patreon


Top
 Profile  
 
PostPosted: Wed Sep 11, 2019 4:01 am 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 1003
Btw. while looking at the 10202xxxh registers, the reminds me of the all-time biggest unknown 3ds thing. Most hardware components have a similar looking set of unknown registers which contain values 0C84h, 0840Ch, 480Ch, C048h on power-up, the four values are 8 bytes apart, and their R/W mask is CCCCh. What are those registers used for ???

Ie. these registers:
10102100h (20h bytes) Y2R
10110100h (20h bytes) LGYFB0
10111100h (20h bytes) LGYFB1
10202260h (20h bytes) LCD0
10202A60h (20h bytes) LCD1
10132100h (20h bytes) MVD
and maybe more

My first guess would be byte-order for RGBA values... but that would require only one 4-digit value, not four such values.

_________________
homepage - patreon


Top
 Profile  
 
PostPosted: Wed Sep 11, 2019 3:40 pm 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 1003
That LCD registers don't seem to be doing anything useful/interesting...

3DS Video LCD Registers
This seems to be an interface between GPU video output and actual LCD screens. The registers allow to control backlight brightness and to set a forced blank color. Some other registers seem to be also affect backlight brightness (or pixel brightness?); and maybe some do affect internal voltages or internal backlight PWM timings?

The bootrom error screen initializes only a few of these registers (and leaves the others at their power-up defaults). Many of the uninitialized registers seem to have no effect on the visible picture, even when setting/clearing all bits; some of them affect the brightness of the pixels or backlight (but only if CtrlFlags.bit0=1).

Code:
General LCD Control Registers
  Physical  Size R/W       Name
  10202000h 4    00070007h reportedly Parallax barrier enable (uh, in 2x3bit?)
  10202004h 4    FFFFFFFFh Whatever, should be 0A390A39h
  10202008h 4    (R)       Whatever, readonly (R) (bit0=top screen mode?)
  1020200Ch 4    00010001h Video Disable Bits (bit0/16=top/bottom disable?)
  10202010h 4    00001F0Fh Whatever, usually 00000900h
  10202014h 4    00000001h Video Enable Bit (bit0)
  10202018h 1E8h (0)       Unused (0) ?
  10202200h 600h ...       LCD Configuration for Top Screen (see below)
  10202800h 200h (0)       Unused (0) ?
  10202A00h 600h ...       LCD Configuration for Bottom Screen (see below)
  10203200h 40h  (0) ???   reportedly LCD related, in DSP area ??????

LCD Configuration for Top/Bottom Screen
  Top/Bottom Addr     Size R/W
  10202200h/10202A00h 4    00000301h CtrlFlags
  10202204h/10202A04h 4    01FFFFFFh Forced Blank Color
  10202208h/10202A08h 8    (0)       Unused (0) ?
  10202210h/10202A10h 4    000003FFh ? (default=0)    ;\
  10202214h/10202A14h 4    000003FFh ? (default=3FFh) ; darker when all zero
  10202218h/10202A18h 4    000003FFh ? (default=0)    ; (if CtrlFlags.bit0=1)
  1020221Ch/10202A1Ch 4    000003FFh ? (default=3FFh) ;/
  10202220h/10202A20h 4    000001FFh ? (default=100h) ;-
  10202224h/10202A24h 4    000000FFh ? (default=0)    ;\
  10202228h/10202A28h 4    000000FFh ? (default=0)    ;
  1020222Ch/10202A2Ch 4    000000FFh ? (default=0)    ;/
  10202230h/10202A30h 4    001F000Fh ? (default=4)    ;-
  10202234h/10202A34h 4    (0)       Unused (0) ?
  10202238h/10202A38h 4    000000FFh Last same entry in 10202400h (FFh=AllSame)
  1020223Ch/10202A3Ch 4    000000FFh ? (default=FFh)
  10202240h/10202A40h 4    000003FFh Backlight ;based on register 244h.low10bit
  10202244h/10202A44h 4    FFFFF3FFh Backlight?;LSBs: backlight? MSBs=flags?
  10202248h/10202A48h 8    (0)       Unused (0) ?
  10202250h/10202A50h 4    00FFFFFFh ? (default=0)    ;\brighter if 2nd=FFFFFFh
  10202254h/10202A54h 4    00FFFFFFh ? (default=0)    ;/(if CtrlFlags.bit0=1)
  10202258h/10202A58h 8    (0)       Unused (0) ?
  10202260h/10202A60h 4    0000CCCCh ? (default=0C84h);\
  10202264h/10202A64h 4    (0)       Unused (0) ?     ;
  10202268h/10202A68h 4    0000CCCCh ? (default=840Ch); the usual unknown stuff
  1020226Ch/10202A6Ch 4    (0)       Unused (0) ?     ; as everywhere else
  10202270h/10202A70h 4    0000CCCCh ? (default=48C0h); (eg. as in YuvToRgb)
  10202274h/10202A74h 4    (0)       Unused (0) ?     ;
  10202278h/10202A78h 4    0000CCCCh ? (default=C048h);
  1020227Ch/10202A7Ch 4    (0)       Unused (0) ?     ;/
  10202280h/10202A80h 24h  000000FFh ? (default=0)    ;-9 words (8th=brighter)
  102022A4h/10202AA4h 4Ch  (0)       Unused (0) ?
  102022F0h/10202AF0h 4    (-R-)     ? (R)            ;\initially 00h, but can
  102022F4h/10202AF4h 4    (-R-)     ? (R)            ; be FFh when screens
  102022F8h/10202AF8h 4    (-R-)     ? (R)            ;/are on?
  102022FCh/10202AFCh 4    (0)       Unused (0) ?
  10202300h/10202B00h 100h 00FFFFFFh New3DS only: LCD calibration array?
  10202400h/10202C00h 400h 000003FFh Backlight related array, used by bootrom

_________________
homepage - patreon


Top
 Profile  
 
PostPosted: Thu Sep 12, 2019 11:41 am 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 1003
Two quick questions...

Floating point unit
The 3ds has floating point hardware, doesn't it? Is that accessed via coprocessor opcodes? What is the best document for the 3ds floating point hardware?
Oh, and slightly unrelated: nds/dsi did support integer sqrt/divide, but that feature seems to have been dropped in 3ds?

Operating system
I know that there are SVC (aka SWI) functions, but they seem to cover only stuff like thread creation. I assume that there are also OS functions for file IO and perhaps even GUI functions? I have spotted docs with command numbers or function numbers for OS functions... but how would one invoke such a function number?
A short description for getting started on using OS functions would be nice! Or some small binary and/or sample source code for something like file io.

_________________
homepage - patreon


Top
 Profile  
 
PostPosted: Thu Sep 12, 2019 3:39 pm 
Offline

Joined: Tue Jun 21, 2016 2:43 pm
Posts: 14
nocash wrote:
Operating system
I know that there are SVC (aka SWI) functions, but they seem to cover only stuff like thread creation. I assume that there are also OS functions for file IO and perhaps even GUI functions? I have spotted docs with command numbers or function numbers for OS functions... but how would one invoke such a function number?
A short description for getting started on using OS functions would be nice! Or some small binary and/or sample source code for something like file io.

Disclaimer: I have never worked with the 3DS, but I do know how it works on the Switch, and the Switch kernel was based on the 3DS one, so they are pretty similar.

They are invoked by using the SendSyncRequest SVC (this is SVC number number 0x32 according to 3dbrew). First, you need to get the session handle for the service you want to communicate with. You can do that by calling the GetServiceHandle function on the Srv (Service Manager) service. This handle can be then used to send messages to the service by using SendSyncRequest. As the name implies, this is a synchronous request, so the calling thread will be put into wait state, and execution is resumed on that thread only when the response to your request is sent back.

Inter-process Communication (IPC) messages:

Communication with services is done with the use of messages. They store things like the command number of the function you want to call, the parameters passed to that function, and also other related information (such as possible buffers also passed to the function, handles etc). Similary, response messages are written at the same place (they overwrite the request message) and use a similar structure. This mechanism allows processes to communicate with each other on the 3DS OS.

The message that is sent to the service should be stored on the Thread Local Storage (TLS), a per-thread 0x200 bytes memory region reserved by the kernel on thread creation. The IPC message is always written at offset 0x80 within the TLS. At the server side, messages can be received by using the ReplyAndReceive SVC (this one is not normally accessible for applications, only the services should use it to reply IPC messages). ReplyAndReceive, as the name implies, is responsible for doing 2 things. First, it replies a request that was previously processed, and then it picks one incoming message on the queue for processing. If the queue is empty, then it simply waits for a message to arrive, during that time the thread will be in wait state.

The kernel is responsible for copying the request messages from the client to the server, and copying reply messages from the server to the client. They are both written at the same address (TLS + 0x80), and the reply message will simply overwrite the request message.

When SendSyncRequest returns, you're supposed to read the reply from the TLS. Normally, it will contain a result code, and depending on what you called, it may also contain more data after that. For some functions, you're also supposed to pass buffers (basically, just a address and size) on the request, where you pass large data to the function, or it can also be used by the service function to write large data that will be returned to you.

Simplified process:

To sum it up, the process is basically like this for invoking a service function:
- Call the ConnectToPort SVC, and pass on name "srv:" to get a handle for the SRV service. (You only need to do that once, you can then store the handle somewhere for later use).
- Call Srv GetServiceHandle function, using the above handle and SendSyncRequest, to get a session handle for the service you want to communicate with, writing the service name on the IPC message (that is the function parameter). The service names usually contains a `:` followed by a character that indicates privilege level. For example, `:u` stands for "user privilege". (You only need to do that once per-service).
- Call SendSyncRequest using the session handle returned from GetServiceHandle to call the desired function. The command number and parameters passed to the function should be written to the IPC message.
- After the above call returns, read the IPC message to get the response, including the result code and possibly other data depending on the function.

References:

The structure of the IPC messages is documented at:
https://www.3dbrew.org/wiki/IPC#Message_Structure
On that page, you can also find a brief explanation of sessions and ports (they are confusing, at least to me).

Documentation of the SVCs can be found at:
https://www.3dbrew.org/wiki/SVC#System_calls
The documentation is not complete however. And in a lot of cases, they are not clear about what the SVCs actually do.

Edit:

For file I/O, I believe you're looking for this service:
https://www.3dbrew.org/wiki/Filesystem_services


Top
 Profile  
 
PostPosted: Fri Sep 13, 2019 2:09 pm 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 1003
Many thanks! I had vaguely suspected that the OS services might accessed through SVC functions... but without your help I would have never guessed how that might work exactly.

_________________
homepage - patreon


Top
 Profile  
 
PostPosted: Sun Sep 15, 2019 11:51 am 
Offline

Joined: Fri Feb 24, 2012 12:09 pm
Posts: 1003
I have found the floating point hardware. It is called VFPv2 (Vector Floating-point). The ARM DDI 0360F (ARM11 MPCore (r2p0) document contains a relative large amount of (mostly useless) information about it, and says to look at the Architecture Reference Manual for the actual floating point opcode specs; there are a lot of different reference manual versions, but I guess that they meant this version: ARM DDI 0100I ARM Architecture Reference Manual (for ARMv6 wirh VFPv2).

I've checked opcode "FMRX r0,FPSID" (aka EEF00A10h), and it does return value 410120b4h (as described in ARM DDI 0360F), that should confirm that the VFPv2 hardware does really exist on 3DS. And with FPSID.bit20=0 it is apparently what they are occasionally calling the "D variant" (with single AND double precision support).

The Fxxxx floating point opcodes are aliases for CP10/CP11 copressor numbers; CP10 used for single, and CP11 for double precision instructions. There seem to be about 100 different opcodes, but many of them are probably (hopefully) just slightly different variations of each other.

_________________
homepage - patreon


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 116 posts ]  Go to page Previous  1 ... 4, 5, 6, 7, 8

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group