]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
DKB 1230/1240/1260 and RapidFire flash rom support.
authorToni Wilen <twilen@winuae.net>
Wed, 21 Jun 2017 17:43:49 +0000 (20:43 +0300)
committerToni Wilen <twilen@winuae.net>
Wed, 21 Jun 2017 17:43:49 +0000 (20:43 +0300)
cpuboard.cpp
expansion.cpp
include/rommgr.h
ncr9x_scsi.cpp
rommgr.cpp

index f81b8439681374f530ddf937dee8bafd8d4e3ab7..b42826973757b53e56d399bdb09edd5e8c3c6cc2 100644 (file)
@@ -1734,8 +1734,7 @@ static void cpuboard_init_2(void)
                blizzardea_bank.mask = blizzardea_bank.reserved_size - 1;
                mapped_malloc(&blizzardea_bank);
 
-       }
-       else if (is_dkb_12x0(&currprefs)) {
+       } else if (is_dkb_12x0(&currprefs)) {
 
                blizzardram_bank.start = 0x10000000;
                blizzardram_bank.reserved_size = cpuboard_size;
@@ -2180,49 +2179,6 @@ static void fixserial(struct uae_prefs *p, uae_u8 *rom, int size)
                makefakeppcrom(rom, type);
 }
 
-static struct zfile *flashfile_open(const TCHAR *name)
-{
-       struct zfile *f;
-       TCHAR path[MAX_DPATH];
-       bool rw = true;
-
-       if (name == NULL || !name[0])
-               return NULL;
-       f = zfile_fopen(name, _T("rb"), ZFD_NORMAL);
-       if (f) {
-               if (zfile_iscompressed(f)) {
-                       rw = false;
-               } else {
-                       zfile_fclose(f);
-                       f = NULL;
-               }
-       }
-       if (!f) {
-               rw = true;
-               f = zfile_fopen(name, _T("rb+"), ZFD_NONE);
-               if (!f) {
-                       rw = false;
-                       f = zfile_fopen(name, _T("rb"), ZFD_NORMAL);
-                       if (!f) {
-                               fetch_rompath(path, sizeof path / sizeof(TCHAR));
-                               _tcscat(path, name);
-                               rw = true;
-                               f = zfile_fopen(path, _T("rb+"), ZFD_NONE);
-                               if (!f) {
-                                       rw = false;
-                                       f = zfile_fopen(path, _T("rb"), ZFD_NORMAL);
-                               }
-                       }
-               }
-       }
-       if (f) {
-               write_log(_T("CPUBoard '%s' flash file '%s' loaded, %s.\n"),
-               cpuboards[currprefs.cpuboard_type].subtypes[currprefs.cpuboard_subtype].name,
-               name, rw ? _T("RW") : _T("RO"));
-       }
-       return f;
-}
-
 static struct zfile *board_rom_open(int *roms, const TCHAR *name)
 {
        struct zfile *zf = NULL;
@@ -2464,12 +2420,12 @@ bool cpuboard_autoconfig_init(struct autoconfig_info *aci)
                                autoconfig_rom = read_rom(rl->rd);
                }
        } else {
-               autoconfig_rom = flashfile_open(romname);
+               autoconfig_rom = flashromfile_open(romname);
                if (!autoconfig_rom) {
                        if (rl)
-                               autoconfig_rom = flashfile_open(rl->path);
+                               autoconfig_rom = flashromfile_open(rl->path);
                        if (!autoconfig_rom)
-                               autoconfig_rom = flashfile_open(defaultromname);
+                               autoconfig_rom = flashromfile_open(defaultromname);
                }
                if (!autoconfig_rom) {
                        if (aci->doinit)
@@ -2522,8 +2478,8 @@ bool cpuboard_autoconfig_init(struct autoconfig_info *aci)
        } else if (is_dkb_wildfire(p)) {
                f0rom_size = 65536;
                zfile_fread(blizzardf0_bank.baseaddr, 1, f0rom_size, autoconfig_rom);
-               flashrom = flash_new(blizzardf0_bank.baseaddr + 0, 32768, 65536, 0x20, flashrom_file, FLASHROM_EVERY_OTHER_BYTE | FLASHROM_PARALLEL_EEPROM);
-               flashrom2 = flash_new(blizzardf0_bank.baseaddr + 1, 32768, 65536, 0x20, flashrom_file, FLASHROM_EVERY_OTHER_BYTE | FLASHROM_EVERY_OTHER_BYTE_ODD | FLASHROM_PARALLEL_EEPROM);
+               flashrom = flash_new(blizzardf0_bank.baseaddr + 0, 32768, 65536, 0x01, 0x20, flashrom_file, FLASHROM_EVERY_OTHER_BYTE | FLASHROM_PARALLEL_EEPROM);
+               flashrom2 = flash_new(blizzardf0_bank.baseaddr + 1, 32768, 65536, 0x01, 0x20, flashrom_file, FLASHROM_EVERY_OTHER_BYTE | FLASHROM_EVERY_OTHER_BYTE_ODD | FLASHROM_PARALLEL_EEPROM);
                autoconf = false;
                aci->start = 0xf00000;
                aci->size = 65536;
@@ -2535,7 +2491,7 @@ bool cpuboard_autoconfig_init(struct autoconfig_info *aci)
                        flashrom_file = autoconfig_rom;
                        autoconfig_rom = NULL;
                }
-               flashrom = flash_new(blizzardf0_bank.baseaddr, f0rom_size, f0rom_size, 0xa4, flashrom_file, 0);
+               flashrom = flash_new(blizzardf0_bank.baseaddr, f0rom_size, f0rom_size, 0x01, 0xa4, flashrom_file, 0);
        } else if (is_a2630(p)) {
                f0rom_size = 65536;
                zfile_fread(blizzardf0_bank.baseaddr, 1, f0rom_size, autoconfig_rom);
@@ -2600,7 +2556,7 @@ bool cpuboard_autoconfig_init(struct autoconfig_info *aci)
                        flashrom_file = autoconfig_rom;
                        autoconfig_rom = NULL;
                }
-               flashrom = flash_new(blizzardea_bank.baseaddr, earom_size, earom_size, 0x20, flashrom_file, 0);
+               flashrom = flash_new(blizzardea_bank.baseaddr, earom_size, earom_size, 0x01, 0x20, flashrom_file, 0);
                memcpy(blizzardf0_bank.baseaddr, blizzardea_bank.baseaddr + 65536, 65536);
        } else if (is_csmk2(p)) {
                earom_size = 131072;
@@ -2610,7 +2566,7 @@ bool cpuboard_autoconfig_init(struct autoconfig_info *aci)
                        flashrom_file = autoconfig_rom;
                        autoconfig_rom = NULL;
                }
-               flashrom = flash_new(blizzardea_bank.baseaddr, earom_size, earom_size, 0x20, flashrom_file, 0);
+               flashrom = flash_new(blizzardea_bank.baseaddr, earom_size, earom_size, 0x01, 0x20, flashrom_file, 0);
                memcpy(blizzardf0_bank.baseaddr, blizzardea_bank.baseaddr + 65536, 65536);
        } else if (is_csmk3(p) || is_blizzardppc(p)) {
                uae_u8 flashtype;
@@ -2638,7 +2594,7 @@ bool cpuboard_autoconfig_init(struct autoconfig_info *aci)
                        autoconfig_rom = NULL;
                }
                fixserial(p, blizzardf0_bank.baseaddr, f0rom_size);
-               flashrom = flash_new(blizzardf0_bank.baseaddr, f0rom_size, f0rom_size, flashtype, flashrom_file, 0);
+               flashrom = flash_new(blizzardf0_bank.baseaddr, f0rom_size, f0rom_size, 0x01, flashtype, flashrom_file, 0);
                aci->start = 0xf00000;
                aci->size = 0x80000;
        } else if (is_blizzard(p)) {
index e11a8ae6d1f741d66bf89ea3629c29d53c6e1dec..f34ec1f00d250645b1c7d1ff50ccbdaa7cab551c 100644 (file)
@@ -5126,6 +5126,21 @@ const struct expansionromtype expansionroms[] = {
                false, EXPANSIONTYPE_INTERNAL
        },
 
+       // misc
+
+       {
+               _T("uaeboard_z2"), _T("UAEBOARD Z2"), NULL,
+               uaesndboard_init_z2, NULL, NULL, ROMTYPE_UAEBOARDZ2 | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z2, true,
+               NULL, 0,
+               false, EXPANSIONTYPE_CUSTOM
+       },
+       {
+               _T("uaeboard_z3"), _T("UAEBOARD Z3"), NULL,
+               uaesndboard_init_z3, NULL, NULL, ROMTYPE_UAEBOARDZ3 | ROMTYPE_NOT, 0, 0, BOARD_AUTOCONFIG_Z3, true,
+               NULL, 0,
+               false, EXPANSIONTYPE_CUSTOM
+       },
+
 
        {
                NULL
@@ -5421,16 +5436,27 @@ static const struct cpuboardsubtype commodore_sub[] = {
                NULL
        }
 };
+
+static const struct expansionboardsettings cpuboard_dkb_cobra_settings[] = {
+       {
+               _T("SCSI (Ferret)"),
+               _T("scsi")
+       },
+       {
+               NULL
+       }
+};
 static const struct cpuboardsubtype dbk_sub[] = {
        {
-               _T("1230/1240"),
+               _T("1230/1240/Cobra"),
                _T("DKB12x0"),
-               ROMTYPE_CB_DKB12x0, 0,
+               ROMTYPE_CB_DKB, 0,
                cpuboard_dkb_add_scsi_unit, EXPANSIONTYPE_SCSI,
                0,
                128 * 1024 * 1024,
                0,
-               ncr_dkb_autoconfig_init, NULL, BOARD_AUTOCONFIG_Z2, 0
+               ncr_dkb_autoconfig_init, NULL, BOARD_AUTOCONFIG_Z2, 0,
+               cpuboard_dkb_cobra_settings
        },
        {
                _T("Wildfire"),
index f37f692dff0914a1e437cf0a16a3a6ed823bddbf..838db67ee265b1f8a11463967a15ba7515798b53 100644 (file)
@@ -22,7 +22,7 @@ extern int decode_cloanto_rom_do (uae_u8 *mem, int size, int real_size);
 #define ROMTYPE_CB_A3001S1     0x00040001
 #define ROMTYPE_CB_APOLLO      0x00040002
 #define ROMTYPE_CB_FUSION      0x00040003
-#define ROMTYPE_CB_DKB12x0     0x00040004
+#define ROMTYPE_CB_DKB         0x00040004
 #define ROMTYPE_CB_WENGINE     0x00040005
 #define ROMTYPE_CB_TEKMAGIC    0x00040006
 #define ROMTYPE_CB_BLIZ1230    0x00040007
@@ -151,6 +151,8 @@ extern int decode_cloanto_rom_do (uae_u8 *mem, int size, int real_size);
 #define ROMTYPE_COMSPEC                0x00100061
 #define ROMTYPE_MALIBU         0x00100062
 #define ROMTYPE_RAPIDFIRE      0x00100063
+#define ROMTYPE_UAEBOARDZ2     0x00100064
+#define ROMTYPE_UAEBOARDZ3     0x00100065
 
 #define ROMTYPE_NOT                    0x00800000
 #define ROMTYPE_QUAD           0x01000000
@@ -256,6 +258,7 @@ void board_prefs_changed(int romtype, int devnum);
 #define LOADROM_ZEROFILL 8
 #define LOADROM_ODDFILL(x) ((x << 16) | LOADROM_EVENONLY)
 bool load_rom_rc(struct romconfig *rc, uae_u32 romtype, int maxfilesize, int fileoffset, uae_u8 *rom, int maxromsize, int flags);
+struct zfile *flashromfile_open(const TCHAR *name);
 
 #define EXPANSION_ORDER_MAX 10000
 
index ddcc24eb3f1d92679d65bf1d956d09668d848fd5..92d60517c9847ff9c4fcca62ddd889b79cb5b102 100644 (file)
@@ -83,6 +83,8 @@ struct ncr9x_state
        uae_u32 board_mask;
        uae_u32 board_mask2;
        uae_u8 *rom;
+       void *flashrom;
+       struct zfile *flashrom_file;
        uae_u8 acmemory[128];
        int configured;
        uaecptr baseaddress;
@@ -195,6 +197,8 @@ static void freencrunit(struct ncr9x_state *ncr)
                freescsi(ncr->scsid[ch]);
                ncr->scsid[ch] = NULL;
        }
+       flash_free(ncr->flashrom);
+       zfile_fclose(ncr->flashrom_file);
        xfree(ncr->rom);
        if (ncr->self_ptr)
                *ncr->self_ptr = NULL;
@@ -1004,6 +1008,8 @@ static void ncr9x_io_bput(struct ncr9x_state *ncr, uaecptr addr, uae_u32 val)
                        return;
                }
        } else if (ISCPUBOARD(BOARD_DKB, BOARD_DKB_SUB_12x0)) {
+               if (!(currprefs.cpuboard_settings & 1))
+                       return;
                if (addr == 0x10100) {
                        ncr->states[0] = val;
                        esp_dma_enable(ncr->devobject.lsistate, 1);
@@ -1295,6 +1301,8 @@ static uae_u32 ncr9x_io_bget(struct ncr9x_state *ncr, uaecptr addr)
                        return 0;
                }
        } else if (ISCPUBOARD(BOARD_DKB, BOARD_DKB_SUB_12x0)) {
+               if (!(currprefs.cpuboard_settings & 1))
+                       return 0x00;
                if (addr == 0x10100) {
                        uae_u8 v = 0;
                        if (ncr->chipirq || ncr->boardirq)
@@ -1365,13 +1373,22 @@ static uae_u32 ncr9x_io_bget(struct ncr9x_state *ncr, uaecptr addr)
 
 static uae_u8 read_rombyte(struct ncr9x_state *ncr, uaecptr addr)
 {
-       uae_u8 v = ncr->rom[addr];
-#if 0
-       if (addr == 0x104)
-               activate_debugger();
-#endif
+       uae_u8 v = 0xff;
+       if (ncr->flashrom) {
+               if ((!ncr->romisoddonly && !ncr->romisevenonly) || (ncr->romisoddonly && (addr & 1)) || (ncr->romisevenonly && !(addr & 1)))
+                       v = flash_read(ncr->flashrom, addr >> 1);
+       } else {
+               v = ncr->rom[addr];
+       }
        return v;
 }
+static void write_rombyte(struct ncr9x_state *ncr, uaecptr addr, uae_u8 v)
+{
+       if (!ncr->flashrom)
+               return;
+       if ((!ncr->romisoddonly && !ncr->romisevenonly) || (ncr->romisoddonly && (addr & 1)) || (ncr->romisevenonly && !(addr & 1)))
+               flash_write(ncr->flashrom, addr >> 1, v);
+}
 
 static uae_u32 ncr9x_bget2(struct ncr9x_state *ncr, uaecptr addr)
 {
@@ -1379,7 +1396,7 @@ static uae_u32 ncr9x_bget2(struct ncr9x_state *ncr, uaecptr addr)
 
        addr &= ncr->board_mask;
        if (ncr->rom && addr >= ncr->rom_start && addr < ncr->rom_end) {
-               if (addr < ncr->io_start || (!ncr->romisoddonly && !ncr->romisevenonly) || (ncr->romisoddonly && (addr & 1)) || (ncr->romisevenonly && (addr & 1)))
+               if (addr < ncr->io_start || (!ncr->romisoddonly && !ncr->romisevenonly) || (ncr->romisoddonly && (addr & 1)) || (ncr->romisevenonly && !(addr & 1)))
                        return read_rombyte (ncr, addr - ncr->rom_offset);
        }
        if (ncr->io_end && (addr < ncr->io_start || addr >= ncr->io_end))
@@ -1403,6 +1420,12 @@ static void ncr9x_bput2(struct ncr9x_state *ncr, uaecptr addr, uae_u32 val)
 #endif
 
        addr &= ncr->board_mask;
+       if (ncr->rom && addr >= ncr->rom_start && addr < ncr->rom_end) {
+               if (addr < ncr->io_start || (!ncr->romisoddonly && !ncr->romisevenonly) || (ncr->romisoddonly && (addr & 1)) || (ncr->romisevenonly && !(addr & 1))) {
+                       write_rombyte(ncr, addr, val);
+                       return;
+               }
+       }
        if (ncr->io_end && (addr < ncr->io_start || addr >= ncr->io_end))
                return;
        ncr9x_io_bput(ncr, addr, val);
@@ -1826,20 +1849,17 @@ bool ncr_oktagon_autoconfig_init(struct autoconfig_info *aci)
        return true;
 }
 
+static const uae_u8 dkb_autoconfig[16] = {
+       0xd2, 0x12, 0x40, 0x00, 0x07, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80
+};
+
 bool ncr_dkb_autoconfig_init(struct autoconfig_info *aci)
 {
-       if (!aci->doinit) {
-               struct zfile *z = read_device_from_romconfig(aci->rc, ROMTYPE_CB_DKB12x0);
-               if (z) {
-                       for (int i = 0; i < (sizeof aci->autoconfig_raw) / 2; i++) {
-                               uae_u8 b;
-                               zfile_fread(&b, 1, 1, z);
-                               aci->autoconfig_raw[i * 2] = b;
-                       }
-                       zfile_fclose(z);
-               }
+       const struct expansionromtype *ert = get_device_expansion_rom(ROMTYPE_RAPIDFIRE);
+
+       aci->autoconfigp = dkb_autoconfig;
+       if (!aci->doinit)
                return true;
-       }
 
        struct ncr9x_state *ncr = getscsi(aci->rc);
        if (!ncr)
@@ -1857,31 +1877,21 @@ bool ncr_dkb_autoconfig_init(struct autoconfig_info *aci)
        ncr->io_end = 0x20000;
        ncr->bank = &ncr9x_bank_generic;
        ncr->board_mask = 131071;
+       ncr->romisevenonly = true;
 
        ncr9x_reset_board(ncr);
 
-       struct zfile *z = read_device_from_romconfig(aci->rc, ROMTYPE_CB_DKB12x0);
-       ncr->rom = xcalloc (uae_u8, DKB_ROM_SIZE * 2);
-       if (z) {
-               // memory board at offset 0x100
-               int i;
-               memset(ncr->rom, 0xff, DKB_ROM_SIZE * 2);
-
-               zfile_fseek(z, 0, SEEK_SET);
-               for (i = 0; i < (sizeof ncr->acmemory) / 2; i++) {
-                       uae_u8 b;
-                       zfile_fread(&b, 1, 1, z);
-                       ncr->acmemory[i * 2] = b;
-               }
-               for (;;) {
-                       uae_u8 b;
-                       if (!zfile_fread(&b, 1, 1, z))
-                               break;
-                       ncr->rom[i * 2] = b;
-                       i++;
-               }
-               zfile_fclose(z);
+       ncr->rom = xcalloc (uae_u8, DKB_ROM_SIZE);
+       load_rom_rc(aci->rc, ROMTYPE_CB_DKB, 32768, 0, ncr->rom, 32768, LOADROM_ONEFILL);
+       for (int i = 0; i < 16; i++) {
+               uae_u8 b = dkb_autoconfig[i];
+               ew(ncr, i * 4, b);
        }
+       ncr->flashrom_file = flashromfile_open(aci->rc->romfile);
+       if (ncr->flashrom_file) {
+               zfile_fread(ncr->rom, 32768, 1, ncr->flashrom_file);
+       }
+       ncr->flashrom = flash_new(ncr->rom, 32768, 32768, 0x1f, 0xdc, ncr->flashrom_file, FLASHROM_PARALLEL_EEPROM);
 
        aci->addrbank = ncr->bank;
        return true;
@@ -2004,15 +2014,21 @@ bool ncr_rapidfire_init(struct autoconfig_info *aci)
        ncr->io_end = 0x20000;
        ncr->bank = &ncr9x_bank_generic;
        ncr->board_mask = 131071;
+       ncr->romisevenonly = true;
 
        ncr9x_reset_board(ncr);
 
-       ncr->rom = xcalloc (uae_u8, DKB_ROM_SIZE * 2);
-       load_rom_rc(aci->rc, ROMTYPE_RAPIDFIRE, 32768, 0, ncr->rom, 65536, LOADROM_EVENONLY | LOADROM_FILL);
+       ncr->rom = xcalloc (uae_u8, DKB_ROM_SIZE);
+       load_rom_rc(aci->rc, ROMTYPE_RAPIDFIRE, 32768, 0, ncr->rom, 32768, LOADROM_ONEFILL);
        for (int i = 0; i < 16; i++) {
                uae_u8 b = ert->autoconfig[i];
                ew(ncr, i * 4, b);
        }
+       ncr->flashrom_file = flashromfile_open(aci->rc->romfile);
+       if (ncr->flashrom_file) {
+               zfile_fread(ncr->rom, 32768, 1, ncr->flashrom_file);
+       }
+       ncr->flashrom = flash_new(ncr->rom, 32768, 32768, 0x1f, 0xdc, ncr->flashrom_file, FLASHROM_PARALLEL_EEPROM);
 
        aci->addrbank = ncr->bank;
        return true;
index d51b234f6c939e5be78c43b5aaea0c1a4519a7be..add13198c124ebed5437b573366ece0d45ec20da 100644 (file)
@@ -95,7 +95,7 @@ struct romdata *getromdatabypath (const TCHAR *path)
        return NULL;
 }
 
-#define NEXT_ROM_ID 208
+#define NEXT_ROM_ID 209
 
 #define ALTROM(id,grp,num,size,flags,crc32,a,b,c,d,e) \
 { _T("X"), 0, 0, 0, 0, 0, size, id, 0, 0, flags, (grp << 16) | num, 0, NULL, crc32, a, b, c, d, e },
@@ -380,10 +380,13 @@ static struct romdata roms[] = {
        ALTROMPN(164, 1, 1, 32768, ROMTYPE_ODD  | ROMTYPE_8BIT, _T("390282-01"), 0xdf76493b, 0x331ede0a, 0x8ca995cc, 0x1917f592, 0x18718e5b, 0x3c7fac39)
        ALTROMPN(164, 1, 2, 32768, ROMTYPE_EVEN | ROMTYPE_8BIT, _T("390283-01"), 0xd74187de, 0x681e4985, 0x4da64bf1, 0x6f2f99f7, 0x4b195f54, 0x0b8bd614)
 
-       { _T("DKB 12x0"), 1, 23, 1, 23, _T("DKB\0"), 32768, 112, 0, 0, ROMTYPE_CB_DKB12x0, 0, 0, NULL,
-       0xf3b2b0b3, 0x1d539593,0xb1d7514e,0xeb214ab3,0x433a97fc,0x8a010366, NULL, NULL },
+       { _T("DKB 1230/1240/Cobra"), 1, 23, 1, 23, _T("DKB\0"), 1460, 112, 0, 0, ROMTYPE_CB_DKB, 0, 0, NULL,
+       0x15ac5257, 0xf0431d02,0xac0f83d3,0x45db18c0,0x23f0cefb,0x33d17217, NULL, NULL },
+       { _T("DKB 1230/1240//Cobra + Ferret v1.23"), 1, 23, 1, 23, _T("DKB\0"), 12060, 208, 0, 0, ROMTYPE_CB_DKB, 0, 0, NULL,
+       0xda878913, 0xb62a68ef,0xb9378d74,0x0be17452,0x1ad07d2e,0xa461a313, NULL, NULL },
        { _T("DKB Rapidfire v1.31"), 1, 31, 1, 31, _T("RAPIDFIRE\0"), 11284, 207, 0, 0, ROMTYPE_RAPIDFIRE, 0, 0, NULL,
        0x68725e50, 0xa66f8ef6,0x901e0e41,0xf8b72bba,0x12165788,0xa452cf01, NULL, NULL },
+
        { _T("Fusion Forty"), 0, 0, 0, 0, _T("FUSIONFORTY\0"), 131072, 113, 0, 0, ROMTYPE_CB_FUSION, 0, 0, NULL,
        0x48fcb5fd, 0x15674dac,0x90b6d8db,0xdda3a175,0x997184c2,0xa423d733, NULL, NULL },
        ALTROMPN(113, 1, 1, 32768, ROMTYPE_QUAD | ROMTYPE_EVEN | ROMTYPE_8BIT, _T("U28"), 0x434a21a8, 0x472c1623, 0x02babd00, 0x7c1a77ff, 0x40dd12ab, 0x39c97f82)
@@ -2264,3 +2267,44 @@ bool load_rom_rc(struct romconfig *rc, uae_u32 romtype, int maxfilesize, int fil
        }
        return true;
 }
+
+struct zfile *flashromfile_open(const TCHAR *name)
+{
+       struct zfile *f;
+       TCHAR path[MAX_DPATH];
+       bool rw = true;
+
+       if (name == NULL || !name[0])
+               return NULL;
+       f = zfile_fopen(name, _T("rb"), ZFD_NORMAL);
+       if (f) {
+               if (zfile_iscompressed(f)) {
+                       rw = false;
+               } else {
+                       zfile_fclose(f);
+                       f = NULL;
+               }
+       }
+       if (!f) {
+               rw = true;
+               f = zfile_fopen(name, _T("rb+"), ZFD_NONE);
+               if (!f) {
+                       rw = false;
+                       f = zfile_fopen(name, _T("rb"), ZFD_NORMAL);
+                       if (!f) {
+                               fetch_rompath(path, sizeof path / sizeof(TCHAR));
+                               _tcscat(path, name);
+                               rw = true;
+                               f = zfile_fopen(path, _T("rb+"), ZFD_NONE);
+                               if (!f) {
+                                       rw = false;
+                                       f = zfile_fopen(path, _T("rb"), ZFD_NORMAL);
+                               }
+                       }
+               }
+       }
+       if (f) {
+               write_log(_T("Flash file '%s' loaded, %s.\n"), name, rw ? _T("RW") : _T("RO"));
+       }
+       return f;
+}