Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - coutts

Pages: 1 ... 9 10 [11] 12 13
251
General Development / Re: 600D Audio Controls?
« on: July 24, 2012, 04:33:38 PM »
I may be able to help with this, i worked with the 500d audio chip a lot last year. Is there a factory documentation for the audio chip? This is what I used when working on the 500d as it tells you exactly what registers to modify for certain features.

Here's some tips:
Code: [Select]
static inline void
audio_ic_set_mgain(
                                   unsigned             mgain
                                   )
{
        unsigned sig1 = audio_ic_read( AUDIO_IC_SIG1 ); // Read the value of register 'Signal Select 1', store it in sig1.
                                                                                                        // We will use this later when we set individual bits on/off for
                                                                                                        // different gain values.
    unsigned sig2 = audio_ic_read( AUDIO_IC_SIG2 ); // Read the value of register 'Signal Select 2', store it in sig2.
   
       
    // Setting the bits for each possible gain setting in the 500d, individually so it's easy to understand.
        //              - 24 hours ago I didn't even understand how to configure the audio chip, so I think this is pretty good
        //                for my first implemenation :)
        //
        // Basically, different gain settings use different combinations of the MGAIN0, MGAIN1, MGAIN2, and MGAIN3 bits being set/cleared.
        // Here's a reference table for the settings, taken from the pdf linked from line 201 above:
        //
        //---------------------------------------------------------
        // MGAIN3  |  MGAIN2  |  MGAIN1  |  MGAIN0 ||  Gain Value
        //---------------------------------------------------------
        //    0    |     0    |    0     |    0    ||     0 dB
        //    0    |     0    |    0     |    1    ||   +20 dB (default setting)
        //    0    |     0    |    1     |    0    ||   +26 dB
        //    0    |     0    |    1     |    1    ||   +32 dB
        //    0    |     1    |    0     |    0    ||   +10 dB
        //    0    |     1    |    0     |    1    ||   +17 dB
        //    0    |     1    |    1     |    0    ||   +23 dB
        //    0    |     1    |    1     |    1    ||   +29 dB
        //    1    |     0    |    0     |    0    ||    +3 dB
        //    1    |     0    |    0     |    1    ||    +6 dB
        //---------------------------------------------------------
        //
        // So my switch statement below looks at the value of the mgain variable (which is changed by the gain setting in the ML menu),
        // and sets the correct combination of bits accordingly.
        //
        // &= ~(1 << x) means clear bit x
        // |= 1 << x means set bit x
        //
        // That should be enough to bring anybody up to speed on things.
        // -Coutts
    switch (mgain)
    {
        case 0: // 0 dB
            sig1 &= ~(1 << 0); //clear bit1 [MGAIN0] in register 'Signal Select 1'
            sig1 &= ~(1 << 1); //clear bit2 [MGAIN2]    "
            sig1 &= ~(1 << 3); //clear bit3 [MGAIN3]    "
            sig2 &= ~(1 << 5); //clear bit4 [MGAIN1] in register 'Signal Select 2'
            break;
           
        case 1: // 3 dB
            sig1 &= ~(1 << 0); //clear MGAIN0
            sig1 &= ~(1 << 1); //clear MGAIN2
            sig1 |= 1 << 3;        //set MGAIN3
            sig2 &= ~(1 << 5); //clear MGAIN1
            break;

more here:
https://bitbucket.org/hudson/magic-lantern/src/77f7db1f8a6e/platform/500D.111/audio.c.500d_under_construction.c

252
Reverse Engineering / Re: prop_register_master
« on: July 23, 2012, 02:57:52 PM »
This should all be identical for DryOS cameras as well

Structs for reference

Stubs for reference from 5d.111 firmware:
TaskClass__TryPostEvent: 0xFFB22AFC


prop_register_slave
struct created every time prop_register_slave is called (only local, it's not used after the call).
Code: [Select]
prop_register_slave  local_struct (len: 0x14)
off_0x00     prop_list_array     //~ len: 4 * arg1(property list). property list is copied to this struct, used to pass to TryPostEvent.
off_0x04     arg1
off_0x08     arg2
off_0x0C     arg3
off_0x10     arg4                //~ arguments passed to prop_register_slave call

This call is what actually does something (post some event to PropMgr):
Code: [Select]
TaskClass__TryPostEvent(
  Manager->name,                   //~ "PropMgr"
  Manager_struct_ptr               //~ pointer to a manager's struct, ex: PropMgr pointer setup in Prop_Initialize from canon's startup_task
  0x4                              //~ not known, always 0x4 for prop_register_slave
  local_struct                     //~ struct outlined above
  0x4                              //~ always same as arg2? 0x4 for prop_register_slave
);





prop_register_master
struct created every time prop_register_master is called (only local, it's not used after the call).
Code: [Select]
prop_register_master  local_struct (len: 0x20)
off_0x00     arg0         //~ arg0 to prop_register_master, usually some property id.
off_0x04     unk_struct   //~ len: arg2. some stuff copied from arg1 to this struct, len of memcpy operation is arg2.
off_0x08     arg2
off_0x0C     arg3
off_0x10     arg4
off_0x14 arg5
off_0x18 arg6
off_0x1C arg7

Calls:
Code: [Select]
TaskClass__TryPostEvent(
  Manager->name,                   //~ "PropMgr"
  Manager_struct_ptr               //~ pointer to a manager's struct, ex: PropMgr pointer setup in Prop_Initialize from canon's startup_task
  0x1                              //~ not known, always 0x1 for prop_register_slave
  local_struct                     //~ struct outlined above
  0x4                              //~ different from prop_register_slave, not the same as arg2 this time. this one is 0x4.
);



Properties registered with prop_register_master:
0x80010002
0x80020002
0x80020003
0x80020004
0x80020006
0x80020007
0x80020008
0x80020009
0x8002000A
0x80030002
0x80030005
0x80030006
0x80030007
0x80030008
0x8003000D
0x8003000E
0x80030011
0x80030014
0x80030015
0x80040000

253
Reverse Engineering / prop_register_master
« on: July 23, 2012, 02:36:33 PM »
Has anyone figured out what this does / is used for yet?

254
General Development / Re: Compiling the installer FIR from source
« on: July 23, 2012, 02:04:19 PM »
Here is some info for packing FIR files for older cameras (mostly what I've dealt with in my time working on ML, no idea about newer cameras). It could give you an idea of what goes into it:

http://magiclantern.wikia.com/wiki/Packing_FIR_Files

It can be a lot of work to compile a new FIR just to test a new small change, so this is why we enable the bootflag in the camera and use an autoexec.bin file. It doesn't need to be signed like a FIR file, and boots automatically unlike a FIR file.

255
User Introduction / Re: Yo peeps
« on: July 21, 2012, 11:04:23 PM »
Welcome! I was the main developer of the 500d tree for a while before upgrading to a 5d. Glad you enjoy it :) the 500d was almost a dead port!

256
Share Your Videos / Re: G E N R E (Short Film)
« on: July 20, 2012, 09:55:26 PM »
Great.

You know, I had a Transcend 16gb card and it was just garbage for me, I wonder if a new card could fix your problems. Now my Transcend 16gb card will only format to 8gb in camera (odd, right?). I've since stopped using mine.

257
Reverse Engineering / Property Classes
« on: July 19, 2012, 11:46:38 AM »
Looking at some PropMgr states, I found some valuable info, names of different ranged properties. From VxWorks in 5dc v1.1.1:

0x1000000 range = TuneData
0x2000000 range = RingData
0x3000000 range = CustomData
0x4000000 range = PcData
0x5000000 range = WftData
0x80000000 range = FixData


important functions:
check_property_list__maybe: 0xFFAB9FA8 --> seems to check if a property passed as arg0 is valid (in one of the "prop lists").
PROPPAD_GetPropertyData: 0xFFAB6D5C --> arg0 is a property, it checks if it fits in one of the lists too maybe? this is where I found the names above.

258
As a test, I added the struct definitions to dryos.h and moved the state_object / state_transition definitions from stateobject.h to dryos.h to keep them all together. I printed out the contents of the PropMgr manager struct, and it all looks to be right, cool!

Quote
        #define PropMgr (*(struct Manager **)0xF508)

        bmp_printf(FONT_LARGE, 0, 0, "PropMgr Manager Struct");
        bmp_printf(FONT_LARGE, 0, 40, "name: %s", PropMgr->name);
        bmp_printf(FONT_LARGE, 0, 70, "taskclass_ptr: 0x%x", PropMgr->taskclass_ptr);
        bmp_printf(FONT_LARGE, 0, 100, "stateobj_ptr: 0x%x", PropMgr->stateobj_ptr);
        bmp_printf(FONT_LARGE, 0, 130, "debugmsg_class: 0x%x", PropMgr->debugmsg_class);
        bmp_printf(FONT_LARGE, 0, 160, "unk_struct_ptr: 0x%x", PropMgr->unk_struct_ptr);
        bmp_printf(FONT_LARGE, 0, 190, "stateobj_ptr2: 0x%x", PropMgr->stateobj_ptr2);
        bmp_printf(FONT_LARGE, 0, 220, "mgr_semaphore: 0x%x", PropMgr->mgr_semaphore);
        bmp_printf(FONT_LARGE, 0, 250, "stateobj_ptr3: 0x%x", PropMgr->stateobj_ptr3);
        bmp_printf(FONT_LARGE, 0, 280, "off_0x20: 0x%x", PropMgr->off_0x20);
        bmp_printf(FONT_LARGE, 0, 310, "off_0x24: 0x%x", PropMgr->off_0x24);
        bmp_printf(FONT_LARGE, 0, 340, "off_0x28: 0x%x", PropMgr->off_0x28);
        bmp_printf(FONT_LARGE, 0, 370, "off_0x2c: 0x%x", PropMgr->off_0x2c);





And look, you can even keep going deeper, like the TaskClass struct:
Quote
        #define PropMgr (*(struct Manager **)0xF508)
        bmp_printf(FONT_LARGE, 0, 0, "Manager Test");
        bmp_printf(FONT_MED, 0, 70, "PropMgr->taskclass_ptr->name: %s", PropMgr->taskclass_ptr->name);
        bmp_printf(FONT_MED, 0, 100, "PropMgr->stateobj_ptr->type: %s", PropMgr->stateobj_ptr->type);
        bmp_printf(FONT_MED, 0, 130, "PropMgr->stateobj_ptr->name: %s", PropMgr->stateobj_ptr->name);



So, what now?

Edit:
I have refined and published my findings to the repo, I added the structures to state-object.h as they all belong together. To hijack one of the managers or modules, simply follow how state object hijacking works.

Good news: at first sight looks like this is identical in DryOS so it can be used on newer cameras! In 500d.111 firmware:
Quote
CreateStageClass: 0xFF1A5E80
CreateTaskClass: 0xFF1A6824

More good news: the structures are the same size in both VxWorks and DryOS!

259
updated, analyzed some more. Please see latest commit in repository for changes:
https://bitbucket.org/hudson/magic-lantern/changeset/288809380c52

In 5dc v1.1.1:
Manager | ptr
  • GenMgr | 0x1B9C
  • EventMgr | 0x4EE8
  • FileCache | 0x4F1C
  • RscMgr | 0x4F28
  • DPMGR_T | 0x504C
  • DPOFMGR_T | 0x510C
  • TOMgr | 0x5910
  • FileMgr | 0x592C
  • PropMgr | 0xF508
  • DbgMgr | 0x101FC

Module | ptr
ShootCapture | 0x4E74
ShootDevelop | 0x4E78
ShootBlack | 0x4EA4
Fcreate | 0x4ED0
Fstorage | 0x4ED8
Rstorage | 0x4EE0
Fread | (seems to be initialized in 2 spots, no solid pointer for it, odd)
Fwrite | (same as above ^)
Factory | 0xD148

Whenever a StageClasss or TaskClass are created, they start a new instance of the StageClassTask or TaskClassTask, which seem to handle events. From the Module or Manager struct, we can call just about any function (like ChangeTaskPriority), or anything that needs any of the pointers / structs contained inside each Module/Manager. One thing I still do not know yet is how state changes happen. I know there is a handler function that looks at off_0x14, off_0x18, and off_0x1c in the StateObject struct, and has some algorithm to calculate what state to change to. I think Alex has this figured out though.

So, from these 2 groups, we can learn the names of every state machine, stage class, or task class in the camera. These 2 are at the top of the two "hierarchies", so this is as far back as we need to reverse-engineer. I think this is very important stuff, as it advances our knowledge of the low level event system that drives everything. I'll correct / update this as I learn more.

260
I spent about 6 hours today mapping these structures in VxWorks from the 5dc v1.1.1 firmware. They should be similar if not identical in DryOS as well. These all have to do with the event system, which is ultimately what I'm trying to understand / hijack. My end goal is the ability to inject whatever event(s) needed to trigger bulb exposures on the 5dc (since it lacks PROP_REMOTE_SW2).

I'm not really too sure how well I did with the data types, but I tried to put as many notes in as I could. I'll work on this more tomorrow and slowly refine what does what. Now I see things like TaskClass and StageClass in the firmware and I'm not so lost/scared looking at it :)

Hijacking a StageClass or TaskClass will be almost identical to how we hijack state objects, so won't be hard to do at all.

[see post below for updated one]

Feel free to contribute / discuss.

261
Camera-specific Development / Re: Canon 40D
« on: July 18, 2012, 06:29:52 PM »
I suggest you look at my initial project for the 5dc:
www.bitbucket.org/coutts/5dplus

Everything starts in entry.S. First use a dumper tool to extract the firmware image from a canon firmware update file (see the build_scripts/eos_tools_v11 folder in that project linked above). Use decrypt_fw and then dissect_fw to split the FIR up. See this wiki page for more details:
http://magiclantern.wikia.com/wiki/Packing_FIR_Files

After you analyze the firmware dump using a program like IDA Pro (or the free ARM Console created by Alex) to see how the camera boots/works, then attempt to boot a custom FIR file running user code. Use the assemble_fw perl script in the eos_tools directory to assemble a new FIR file with your usercode (compiled autoexec.bin) instead of canon's payload. The final step is to run decrypt_fw again on this fir to sign it for the camera to accept it. (Note: this step may or may not be necessary, depends on the camera. Try both if one doesn't work). Start by just blinking an LED or something basic to know your code runs. You don't need to boot the main firmware to blink an LED.

If 40d is similar to the 5dc, then you won't be able to run any practical code from a FIR (including calling the EnableBootDisk function or booting the firmware/camera) so you will need to write some code that scans the bootloader area (0xFFFF0000-0xFFFFFFFF) for function signatures to identify the read/write bootflag functions. This will allow you to set the camera's bootflag, to boot an autoexec.bin file with a prepared card, and development takes off from there (you will be able to boot the firmware and do anything from autoexec). I created this bootdisk code from the 350d method, using the 400d bootloader to find the signatures I needed. Only modification you will need is to change are the references to these:
Quote
read_bootflag = (ft_read_bootflag)0xFFFF8AE0;
write_bootflag = (ft_write_bootflag)0xFFFF89F0;
https://bitbucket.org/coutts/5dplus/src/e486f2e53796/bootdisk.c

The 5dc took me many hours to get going, I dumped many memory addresses through LED blinks in binary, you should be prepared to do the same. Here is some code that you can use to blink out the contents of a memory address if you know the red/blue LED addresses:
https://bitbucket.org/coutts/5dplus/src/a1cc964de4af/init.c

You can use this to write code to search for specific signatures of the read_bootflag and write_bootflag functions. Some signatures would be instructions like:
Quote
MOVEQ   R7, #0xF8000000
which is assembled and looks like this in memory:
Quote
0x03A0733E

Use the 5dc bootloader (I can send you it) to know what signatures you're looking for (unique instructions that would only appear in the read/write bootflag functions). After you find a signature and have a match at some spot in the BL area (0xFFFF0000-0xFFFFFFFF), use this address and search in reverse (going backwards in memory to lower addresses) until you find the nearest PUSH (STMFD) instruction, this will be the address of the start of the function so that you can call it / use it.



I'll just tell you the signatures to find.
First, for write_bootflag. Here is a small snippet from that function, the first 5 instructions:
Quote
ROM:FFFF89F0                 STMFD   SP!, {R4-R8,LR}
ROM:FFFF89F4                 MOV     R5, R1
ROM:FFFF89F8                 MOV     R4, #0
ROM:FFFF89FC                 CMP     R0, #0
ROM:FFFF8A00                 MOVNE   R7, #0xF8000000
If you were scanning memory, these 5 instructions would look like this(starting at 0xFFFF89F0 on the left and ending on 0xFFFF8A00 on the right):
Quote
0xE92D41F0 0xE1A05001 0xE3A04000 0xE3500000 0x13A0733E

So, look for the signature for the MOVNE R7, #0xF8000000 instruction, then once you find it, search backwards for the STMFD (push) instruction signature, and you will have located write_bootflag in the 40d bootloader. Chances are the functions will probably be identical, but take caution to verify at least 3 times that you have located the correct function and it seems the same / similar to the 5dc one (remember we are working blind here).


Now, read_bootflag. First 5 instructions look like:
Quote
ROM:FFFF8AE0                 STR     LR, [SP,#var_4]!
ROM:FFFF8AE4                 CMP     R0, #0
ROM:FFFF8AE8                 MOVNE   R3, #0xF8000000
ROM:FFFF8AEC                 ADDNE   R3, R3, #0x2000
ROM:FFFF8AF0                 MOVNE   R2, #0x40
And in memory would look like this (same thing as before, starting at 0xFFFF8AE0 on left and ending at 0xFFFF8AF0 on the right):
Quote
0xE52DE004 0xE3500000 0x3E33A013 0x12833A02 0x13A02040
Note: there isn't a STMFD (push) instruction in read_bootflag. The 400d bootloader is like this too, so chances are the 40d is as well.

NOTE: you may need to reverse endianness of the assembled instructions above to see them in memory, but maybe not, I can't remember :P


So, once you have located read_bootflag() and write_bootflag(), you will be able to really start developing. :) This may seem confusing, and I'm sorry, but I hope you will see how valuable this information is (I had to figure it all out on my own). The 350d people dumped the bootloader using a photo diode and the LED to blink the code in binary to a computer, I couldn't figure that out so I did it this way. Let me know if you have any questions, I can probably help a lot. Do you use gmail?

262
Camera-specific Development / Re: Canon 5D classic
« on: July 16, 2012, 04:00:35 PM »
Hi, awesome work you are doing with the 5DC. I am trialing ML on my 500D at work and its been great! I'd love to start time lapsing on the 5DC is it possible to just use this feature? Or shall I just bite the bullet and get a hardware intervalometer? I am going on holiday in 2 weeks and I'd like to do some time lapsing while I'm away.
intervalometer will work :)
I haven't released an autoexec.bin yet just because there is so much to fix yet. I am close though, don't worry.

All the nifty things sounds cool, but will it add AF microadjustment?

Still, can't wait to see it released : )
unfortunately no :( 5dc is far too old for this feature.

Hi,

this is great work in progress. I only registered to encourage you.
I have the 5D classic and love it. The only thing I wish would be an AutoISO function in P/Av/Tv mode (even if it is only between ISO 100 and 400), but of course, anything would be great.
I keep my fingers crossed that you manage soon.
Keep up the fantastic work,
Bests,
Chris
This may be possible, but first I need to work on getting ML running stable on the camera.

263
User Introduction / Greetings from USA
« on: July 15, 2012, 04:04:17 PM »
I just realized I've never made an intro on here, so here it is! My name is Andrew, I'm a 21 year old computer science major. I first discovered ML just over 1 year ago, and began speaking to A1ex. He has since taught me everything I know about how ML works / how to develop / port it. Before that I had no knowledge / understanding of embedded systems at all. I hadn't even heard of assembly language or any of that. Needless to say, I owe him (and the other developers like Indy) a lot. I began working on the 500d port last year, and eventually brought it into the unified tree (it was a dead port with no active developer at the time, so I had to save it!).

Now I have sold my 500d and recently (a few months ago) bought a 5dc. I've been working to port ML to it and making good progress (check the New Ports section for the log).

I'm really happy that there is finally a central forum for all ML related things, so now the community can begin to grow. Looking forward to seeing how ML progresses over the coming months, have a nice day!


- P.S. am I still the only american involved here besides Trammel?

264
User Introduction / Re: G'day from Melbourne, Australia
« on: July 15, 2012, 04:00:46 PM »
Welcome to the forum! I think you will be very pleased with how powerful ML can be when put in the right hands :)

265
Camera-specific Development / Re: Canon 5D classic
« on: July 15, 2012, 03:57:32 PM »
Hi,
I wonder if trap focus will work when I have AF under AE lock button (under thumb), half shutter I have AE lock?

It is Custom Function -> position "04" value "1"
I still need to find a status pointer that indicates focus confirmation, but yes I believe it should still work regardless of that CFn value.

The hunt continues for shutter actuation counter too, searched about 1000 properties yesterday with no luck. HDR bracketing works now, but I need to find PROP_LENS to determine min/max aperture that ML can use. That will fix aperture setting. As it stands, intervalometer and hdr bracketing are the only 2 features that work.

And some disappointing news for focus patterns, I couldn't set any custom focus patterns using the property. Not sure if it's going to be possible now. It just reverted to 0 every time I set something (selecting no AF points). Weird.

266
General Chat / Re: Kicktarter for 5D MK III?
« on: July 13, 2012, 11:12:09 PM »
I think kickstarter could work, there is no need for a physical product or anything. I think kickstarter or indiegogo would work, but Indiegogo sounds like it would be more appropriate.

If you need someone in the US, i can help.

267
Camera-specific Development / Re: Canon 5D classic
« on: July 13, 2012, 06:46:17 PM »
Good news: custom AF points may work for 5dc! Property seems to be the same from DryOS. Can anyone verify if the values are the same?


268
Camera-specific Development / Re: Canon 5D classic
« on: July 13, 2012, 02:01:32 AM »
Can you get the shutter count by printing out ioGlobalStdset?

void MyGlobalStdSet ()
{ int f1 = -1;
   while (f1==-1) { f1=FIO_CreateFile("A:/STDOUT.TXT"); if
(f1==-1) SleepTask(100); } ioGlobalStdSet(1,f1);}

NSTUB (0xFFB4A358, ioGlobalStdSet);
Didn't seem to print anything to that file, interesting. I know there are some printf statements in the ROM, are we using the right arguments for this?

edit:
could be related to this (taken from vxworks documentation):
Quote
All tasks will use this new assignment when doing I/O to stdFd, unless they have specified a task-specific standard file descriptor (see ioTaskStdSet( )).
http://www-kryo.desy.de/documents/vxWorks/V5.4/vxworks/ref/ioLib.html#ioGlobalStdSet

269
Camera-specific Development / Re: Canon 5D classic
« on: July 11, 2012, 02:14:14 AM »
guess there isn't a pointer in the first 0x1000000 of memory like in the 400d. hmm, the hunt continues

270
Hardware and Accessories / Re: Lens upgrade for 18-55 (600D)
« on: July 11, 2012, 12:44:09 AM »
I've had a lot of good luck with sigma lenses. For a crop body like the 600D, I suggest the Sigma 30mm f/1.4. I posted this same response in that other thread, so refer there to see sample pictures to see how it looks on a crop body :)

271
Camera-specific Development / Re: Canon 5D classic
« on: July 11, 2012, 12:24:48 AM »
For the Shuttercountvalue-Topic:   Wouldn't it be possible to dump the whole memory, make a picture, dump again and compare both dumped images? There should be one register altered, but this is just one guess.
the property region of memory can't be observed, it just dumps an empty file. I've found anything past 0x1000000 is invisible to dumps (memory layout is different than dryos). In 400plus they just use a simple pointer in memory to read the shutter value.

I could try that, but I don't have something to diff the 2 dumps. Anybody want to write up a python script? :D

272
General Development / Re: ML credits (needs updating)
« on: July 08, 2012, 03:53:52 AM »
Trammel hasn't quit, I think he is just busy with other projects. Probably same for AJ.

273
General Development / Re: Inside the 650d
« on: July 08, 2012, 03:52:02 AM »
very cool

274
Camera-specific Development / Re: Canon 5D classic
« on: July 06, 2012, 11:39:15 PM »
short term is a no for shutter count. I can't find the property for it yet. Feel free to help me hunt it down :)
But the fact that canon can check the shutter count at its service centers tells me that there is a property recording it somewhere.

Made some progress today: ML is now detecting half press shutter finally :D
I had to hijack a state object (EMState) to see when the shutter was pressed. This is because for whatever reason, only an event for halfshutter unpress is sent by the GUI task. So I had to improvise.


Next I need to find focus confirmation, that will make Trap Focus work.
For HDR / bulb timer I need to find a way to trigger full press of the shutter (PROP_REMOTE_SW2 isn't in the 5dc).
For custom AF patterns I need to find the property for the focus points.


Progressing nicely :)

275
General Development / Re: Design proposals for future ML interface
« on: July 05, 2012, 04:37:27 AM »
well, count the 5dc out for any change like this :( (there's only 16 colors total in the 5dc).

looks cool though, make it happen! :)

Pages: 1 ... 9 10 [11] 12 13