In
trunk r4797 I changed the way g7x gets the active raw buffer. I suspect this applies to other digic 6 cameras (and maybe other recent cameras), so I'm posting a new thread.
BackgroundIn the past, cameras had one or two raw buffers which were at fixed addresses and used in almost every shooting mode.
G7X uses up to 3 buffers, with the addresses and number varying depending on shooting mode, continuous shooting setting, and Canon raw setting.
ImplementationInstead of trying to trying to identify every permutation and reproduce the logic in hook_raw_image_addr, I decided to try to find where the Canon firmware stores the actual raw buffer it is using for a given shot.
I found a function sub_fc152772 (addresses refer to 100d but are mostly the same in other g7x subs) which I've called captseq_raw_addr_init
It's called in both the "quick shoot" and normal code paths, although it may be skipped in some cases. It appears to store the current raw address in struct pointed to by r1 (at offset 0x5c in the case of g7x)
The parameter in r0 is the value that ends up in the active_raw_buffer variable, generated by the preceding call to sub_fc152724. The actual raw address (along with some other values) appears to come from sub_fc184310
The struct in r1 is not at a fixed address, so cannot be accessed with a simple stubs_min define. In the normal shoot case, it's pointed to by the message struct, while in quick shoot it seems to come from somewhere else. In either case, it varies between calls.
To use this, I added a new function captseq_raw_addr_init_my which replaces the call to captseq_raw_addr_init, and stores the current address in the global variable current_raw_addr. This in turn is used by hook_raw_image_addr
Testing a lot of different scene modes, continuous settings etc, the address obtained this seems to be correct.
This allows using CHDK raw with many mode / setting combinations where Canon raw is disabled, and allows rawop / raw histogram to work correctly.
IssuesFrom the disassembly, it appears there may be cases where captseq_raw_addr_init could be skipped. I didn't find any with extensive logging, but I certainly didn't try every permutation.
The raw address is only valid for a given shot, but is stored in a global where it could be used later. To avoid this, I added clear_current_raw_addr, which is called both at the start of pre-shoot, and after the raw hook. This isn't 100% effective, because there are currently some code paths that don't hit the raw hook. DNG reversing makes using an incorrect raw potentially very bad.
At the moment, if the raw address isn't valid, hook_raw_image_addr falls back to the old code, because CHDK assumes a raw address is always available. AFAIK benchmark is the only thing that assumes it can get a raw address outside of shooting. It might make more sense to use an arbitrary uncached address (e.g. MEMBASEADDR | CAM_UNCACHED_BIT) and make hook_raw_image_addr return NULL when valid raw isn't available.
The code in raw.c isn't set up deal with hook_raw_image_addr returning null either, so if captseq_raw_addr_init was skipped in some case, it would fail badly. It probably wouldn't be too hard to make it skip all the buffer stuff in this case though.
On previous ports with 2 raw buffers, it the second buffer was used to speed up DNG reversing. There is no obvious way to support this with the new method.