📄 vmuload.c
字号:
/* VMULoad 1.0 (c)2000 Dan Potter Please see the file README for info about distribution and usage. Thanks to Marcus Comstedt for this VMU format info.*/#include "dream.h"uint8 buf[512];uint8 fat[512];typedef struct { uint16 first_block; uint16 block_cnt; char fn[12];} vmufile_t;vmufile_t files[16] = {0};/* Routine to flush parts of cache.. thanks to the Linux-SH guys *//* This routine was taken from sh-stub.c which had a prominent no-copyright notice at the top. Therefore, I'm including it now under the copyright umbrella of KallistiOS. */#define L1_CACHE_BYTES 32#define CACHE_IC_ADDRESS_ARRAY 0xf0000000#define CACHE_IC_ENTRY_MASK 0x1fe0struct __large_struct { uint32 buf[100]; };#define __m(x) (*(struct __large_struct *)(x))/* end is really cnt */static void flush_icache_range(uint32 start, uint32 end) { uint32 addr, data, v; end += start; start &= ~(L1_CACHE_BYTES-1); for (v=start; v<end; v+=L1_CACHE_BYTES) { /* Write back O Cache */ asm volatile("ocbwb %0" : /* no output */ : "m" (__m(v))); /* Invalidate I Cache */ //addr = CACHE_IC_ADDRESS_ARRAY | // (v & CACHE_IC_ENTRY_MASK) | 0x8 /* A-bit */; addr = CACHE_IC_ADDRESS_ARRAY | (v & CACHE_IC_ENTRY_MASK); data = (v & 0xfffffc00); /* Valid = 0 */ *((volatile uint32*)addr) = data; }}/* Read the VMU's directory, looking for VMULoad files */int vmu_scan_card(uint8 addr) { int i, n, curfile; uint8 *ent; uint16 *buf16 = (uint16*)buf, dirblock, dirlength, *ent16; uint16 file_block = 0; memset(files, 0, sizeof(files)); curfile = 0; /* Read the root block and find out where the directory is located */ if (vmu_block_read(addr, 255, buf)) { printf("Can't read VMU root block\r\n"); } dirblock = buf16[0x4a/2]; dirlength = buf16[0x4c/2]; /* Draw entries and look for the ICONDATA.VMS entry */ for (n=dirlength; n>0; n--) { /* Read one dir block */ if (vmu_block_read(addr, dirblock, buf) != 0) { printf("Can't read VMU block %d\r\n", dirblock); return -1; } /* Each block has 16 entries */ for (i=0; i<16; i++) { ent = buf+i*32; if (!*ent) continue; ent16 = (uint16*)ent; files[curfile].first_block = ent16[1]; files[curfile].block_cnt = ent16[0x18/2]; memcpy(files[curfile].fn, ent+4, 12); curfile++; if (curfile >= 16) { i = 16; n = 0; break; } } dirblock--; } return 0;}/* Load the indexed file from the VMU */int vmu_load_file(uint8 addr, int idx, uint8 *buffer) { uint16 *fat16 = (uint16*)fat; uint16 blkcnt = 0; uint16 file_block = files[idx].first_block; /* Read the FAT */ if (vmu_block_read(addr, 254, fat) < 0) { printf("Can't read VMU FAT\r\n"); return -1; } while (file_block != 0xfffa) { printf("Loading block %d\r\n", file_block); if (vmu_block_read(addr, file_block, buffer) < 0) { printf("Failure to read block %d\r\n", file_block); return -1; } if (blkcnt > 0) buffer += 512; file_block = fat16[file_block]; blkcnt++; /* Sanity check */ if (blkcnt > 200) { printf("More than 200 blocks: corrupted memory card?\r\n"); return -1; } } printf("Load complete: loaded %d blocks\r\n", blkcnt); flush_icache_range(0x8c010000, 512*blkcnt+512); return 0;}/* VMU file menu */void draw_listing(int cur) { uint16 *out = vram_s + 640*60+20; int i; char tmp[64]; /* Clear everything */ vid_clear(0,0,0); /* Put a banner */ bfont_draw_str(vram_s+640*20+20, 640, "VMULoad v1.0 (c)2000 Dan Potter/Cryptic Allusion"); for (i=0; i<16; i++) { if (files[i].block_cnt == 0) continue; strncpy(tmp, files[i].fn, 12); tmp[12] = 0; bfont_draw_str(out, 640, tmp); sprintf(tmp, "(%d blocks @ %d)", files[i].block_cnt, files[i].first_block); bfont_draw_str(out + 16*13, 640, tmp); out += 640*24; } bfont_draw(vram_s+640*(60+24*cur)+8, 640, '>');}uint8 mcont=0, mvmu=0;int vmu_menu() { cont_cond_t cond; int cur = 0, cnt = 0, moved = 0; /* Make sure we have a controller */ if (!mcont) { mcont = maple_controller_addr(); if (!mcont) { printf("Can't find a controller\r\n"); return -1; } } /* Make sure we have a VMU */ if (!mvmu) { mvmu = maple_vmu_addr(); if (!mvmu) { printf("Can't find a VMU\r\n"); return -1; } } /* Draw the memory card listing */ if (vmu_scan_card(mvmu) < 0) return -1; draw_listing(cur); /* Now let the user pick one */ while(1) { /* Check status */ if (cont_get_cond(mcont, &cond) < 0) { printf("Couldn't get controller status\r\n"); return -1; } /* File selection */ if (!(cond.buttons & CONT_A)) return cur; /* Exit */ if (!(cond.buttons & CONT_START)) return -1; /* Move selector */ if (!(cnt % 10) && !(cond.buttons & CONT_DPAD_UP)) { moved = 1; if (cur > 0) cur--; } if (!(cnt % 10) && !(cond.buttons & CONT_DPAD_DOWN)) { moved = 1; if (cur < 16) cur++; } if (moved) { draw_listing(cur); moved = 0; } /* Once in a while rescan maple to allow VMU switchout and memory bank swapping */ cnt++; if (!(cnt % 25)) { int scanned = 0; maple_rescan_bus(1); while (!maple_vmu_addr()) { maple_rescan_bus(1); timer_sleep(100); scanned = 1; } if (scanned) { mvmu = maple_vmu_addr(); if (vmu_scan_card(mvmu) < 0) { printf("Error scanning card\r\n"); return -1; } draw_listing(0); cur = 0; } } timer_sleep(10); } return -1;}void call_prog() { uint32 *mem = (uint32*)0x8c010000; /* void (*m)() = (void (*)())(mem[0x38/4]); */ void (*m)() = (void (*)())mem; m();}/* wow: cheap! =) */void disclaim() { int y = 20; bfont_draw_str(vram_s+640*(y+=24)+20, 640, "Despite the preceeding disclaimer,"); bfont_draw_str(vram_s+640*(y+=24)+20, 640, "this program is not produced by"); bfont_draw_str(vram_s+640*(y+=24)+20, 640, "or under license from Sega Enterprises, Ltd.,"); bfont_draw_str(vram_s+640*(y+=24)+20, 640, "but by a group of hobbyist developers."); y+=24; bfont_draw_str(vram_s+640*(y+=24)+20, 640, "\"Sega\" and \"Dreamcast\" are registered"); bfont_draw_str(vram_s+640*(y+=24)+20, 640, "trademarks of Sega Enterprises, Ltd."); timer_sleep(8000);}int dc_main() { /* Do initial setup */ serial_disable(); dc_setup(DM_640x480, PM_RGB565); disclaim(); /* VMU File menu */ while (1) { int cur; if ( (cur=vmu_menu()) < 0) // return 0; continue; /* Load from VMU */ bfont_draw_str(vram_s+640*376+20, 640, "Loading program"); if (vmu_load_file(mvmu, cur, (uint8*)(0x8c010000)) < 0) { bfont_draw_str(vram_s+640*400+20, 640, "Can't load file"); return 0; } /* Call program */ bfont_draw_str(vram_s+640*400+20, 640, "Executing program"); call_prog(); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -