]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Flash/EEPROM support updates.
authorToni Wilen <twilen@winuae.net>
Sat, 4 Nov 2023 13:53:53 +0000 (15:53 +0200)
committerToni Wilen <twilen@winuae.net>
Sat, 4 Nov 2023 13:53:53 +0000 (15:53 +0200)
ar.cpp
cpuboard.cpp
flashrom.cpp
gfxboard.cpp
idecontrollers.cpp
include/flashrom.h
include/ide.h
include/rommgr.h
memory.cpp
rommgr.cpp

diff --git a/ar.cpp b/ar.cpp
index b867fe7b0aeaa842eff59ca7b23739725610027b..6affae9c10927097ef7073860ca931dabe14e6a2 100644 (file)
--- a/ar.cpp
+++ b/ar.cpp
@@ -1659,7 +1659,7 @@ int action_replay_load (void)
                if (rd->type & ROMTYPE_CD32CART)
                        return 0;
        }
-       f = read_rom_name (currprefs.cartfile);
+       f = read_rom_name(currprefs.cartfile, false);
        if (!f) {
                write_log (_T("failed to load '%s' cartridge ROM\n"), currprefs.cartfile);
                return 0;
@@ -1812,7 +1812,7 @@ int hrtmon_load (void)
        if (!isinternal) {
                if (currprefs.cartfile[0] == '\0')
                        return 0;
-               f = read_rom_name (currprefs.cartfile);
+               f = read_rom_name(currprefs.cartfile, false);
                if(!f) {
                        write_log (_T("failed to load '%s' cartridge ROM\n"), currprefs.cartfile);
                        return 0;
index f1e6fabc02fadc6575c6aa2852962705a2218309..a73baa6496cd46f84144e52122ae7a88f584b352 100644 (file)
@@ -662,6 +662,7 @@ static uae_u32 REGPARAM2 blizzardf0_bget(uaecptr addr)
 
        blizzardf0_slow(1);
 
+       addr &= blizzardf0_bank.mask;
        if (is_csmk3(&currprefs) || is_blizzardppc(&currprefs)) {
                if (flash_unlocked) {
                        return flash_read(flashrom, addr);
@@ -678,7 +679,6 @@ static uae_u32 REGPARAM2 blizzardf0_bget(uaecptr addr)
                                return flash_read(flashrom, addr);
                }
        }
-       addr &= blizzardf0_bank.mask;
        v = blizzardf0_bank.baseaddr[addr];
        return v;
 }
@@ -714,12 +714,12 @@ static void REGPARAM2 blizzardf0_bput(uaecptr addr, uae_u32 b)
 {
        blizzardf0_slow(1);
 
+       addr &= blizzardf0_bank.mask;
        if (is_csmk3(&currprefs) || is_blizzardppc(&currprefs)) {
                if (flash_unlocked) {
                        flash_write(flashrom, addr, b);
                }
        } else if (is_csmk2(&currprefs)) {
-               addr &= 65535;
                addr += 65536;
                addr &= ~3;
                addr |= csmk2_flashaddressing;
@@ -854,6 +854,7 @@ static void REGPARAM2 blizzardea_bput(uaecptr addr, uae_u32 b)
                if (addr >= CYBERSTORM_MK2_SCSI_OFFSET) {
                        cpuboard_ncr9x_scsi_put(addr, b);
                }  else {
+                       addr &= 65535;
                        addr &= ~3;
                        addr |= csmk2_flashaddressing;
                        flash_write(flashrom, addr, b);
index 298df379bc016cebc3842e5a0c5685a56de4c9a2..220e8ecb2f302414be91810ec622da046e6f8ec0 100644 (file)
@@ -246,14 +246,16 @@ void *eeprom93xx_new(const uae_u8 *memory, int nwords, struct zfile *zf)
        }
 
        eeprom = (eeprom93xx_eeprom_t *)xcalloc(eeprom93xx_eeprom_t, 1);
-       eeprom->size = nwords;
-       eeprom->addrbits = addrbits;
-       for (int i = 0; i < nwords; i++) {
-               eeprom->contents[i] = (memory[i * 2 + 0] << 8) | memory[i * 2 + 1];
-       }
-       /* Output DO is tristate, read results in 1. */
-       eeprom->eedo = 1;
-//     write_log("eeprom = 0x%p, nwords = %u\n", eeprom, nwords);
+       if (eeprom) {
+               eeprom->size = nwords;
+               eeprom->addrbits = addrbits;
+               for (int i = 0; i < nwords; i++) {
+                       eeprom->contents[i] = (memory[i * 2 + 0] << 8) | memory[i * 2 + 1];
+               }
+               /* Output DO is tristate, read results in 1. */
+               eeprom->eedo = 1;
+       //      write_log("eeprom = 0x%p, nwords = %u\n", eeprom, nwords);
+       }
        return eeprom;
 }
 
@@ -542,16 +544,16 @@ void *eeprom_new(uae_u8 *memory, int size, struct zfile *zf)
     bitbang_i2c_interface *s;
 
     s = xcalloc(bitbang_i2c_interface, 1);
-
-       eeprom_reset(s);
-
-       s->memory = memory;
-       s->size = size;
-       s->zf = zf;
-       s->addressbitmask = (size / 256) - 1;
-       s->device_address = 0xa0;
-       s->device_address_mask = 0xf0;
-
+       if (s) {
+               eeprom_reset(s);
+
+               s->memory = memory;
+               s->size = size;
+               s->zf = zf;
+               s->addressbitmask = (size / 256) - 1;
+               s->device_address = 0xa0;
+               s->device_address_mask = 0xf0;
+       }
     return s;
 }
 
@@ -560,18 +562,19 @@ void *i2c_new(uae_u8 device_address, int size, uae_u8 (*read_func)(uae_u8 addr),
        bitbang_i2c_interface *s;
 
        s = xcalloc(bitbang_i2c_interface, 1);
-
-       eeprom_reset(s);
-
-       s->memory = NULL;
-       s->size = size;
-       s->zf = NULL;
-       s->addressbitmask = 0;
-       s->device_address = 0xa2;
-       s->device_address_mask = 0xff;
-
-       s->read_func = read_func;
-       s->write_func = write_func;
+       if (s) {
+               eeprom_reset(s);
+
+               s->memory = NULL;
+               s->size = size;
+               s->zf = NULL;
+               s->addressbitmask = 0;
+               s->device_address = 0xa2;
+               s->device_address_mask = 0xff;
+
+               s->read_func = read_func;
+               s->write_func = write_func;
+       }
        return s;
 }
 
@@ -603,10 +606,16 @@ struct flashrom_data
        int state;
        int modified;
        int sectorsize;
+       int pagesize;
        uae_u8 devicecode, mfgcode;
        int flags;
+       int writeprot;
+       int lastpagewrite;
        int firstwriteoffset;
        int lastwriteoffset;
+       uae_u8 page[128];
+       bool mpage[128];
+       bool pagemodified;
        struct zfile *zf;
 };
 
@@ -624,17 +633,22 @@ static void setmodified(struct flashrom_data *fd, int offset)
 void *flash_new(uae_u8 *rom, int flashsize, int allocsize, uae_u8 mfgcode, uae_u8 devcode, struct zfile *zf, int flags)
 {
        struct flashrom_data *fd = xcalloc(struct flashrom_data, 1);
-       fd->flashsize = flashsize;
-       fd->allocsize = allocsize;
-       fd->mask = fd->flashsize - 1;
-       fd->zf = zf;
-       fd->rom = rom;
-       fd->flags = flags;
-       fd->devicecode = devcode;
-       fd->mfgcode = mfgcode;
-       fd->sectorsize = devcode == 0x20 ? 16384 : 65536;
-       fd->lastwriteoffset = 0;
-       fd->firstwriteoffset = allocsize;
+       if (fd) {
+               fd->flashsize = flashsize;
+               fd->allocsize = allocsize;
+               fd->mask = fd->flashsize - 1;
+               fd->zf = zf;
+               fd->rom = rom;
+               fd->flags = flags;
+               fd->devicecode = devcode;
+               fd->pagesize = mfgcode == 0xbf ? 128 : 64;
+               fd->mfgcode = mfgcode;
+               fd->sectorsize = devcode == 0x20 ? 16384 : 65536;
+               fd->lastwriteoffset = 0;
+               fd->firstwriteoffset = allocsize;
+               fd->writeprot = (flags & FLASHROM_DATA_PROTECT) ? 1 : 0;
+               fd->lastpagewrite = -1;
+       }
        return fd;
 }
 
@@ -646,13 +660,36 @@ void flash_free(void *fdv)
        if (fd->zf && fd->modified) {
                if (fd->flags & FLASHROM_EVERY_OTHER_BYTE) {
                        zfile_fseek(fd->zf, (fd->flags & FLASHROM_EVERY_OTHER_BYTE_ODD) ? 1 : 0, SEEK_SET);
-                       for (int i = 0; i < fd->allocsize; i++) {
+                       int last = fd->lastwriteoffset + 1;
+                       last += 511;
+                       last &= ~511;
+                       if (last > fd->allocsize) {
+                               last = fd->allocsize;
+                       }
+                       for (int i = 0; i < last; i++) {
                                zfile_fwrite(&fd->rom[i * 2], 1, 1, fd->zf);
                                zfile_fseek(fd->zf, 1, SEEK_CUR);
                        }
+               } else if (fd->flags & FLASHROM_SKIP_EVERY_OTHER_BYTE) {
+                       zfile_fseek(fd->zf, 0, SEEK_SET);
+                       int last = fd->lastwriteoffset + 1;
+                       last += 511;
+                       last &= ~511;
+                       if (last > fd->allocsize) {
+                               last = fd->allocsize;
+                       }
+                       for (int i = 0; i <  last / 2; i++) {
+                               zfile_fwrite(&fd->rom[i * 2], 1, 1, fd->zf);
+                       }
                } else {
-                       zfile_fseek(fd->zf, fd->firstwriteoffset, SEEK_SET);
-                       zfile_fwrite(fd->rom + fd->firstwriteoffset, fd->lastwriteoffset - fd->firstwriteoffset + 1, 1, fd->zf);
+                       uae_s32 msize = zfile_ftell32(fd->zf);
+                       if (msize > fd->lastwriteoffset) {
+                               zfile_fseek(fd->zf, fd->firstwriteoffset, SEEK_SET);
+                               zfile_fwrite(fd->rom + fd->firstwriteoffset, fd->lastwriteoffset - fd->firstwriteoffset + 1, 1, fd->zf);
+                       } else {
+                               zfile_fseek(fd->zf, 0, SEEK_SET);
+                               zfile_fwrite(fd->rom, fd->lastwriteoffset + 1, 1, fd->zf);
+                       }
                }
        }
        xfree(fdv);
@@ -674,76 +711,126 @@ bool flash_active(void *fdv, uaecptr addr)
        return fd->state != 0;
 }
 
+static void writeflash(struct flashrom_data *fd, int addr, uae_u8 v)
+{
+       if (!(fd->flags & FLASHROM_PARALLEL_EEPROM)) {
+               fd->state = 100;
+               if (fd->writeprot <= 0) {
+                       if (fd->rom[addr] != v) {
+                               fd->rom[addr] = v;
+                               fd->modified = 1;
+                       }
+                       if (fd->modified) {
+                               setmodified(fd, addr);
+                       }
+                       gui_flicker_led(LED_MD, 0, 2);
+               }
+       } else {
+               int page = addr & ~(fd->pagesize - 1);
+               int mpage = addr & (fd->pagesize - 1);
+               if (fd->lastpagewrite != page) {
+                       memset(fd->mpage, 0, sizeof(fd->mpage));
+                       fd->pagemodified = false;
+                       fd->lastpagewrite = page;
+               }
+               if (fd->writeprot <= 0) {
+                       fd->page[mpage] = v;
+                       fd->mpage[mpage] = true;
+                       fd->pagemodified = true;
+                       gui_flicker_led(LED_MD, 0, 2);
+               }
+               fd->state = 7 + 1;
+       }
+}
+
 bool flash_write(void *fdv, uaecptr addr, uae_u8 v)
 {
        struct flashrom_data *fd = (struct flashrom_data*)fdv;
-       int oldstate;
-       uae_u32 addr2;
        int other_byte_mult = 1;
 
        if (!fd)
                return false;
 
-       if (fd->flags & FLASHROM_EVERY_OTHER_BYTE) {
+       if (fd->flags & (FLASHROM_SKIP_EVERY_OTHER_BYTE | FLASHROM_EVERY_OTHER_BYTE)) {
                addr >>= 1;
                other_byte_mult = 2;
        }
 
-       oldstate = fd->state;
+       if (addr * other_byte_mult >= fd->allocsize) {
+               return false;
+       }
+
+       int oldstate = fd->state;
+       bool det = false;
 
 #if FLASH_LOG > 1
        write_log(_T("flash write %08x %02x (%d) PC=%08x\n"), addr, v, fd->state, m68k_getpc());
 #endif
 
        addr &= fd->mask;
-       addr2 = addr & 0xffff;
 
-       if (fd->state >= 7 && fd->state < 7 + 64) {
-               if (!(fd->flags & FLASHROM_PARALLEL_EEPROM)) {
-                       fd->state = 100;
-               } else {
-                       fd->state++;
-                       if (fd->state >= 7 + 64)
-                               fd->state = 100;
-               }
-               if (addr >= fd->allocsize)
-                       return false;
+       if (fd->state == 7 || fd->state == 8) {
                int a = addr * other_byte_mult;
-               if (fd->rom[a] != v) {
-                       fd->rom[a] = v;
-                       setmodified(fd, a);
-               }
-               gui_flicker_led (LED_MD, 0, 2);
+               writeflash(fd, a, v);
                return true;
        }
 
-       if (v == 0xf0) {
+       if (v == 0xf0 && fd->state > 0 && fd->state < 7) {
                fd->state = 0;
                return false;
        }
 
        // unlock
-       if (addr2 == 0x5555 && fd->state <= 2 && v == 0xaa)
+       if (addr == 0x5555 && fd->state <= 2 && v == 0xaa) {
                fd->state = 1;
-       if (addr2 == 0x2aaa && fd->state == 1 && v == 0x55)
+               det = true;
+       }
+       if (addr == 0x2aaa && fd->state == 1 && v == 0x55) {
                fd->state = 2;
+               det = true;
+       }
+
+       // software id exit and reset first byte
+       if (addr == 0x5555 && fd->state == 3 && v == 0xaa) {
+               fd->state = 1;
+               det = true;
+       }
 
        // autoselect
-       if (addr2 == 0x5555 && fd->state == 2 && v == 0x90)
+       if (addr == 0x5555 && fd->state == 2 && v == 0x90) {
                fd->state = 3;
+               det = true;
+       }
 
-       // program
-       if (addr2 == 0x5555 && fd->state == 2 && v == 0xa0)
+       // data protect enable
+       if (addr == 0x5555 && fd->state == 2 && v == 0xa0) {
                fd->state = 7;
+               det = true;
+               fd->writeprot = -1;
+               return false;
+       }
+
+       // data protect disable
+       if (addr == 0x5555 && fd->state == 6 && v == 0x20) {
+               fd->state = 0;
+               fd->writeprot = 0;
+               return false;
+       }
 
-       // chip/sector erase
-       if (addr2 == 0x5555 && fd->state == 2 && v == 0x80)
+       // chip/sector erase/protect disable
+       if (addr == 0x5555 && fd->state == 2 && v == 0x80) {
                fd->state = 4;
-       if (addr2 == 0x5555 && fd->state == 4 && v == 0xaa)
+               det = true;
+       }
+       if (addr == 0x5555 && fd->state == 4 && v == 0xaa) {
                fd->state = 5;
-       if (addr2 == 0x2aaa && fd->state == 5 && v == 0x55)
+               det = true;
+       }
+       if (addr == 0x2aaa && fd->state == 5 && v == 0x55) {
                fd->state = 6;
-       if (addr2 == 0x5555 && fd->state == 6 && v == 0x10) {
+               det = true;
+       }
+       if (addr == 0x5555 && fd->state == 6 && v == 0x10) {
                for (int i = 0; i < fd->allocsize; i++)  {
                        int a = i * other_byte_mult;
                        if (fd->rom[a] != 0xff) {
@@ -776,8 +863,15 @@ bool flash_write(void *fdv, uaecptr addr, uae_u8 v)
                return true;
        }
 
-       if (fd->state == oldstate)
+       if (fd->state == oldstate || !det) {
                fd->state = 0;
+       }
+
+       if (!det && (fd->flags & FLASHROM_PARALLEL_EEPROM)) {
+               int a = addr * other_byte_mult;
+               writeflash(fd, a, v);
+               return true;
+       }
        return false;
 }
 
@@ -793,12 +887,32 @@ uae_u32 flash_read(void *fdv, uaecptr addr)
        if (!fd)
                return 0;
 
-       if (fd->flags & FLASHROM_EVERY_OTHER_BYTE) {
+       if (fd->flags & (FLASHROM_EVERY_OTHER_BYTE | FLASHROM_SKIP_EVERY_OTHER_BYTE)) {
                addr >>= 1;
                other_byte_mult = 2;
        }
 
+       if (addr * other_byte_mult >= fd->allocsize) {
+               return 0xff;
+       }
+
        addr &= fd->mask;
+
+       // write data in pagebuffer when any read is done
+       if ((fd->flags & FLASHROM_PARALLEL_EEPROM) && fd->pagemodified) {
+               fd->pagemodified = false;
+               for (int i = 0; i < fd->pagesize; i++) {
+                       int offset = fd->lastpagewrite + i;
+                       if (fd->mpage[i]) {
+                               if (fd->rom[offset] != fd->page[i]) {
+                                       fd->rom[offset] = fd->page[i];
+                                       setmodified(fd, offset);
+                               }
+                               fd->mpage[i] = false;
+                       }
+               }
+       }
+
        if (fd->state == 3) {
                uae_u8 a = addr & 0xff;
                if (a == 0)
@@ -821,14 +935,12 @@ uae_u32 flash_read(void *fdv, uaecptr addr)
                if (fd->state & 1)
                        v ^= 0x40;
                fd->state++;
-               if (fd->state >= 110)
+               if (fd->state >= 110) {
                        fd->state = 0;
+               }
        } else {
                fd->state = 0;
-               if (addr >= fd->allocsize)
-                       v = 0xff;
-               else
-                       v = fd->rom[addr * other_byte_mult];
+               v = fd->rom[addr * other_byte_mult];
        }
 #if FLASH_LOG > 1
        write_log(_T("flash read %08x = %02X (%d) PC=%08x\n"), oaddr, v, fd->state, m68k_getpc());
index 5f7d507a792e382469eb481849d1dbea47a02c6e..c3e57c19159e91c9374301bafa826256545fb27b 100644 (file)
@@ -4494,7 +4494,7 @@ bool gfxboard_init_memory (struct autoconfig_info *aci)
                        _tcscat(path, _T("voodoo3.rom"));
                else
                        _tcscat(path, _T("s3virge.rom"));
-               struct zfile *zf = read_rom_name(path);
+               struct zfile *zf = read_rom_name(path, false);
                if (zf) {
                        gb->bios = xcalloc(uae_u8, 65536);
                        gb->bios_mask = 65535;
index c84311ac4704cf83109d7b156f36d9e654930313..a578349baa02f475c4188fb1e830aa4bef30c1fe 100644 (file)
@@ -28,6 +28,8 @@
 #include "ncr9x_scsi.h"
 #include "autoconf.h"
 #include "devices.h"
+#include "flashrom.h"
+
 
 #define DEBUG_IDE 0
 #define DEBUG_IDE_GVP 0
@@ -148,6 +150,8 @@ static void freencrunit(struct ide_board *ide)
        }
        if (ide->self_ptr)
                *ide->self_ptr = NULL;
+       flash_free(ide->flashrom);
+       zfile_fclose(ide->romfile);
        xfree(ide->rom);
        xfree(ide);
 }
@@ -478,9 +482,18 @@ static int get_adide_reg(uaecptr addr, struct ide_board *board)
        return reg;
 }
 
-static int get_buddha_reg(uaecptr addr, struct ide_board *board, int *portnum)
+static int get_buddha_reg(uaecptr addr, struct ide_board *board, int *portnum, int *flashoffset)
 {
        int reg = -1;
+       if (flashoffset) {
+               *flashoffset = -1;
+       }
+       if (board->flashenabled) {
+               if (flashoffset && !(addr & 1)) {
+                       *flashoffset = ((board->userdata & 0x100) ? 32768 : 0) + (addr >> 1);
+               }
+               return -1;
+       }
        if (addr < 0x800 || addr >= 0xe00)
                return reg;
        *portnum = (addr - 0x800) / 0x200;
@@ -648,14 +661,18 @@ static uae_u32 ide_read_byte(struct ide_board *board, uaecptr addr)
                write_log(_T("IDE IO BYTE READ %08x %08x\n"), addr, M68K_GETPC);
 #endif
        
-       if (addr < 0x40 && (!board->configured || board->keepautoconfig))
+       if (addr < 0x40 && !board->flashenabled && (!board->configured || board->keepautoconfig))
                return board->acmemory[addr];
 
        if (board->type == BUDDHA_IDE) {
 
                int portnum;
-               int regnum = get_buddha_reg(addr, board, &portnum);
-               if (regnum >= 0) {
+               int flashoffset = -1;
+               bool p1 = (board->aci->rc->device_settings & 3) == 1;
+               int regnum = get_buddha_reg(addr, board, &portnum, &flashoffset);
+               if (flashoffset >= 0) {
+                       v = flash_read(board->flashrom, flashoffset);
+               } else if (regnum >= 0) {
                        if (board->ide[portnum])
                                v = get_ide_reg_multi(board, regnum, portnum, 1);
                } else if (addr >= 0xf00 && addr < 0x1000) {
@@ -663,7 +680,7 @@ static uae_u32 ide_read_byte(struct ide_board *board, uaecptr addr)
                                v = ide_irq_check(board->ide[0], false) ? 0x80 : 0x00;
                        } else if ((addr & ~3) == 0xf40) {
                                v = ide_irq_check(board->ide[1], false) ? 0x80 : 0x00;
-                       } else if ((addr & ~3) == 0xf80 && (board->aci->rc->device_settings & 3) != 1) {
+                       } else if ((addr & ~3) == 0xf80 && !p1) {
                                v = ide_irq_check(board->ide[2], false) ? 0x80 : 0x00;
                        } else {
                                v = 0;
@@ -671,7 +688,11 @@ static uae_u32 ide_read_byte(struct ide_board *board, uaecptr addr)
                } else if (addr >= 0x7fc && addr <= 0x7ff) {
                        v = board->userdata;
                } else {
-                       v = board->rom[addr & board->rom_mask];
+                       int offset = (addr >> 1) & board->rom_mask;
+                       if (p1 && (board->userdata & 0x100)) {
+                               offset += 0x8000;
+                       }
+                       v = board->rom[offset];
                }
 
        } else if (board->type == ALF_IDE || board->type == TANDEM_IDE) {
@@ -1083,7 +1104,7 @@ static uae_u32 ide_read_word(struct ide_board *board, uaecptr addr)
                if (board->type == BUDDHA_IDE) {
 
                        int portnum;
-                       int regnum = get_buddha_reg(addr, board, &portnum);
+                       int regnum = get_buddha_reg(addr, board, &portnum, NULL);
                        if (regnum == IDE_DATA) {
                                if (board->ide[portnum])
                                        v = get_ide_reg_multi(board, IDE_DATA, portnum, 1);
@@ -1393,15 +1414,65 @@ static void ide_write_byte(struct ide_board *board, uaecptr addr, uae_u8 v)
                if (board->type == BUDDHA_IDE) {
 
                        int portnum;
-                       int regnum = get_buddha_reg(addr, board, &portnum);
-                       if (regnum >= 0) {
+                       int flashoffset = -1;
+                       bool p1 = (board->aci->rc->device_settings & 3) == 1;
+                       int regnum = get_buddha_reg(addr, board, &portnum, &flashoffset);
+                       if (flashoffset >= 0) {
+                               flash_write(board->flashrom, flashoffset, v);
+                       } else if (regnum >= 0) {
                                if (board->ide[portnum]) {
                                        put_ide_reg_multi(board, regnum, v, portnum, 1);
                                }
                        } else if (addr >= 0xfc0 && addr < 0xfc4) {
                                board->intena = true;
+                               if (addr == 0xfc2 && p1) {
+                                       uae_u8 v2 = v & 0xf0;
+                                       int cnt = (board->userdata >> 16) & 15;
+                                       if (v2 == 0xa0 && cnt == 0) {
+                                               cnt++;
+                                       } else if (v2 == 0x50 && cnt == 1) {
+                                               cnt++;
+                                       } else if (v2 == 0xa0 && cnt == 2) {
+                                               cnt++;
+                                       } else if (v2 == 0x70 && cnt == 3) {
+                                               board->userdata |= 0x100000;
+                                               write_log("RAM expansion OFF\n");
+                                       } else if (v2 == 0xc0 && cnt == 3) {
+                                               board->userdata |= 0x200000;
+                                       } else if (v2 == 0xe0 && cnt == 3) {
+                                               write_log("Lockdown EEPROM\n");
+                                       } else if (v2 == 0xb0 && cnt == 3) {
+                                               write_log("Fast-Z2 ON\n");
+                                       } else if (v2 == 0x30 && cnt == 3) {
+                                               write_log("Fast-Z2 OFF\n");
+                                       } else if (v2 == 0x90 && cnt == 3) {
+                                               write_log("Early write ON\n");
+                                       } else if (v2 == 0x80 && cnt == 3) {
+                                               write_log("Early write OFF\n");
+                                       } else if (v2 == 0x60 && (board->userdata & 0x100000)) {
+                                               write_log("$a00000 ON\n");
+                                       } else if (v2 == 0x60 && (board->userdata & 0x200000)) {
+                                               write_log("$c00000 ON\n");
+                                       } else if (v2 == 0xf0 && cnt == 3) {
+                                               board->flashenabled = true;
+                                       } else {
+                                               cnt = 0;
+                                       }
+                                       board->userdata &= 0xfff0ffff;
+                                       board->userdata |= cnt << 16;
+                               }
                        } else if (addr >= 0x7fc && addr <= 0x7ff) {
-                               board->userdata = v;
+                               board->userdata &= ~0xff;
+                               board->userdata |= v;
+                       } else if (addr == 0xc3) {
+                               if (p1) {
+                                       board->userdata |= 0x100;
+                               }
+                       } else if (addr == 0xc1) {
+                               board->userdata &= ~0x100;
+                       } else if (addr == 1) {
+                               board->userdata = 0;
+                               board->flashenabled = false;
                        }
 
                } else  if (board->type == ALF_IDE || board->type == TANDEM_IDE) {
@@ -1670,7 +1741,7 @@ static void ide_write_word(struct ide_board *board, uaecptr addr, uae_u16 v)
                if (board->type == BUDDHA_IDE) {
 
                        int portnum;
-                       int regnum = get_buddha_reg(addr, board, &portnum);
+                       int regnum = get_buddha_reg(addr, board, &portnum, NULL);
                        if (regnum == IDE_DATA) {
                                if (board->ide[portnum])
                                        put_ide_reg_multi(board, IDE_DATA, v, portnum, 1);
@@ -2479,21 +2550,26 @@ bool buddha_init(struct autoconfig_info *aci)
                return true;
        }
        struct ide_board *ide = getide(aci);
+       bool p1 = (aci->rc->device_settings & 3) == 1;
 
        ide->configured = 0;
        ide->bank = &ide_bank_generic;
        ide->rom_size = 65536;
        ide->mask = 65536 - 1;
 
-       ide->rom = xcalloc(uae_u8, ide->rom_size);
-       memset(ide->rom, 0xff, ide->rom_size);
+       ide->rom = xcalloc(uae_u8, ide->rom_size * 2);
+       memset(ide->rom, 0xff, ide->rom_size * 2);
        ide->rom_mask = ide->rom_size - 1;
-       load_rom_rc(aci->rc, ROMTYPE_BUDDHA, 32768, 0, ide->rom, 65536, LOADROM_EVENONLY_ODDONE | LOADROM_FILL);
+       ide->romfile = load_rom_rc_zfile(aci->rc, ROMTYPE_BUDDHA, 65536, 0, ide->rom, 65536, LOADROM_FILL);
+       if (p1) {
+               ide->flashrom = flash_new(ide->rom, 65536, 65536, 0xbf, 0x5d, ide->romfile, FLASHROM_PARALLEL_EEPROM | FLASHROM_DATA_PROTECT);
+       }
+
        for (int i = 0; i < 16; i++) {
                uae_u8 b = ert->autoconfig[i];
                if (i == 1 && (aci->rc->device_settings & 3) == 2)
                        b = 42;
-               if (i == 9 && (aci->rc->device_settings & 3) == 1)
+               if (i == 9 && p1)
                        b = 6;
                ew(ide, i * 4, b);
        }
index 2f12bad43e428ea44e89980ba5b3d2ee48cefc10..0f355118a4a45b81018fa15b8a9ded97ef1c1f6e 100644 (file)
@@ -26,6 +26,8 @@ int eeprom_i2c_set(void *i2c, int line, int level);
 #define FLASHROM_EVERY_OTHER_BYTE 1
 #define FLASHROM_EVERY_OTHER_BYTE_ODD 2
 #define FLASHROM_PARALLEL_EEPROM 4
+#define FLASHROM_SKIP_EVERY_OTHER_BYTE 8
+#define FLASHROM_DATA_PROTECT 16
 
 void *i2c_new(uae_u8 device_address, int size, uae_u8(*read_func)(uae_u8 addr), void(*write_func)(uae_u8 addr, uae_u8 v));
 void i2c_free(void *i2c);
index a2d0c5a0527aba1b3b46bc62baf368b8c9292ca8..c9992aa5c2dc446110961de9b1ddde4a0e14f13d 100644 (file)
@@ -33,6 +33,8 @@ typedef void (*hsync_func)(struct ide_board*);
 struct ide_board
 {
        uae_u8 *rom;
+       void *flashrom;
+       struct zfile *romfile;
        uae_u8 acmemory[128];
        int rom_size;
        int rom_start;
@@ -47,6 +49,7 @@ struct ide_board
        bool intena;
        bool enabled;
        bool intlev6;
+       bool flashenabled;
        int state;
        uae_u8 state2[8];
        int type;
index ca34b6dd3dab2ff69601f568a88be986c8089ca3..52c39857f549a1d21bed2279d63a5191810011b1 100644 (file)
@@ -274,9 +274,9 @@ extern struct romlist *getromlistbyromdata (const struct romdata *rd);
 extern void romlist_add (const TCHAR *path, struct romdata *rd);
 extern TCHAR *romlist_get (const struct romdata *rd);
 extern void romlist_clear (void);
-extern struct zfile *read_rom (struct romdata *rd);
-extern struct zfile *read_rom_name (const TCHAR *filename);
-extern struct zfile *read_device_from_romconfig(struct romconfig *rc, uae_u32 romtype);
+extern struct zfile *read_rom(struct romdata *rd, bool rw = false);
+extern struct zfile *read_rom_name(const TCHAR *filename, bool rw = false);
+extern struct zfile *read_device_from_romconfig(struct romconfig *rc, uae_u32 romtype, bool rw = false);
 
 extern int load_keyring (struct uae_prefs *p, const TCHAR *path);
 extern uae_u8 *target_load_keyfile (struct uae_prefs *p, const TCHAR *path, int *size, TCHAR *name);
@@ -314,6 +314,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 *load_rom_rc_zfile(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 678bd0ac7de830970ebb98002f7a4bcab73de577..52676825f18ec0d3ceff96f8628b4fd7fd866b42 100644 (file)
@@ -1674,7 +1674,7 @@ static bool load_extendedkickstart (const TCHAR *romextfile, int type)
                extendedkickmem_type = EXTENDED_ROM_ARCADIA;
                return false;
        }
-       f = read_rom_name (romextfile);
+       f = read_rom_name (romextfile, false);
        if (!f) {
                notify_user (NUMSG_NOEXTROM);
                return false;
@@ -1871,7 +1871,7 @@ static struct zfile *get_kickstart_filehandle(struct uae_prefs *p)
        struct zfile *f;
        TCHAR tmprom[MAX_DPATH], tmprom2[MAX_DPATH];
 
-       f = read_rom_name(p->romfile);
+       f = read_rom_name(p->romfile, false);
        _tcscpy(tmprom, p->romfile);
        _tcscpy(tmprom2, p->romfile);
        if (f == NULL) {
index e2ed023259cebf9e64f6ee4b4011cbf1b7f71375..3472761d112751a17e75bf504acfb25317ac8e82 100644 (file)
@@ -1921,7 +1921,7 @@ static void descramble (const struct romdata *rd, uae_u8 *data, int size, int od
                descramble_nordicpro (data, size, odd);
 }
 
-static int read_rom_file (uae_u8 *buf, const struct romdata *rd)
+static int read_rom_file(uae_u8 *buf, const struct romdata *rd, bool rw)
 {
        struct zfile *zf;
        struct romlist *rl = romlist_getrl (rd);
@@ -1929,7 +1929,7 @@ static int read_rom_file (uae_u8 *buf, const struct romdata *rd)
 
        if (!rl || rl->path[0] == '\0')
                return 0;
-       zf = zfile_fopen (rl->path, _T("rb"), ZFD_NORMAL);
+       zf = zfile_fopen (rl->path, rw ? _T("rb+") : _T("rb"), ZFD_NORMAL);
        if (!zf)
                return 0;
        addkeydir (rl->path);
@@ -2005,7 +2005,7 @@ static void alg_descramble(struct romdata *rd, uae_u8 *buf, int size)
        }
 }
 
-struct zfile *read_rom(struct romdata *prd)
+struct zfile *read_rom(struct romdata *prd, bool rw)
 {
        struct romdata *rd2 = prd;
        struct romdata *rd = prd;
@@ -2043,7 +2043,7 @@ struct zfile *read_rom(struct romdata *prd)
                for (i = 0; i < 2; i++) {
                        memset (buf, 0, size);
                        if (!(flags & (ROMTYPE_EVEN | ROMTYPE_ODD))) {
-                               read_rom_file (buf, rd);
+                               read_rom_file(buf, rd, rw);
                                if (flags & ROMTYPE_CD32) {
                                        memcpy (buf2, buf, size);
                                        mergecd32 (buf, buf2, size);
@@ -2053,14 +2053,14 @@ struct zfile *read_rom(struct romdata *prd)
                        } else if (flags & ROMTYPE_QUAD) {
                                if (i == 0) {
                                        for (int k = 0; k < 4; k++) {
-                                               read_rom_file (buf2, rd2 + k + 1);
+                                               read_rom_file(buf2, rd2 + k + 1, rw);
                                                for (j = 0; j < size; j += 4)
                                                        buf[j + k] = buf2[j / 4];
                                        }
                                } else {
                                        for (int kk = 0; kk < 2; kk++) {
                                                for (int k = 0; k < 2; k++) {
-                                                       read_rom_file (buf2, rd2 + k + kk * 2 + 1);
+                                                       read_rom_file(buf2, rd2 + k + kk * 2 + 1, rw);
                                                        for (j = 0; j < size / 2; j += 2) {
                                                                buf[j + k + kk * (rd2->size / 2)] = buf2[j / 2];
                                                        }
@@ -2079,14 +2079,14 @@ struct zfile *read_rom(struct romdata *prd)
                                else
                                        rdpair = rd;
                                if (flags & ROMTYPE_8BIT) {
-                                       read_rom_file (buf2, rd);
+                                       read_rom_file(buf2, rd, rw);
                                        if (flags & ROMTYPE_BYTESWAP)
                                                byteswap (buf2, romsize);
                                        if (flags & ROMTYPE_SCRAMBLED)
                                                descramble (rd, buf2, romsize, odd);
                                        for (j = 0; j < size; j += 2)
                                                buf[j + odd] = buf2[j / 2];
-                                       read_rom_file (buf2, rdpair);
+                                       read_rom_file(buf2, rdpair, rw);
                                        if (flags & ROMTYPE_BYTESWAP)
                                                byteswap (buf2, romsize);
                                        if (flags & ROMTYPE_SCRAMBLED)
@@ -2094,7 +2094,7 @@ struct zfile *read_rom(struct romdata *prd)
                                        for (j = 0; j < size; j += 2)
                                                buf[j + (1 - odd)] = buf2[j / 2];
                                } else {
-                                       read_rom_file (buf2, rd);
+                                       read_rom_file(buf2, rd, rw);
                                        if (flags & ROMTYPE_BYTESWAP)
                                                byteswap (buf2, romsize);
                                        if (flags & ROMTYPE_SCRAMBLED)
@@ -2103,7 +2103,7 @@ struct zfile *read_rom(struct romdata *prd)
                                                buf[j + 2 * odd + 0] = buf2[j / 2 + 0];
                                                buf[j + 2 * odd + 1] = buf2[j / 2 + 1];
                                        }
-                                       read_rom_file (buf2, rdpair);
+                                       read_rom_file(buf2, rdpair, rw);
                                        if (flags & ROMTYPE_BYTESWAP)
                                                byteswap (buf2, romsize);
                                        if (flags & ROMTYPE_SCRAMBLED)
@@ -2233,7 +2233,7 @@ static struct zfile *rom_fopen2(const TCHAR *name, const TCHAR *mode, int mask)
        return f;
 }
 
-struct zfile *read_rom_name (const TCHAR *filename)
+struct zfile *read_rom_name(const TCHAR *filename, bool rw)
 {
        struct zfile *f;
 
@@ -2245,7 +2245,7 @@ struct zfile *read_rom_name (const TCHAR *filename)
                                return f;
                }
        }
-       f = rom_fopen2(filename, _T("rb"), ZFD_NORMAL);
+       f = rom_fopen2(filename, rw ? _T("rb+") : _T("rb"), ZFD_NORMAL);
        if (f) {
                uae_u8 tmp[11] = { 0 };
                zfile_fread(tmp, sizeof tmp, 1, f);
@@ -2598,19 +2598,19 @@ static bool isspecialrom(const TCHAR *name)
        return false;
 }
 
-struct zfile *read_device_from_romconfig(struct romconfig *rc, uae_u32 romtype)
+struct zfile *read_device_from_romconfig(struct romconfig *rc, uae_u32 romtype, bool rw)
 {
        struct zfile *z = NULL;
        if (isspecialrom(rc->romfile))
                return z;
-       z = read_rom_name (rc->romfile);
+       z = read_rom_name(rc->romfile, rw);
        if (z)
                return z;
        if (romtype) {
                struct romlist *rl = getromlistbyromtype(romtype, NULL);
                if (rl) {
                        struct romdata *rd = rl->rd;
-                       z = read_rom(rd);
+                       z = read_rom(rd, rw);
                }
        }
        return z;
@@ -2624,7 +2624,7 @@ struct zfile *read_device_rom(struct uae_prefs *p, int romtype, int devnum, int
                const TCHAR *romname = brc->roms[idx].romfile;
                if (isspecialrom(romname))
                        return NULL;
-               struct zfile *z = read_rom_name (romname);
+               struct zfile *z = read_rom_name (romname, false);
                if (!z && roms) {
                        struct romlist *rl = getromlistbyids(roms, romname);
                        if (rl) {
@@ -2725,13 +2725,16 @@ static struct zfile *parse_trumpcard_driver(struct zfile *z)
        return zd;
 }
 
-bool load_rom_rc(struct romconfig *rc, uae_u32 romtype, int maxfilesize, int fileoffset, uae_u8 *rom, int maxromsize, int flags)
+static bool load_rom_rc1(struct romconfig *rc, uae_u32 romtype, int maxfilesize, int fileoffset, uae_u8 *rom, int maxromsize, int flags, struct zfile **zf)
 {
+       if (zf) {
+               *zf = NULL;
+       }
        if (flags & LOADROM_ONEFILL)
                memset(rom, 0xff, maxromsize);
        if (flags & LOADROM_ZEROFILL)
                memset(rom, 0x00, maxromsize);
-       struct zfile *f = read_device_from_romconfig(rc, romtype);
+       struct zfile *f = read_device_from_romconfig(rc, romtype, zf != NULL);
        if (!f)
                return false;
        TCHAR *ext = _tcsrchr(zfile_getname(f), '.');
@@ -2772,7 +2775,11 @@ bool load_rom_rc(struct romconfig *rc, uae_u32 romtype, int maxfilesize, int fil
        }
        if (f)
                write_log(_T("ROM '%s' loaded, %d bytes.\n"), zfile_getname(f), bytes);
-       zfile_fclose(f);
+       if (!zf) {
+               zfile_fclose(f);
+       } else {
+               *zf = f;
+       }
        int posend = pos;
        if (!(flags & LOADROM_FILL))
                return true;
@@ -2787,6 +2794,19 @@ bool load_rom_rc(struct romconfig *rc, uae_u32 romtype, int maxfilesize, int fil
        return true;
 }
 
+bool load_rom_rc(struct romconfig *rc, uae_u32 romtype, int maxfilesize, int fileoffset, uae_u8 *rom, int maxromsize, int flags)
+{
+       return load_rom_rc1(rc, romtype, maxfilesize, fileoffset, rom, maxromsize, flags, NULL);
+}
+struct zfile *load_rom_rc_zfile(struct romconfig *rc, uae_u32 romtype, int maxfilesize, int fileoffset, uae_u8 *rom, int maxromsize, int flags)
+{
+       struct zfile *zf = NULL;
+       if (!load_rom_rc1(rc, romtype, maxfilesize, fileoffset, rom, maxromsize, flags, &zf)) {
+               return NULL;
+       }
+       return zf;
+}
+
 struct zfile *flashromfile_open(const TCHAR *name)
 {
        struct zfile *f;