+
+#define PAGE_SIZE 0x1000
+
+#define CACHE_SYNC_INSTRUCTIONS 0x002 /* discard all cached instructions */
+#define CACHE_SYNC_WRITEBACK 0x004 /* write back but don't discard data cache*/
+
+WINBASEAPI BOOL WINAPI CacheRangeFlush(LPVOID pAddr, DWORD dwLength, DWORD dwFlags);
+WINBASEAPI BOOL WINAPI VirtualCopy(LPVOID lpvDest, LPVOID lpvSrc, DWORD cbSize, DWORD fdwProtect);
+
+void cache_flush_d_inval_i(void *start_addr, void *end_addr)
+{
+ int size = end_addr - start_addr;
+ CacheRangeFlush(start_addr, size, CACHE_SYNC_WRITEBACK);
+ CacheRangeFlush(start_addr, size, CACHE_SYNC_INSTRUCTIONS);
+}
+
+
+#if 0
+static void *mmap_phys(unsigned int addr, int pages)
+{
+ void *mem;
+ int ret;
+
+ mem = VirtualAlloc(0, pages*PAGE_SIZE, MEM_RESERVE, PAGE_NOACCESS);
+ if (mem == NULL)
+ {
+ lprintf("VirtualAlloc failed\n");
+ return NULL;
+ }
+
+ ret = VirtualCopy(mem, (void *)addr, pages*PAGE_SIZE, PAGE_READWRITE | PAGE_NOCACHE);
+ if (ret == 0)
+ {
+ lprintf("VirtualFree failed\n");
+ VirtualFree(mem, 0, MEM_RELEASE);
+ return NULL;
+ }
+
+ return mem;
+}
+
+static void munmap_phys(void *ptr)
+{
+ VirtualFree(ptr, 0, MEM_RELEASE);
+}
+
+// FB
+static int directfb_initialized = 0;
+static int directfb_addrs[2] = { 0, 0 };
+static void *directfb_ptrs[2] = { NULL, NULL };
+static int directfb_sel = 0; // the one currently displayed
+static volatile unsigned int *memregs = NULL;
+
+/*static void xdump(void)
+{
+ int i;
+ for (i = 0; i < 0x1000/4; i += 4)
+ {
+ lprintf("%04x: %08x %08x %08x %08x\n", i*4, memregs[i],
+ memregs[i+1], memregs[i+2], memregs[i+3]);
+ }
+}*/
+
+static int directfb_init(void)
+{
+ memregs = mmap_phys(0xac009000, 1);
+ if (memregs == NULL)
+ {
+ lprintf("can't access hw regs\n");
+ return -1;
+ }
+
+ // fake lock
+ Framework2D_LockBuffer(1);
+
+ // 0xAC00905C
+ directfb_addrs[0] = memregs[0x5c>>2];
+ lprintf("fb0 is at %08x\n", directfb_addrs[0]);
+
+ Framework2D_UnlockBuffer();
+
+ directfb_ptrs[0] = mmap_phys(directfb_addrs[0], (321*240*2+PAGE_SIZE-1) / PAGE_SIZE);
+ if (directfb_ptrs[0] == NULL)
+ {
+ lprintf("failed to map fb0\n");
+ goto fail0;
+ }
+
+ // use directx to discover other buffer
+ xdump();
+ Framework2D_Flip();
+ lprintf("---\n");
+ xdump();
+ exit(1);
+ //Framework2D_LockBuffer(1);
+
+ directfb_addrs[1] = memregs[0x5c>>2] + 0x30000;
+ lprintf("fb1 is at %08x\n", directfb_addrs[1]);
+
+ //Framework2D_UnlockBuffer();
+
+ directfb_ptrs[1] = mmap_phys(directfb_addrs[1], (321*240*2+PAGE_SIZE-1) / PAGE_SIZE);
+ if (directfb_ptrs[1] == NULL)
+ {
+ lprintf("failed to map fb1\n");
+ goto fail1;
+ }
+
+ directfb_initialized = 1;
+ directfb_sel = 1;
+ return 0;
+
+fail1:
+ munmap_phys(directfb_ptrs[0]);
+fail0:
+ munmap_phys((void *)memregs);
+ return -1;
+}
+
+static void directfb_fini(void)
+{
+ if (!directfb_initialized) return;
+
+ munmap_phys(directfb_ptrs[0]);
+ munmap_phys(directfb_ptrs[1]);
+ munmap_phys((void *)memregs);
+}
+
+void *directfb_lock(int is_front)
+{
+ int which;
+
+ if (!directfb_initialized)
+ // fall back to directx
+ return Framework2D_LockBuffer(is_front);
+
+ if (is_front)
+ which = directfb_sel;
+ else
+ which = directfb_sel ^ 1; // return backbuffer when possible
+
+ return directfb_ptrs[which];
+}
+
+void directfb_unlock(void)
+{
+ if (!directfb_initialized)
+ // fall back to directx
+ Framework2D_UnlockBuffer();
+}
+
+void directfb_flip(void)
+{
+ if (!directfb_initialized) {
+ Framework2D_Flip();
+ return;
+ }
+
+ directfb_sel ^= 1;
+ // doesn't work
+ memregs[0x5c>>2] = directfb_addrs[directfb_sel];
+}
+#endif