sarah-walker-pcem / arculator

Arculator
http://b-em.bbcmicro.com/arculator
GNU General Public License v2.0
56 stars 23 forks source link

Add emulation support for 4MB ROMs #34

Open philpem opened 1 year ago

philpem commented 1 year ago

Trying to load a 4MB ROM normally makes Arculator crash. This change expands the ROM buffer and maps it so that 4MB ROMs may be tested.

This is useful for testing custom RISC OS 3.1 images (e.g. the Stardot unofficial RISC OS 3.20).

Rebase of previous patch on top of Arculator 2.2 code.

This might not be fully correct - comments appreciated. Generally on physical hardware e.g. A4000 a 4MB romset can be fitted but this breaks POSTBox debugging as the address line is reused for POSTBox I/O - this is a RISC OS 3.11 SELFTEST bug not an Arculator one.

If a 2MB romset is loaded, the ROM will be visible twice in the physical memory map due to the topmost address bit being no-connect. With a 4MB romset, the ROM will obviously only appear once.

sarah-walker-pcem commented 1 year ago

Commit message mentions mapping changes but I don't see any in this change?

philpem commented 10 months ago

I'm not sure what mapping changes would be required - I'm not sure how that works in Arculator (I've not been able to find the relevant code).

Looking at the A3000 TRM (https://chrisacorns.computinghistory.org.uk/docs/Acorn/Manuals/Acorn_A3000TRM.pdf) the ROM is mapped into a 12MB block between &3400000 and &3FFFFFF. On the A4 (http://classicacorn.computinghistory.org.uk/32bit_service_manuals/A4trm.pdf) the ROM is segmented - Fifth Column ROM is from &3400000 to &3800000 (4MB) and RISC OS ROM is from &3800000 to &3FFFFFF (4MB).

The only bit that needs to be handled is ROM wrapping: if a 2MB ROM is loaded, the ROM will appear twice in the "RISC OS ROM space) to fill the 4MB, because the 2MB ROM doesn't have the uppermost address bit. A 4MB ROM would just appear linearly in that space.

It looks like this would need changes to this block in meminit():

    for (c = 0x3800; c < 0x4000; c++)
        mempoint[c] = ((uint8_t *)&rom[(c & 0x1FF) << 10]) - (c << 12);
    for (c = 0x3fc0; c < 0x4000; c++) /*Map support ROM at end of address space*/
        memstat[c] = support_rom_enabled ? 0 : 5;

But I'm not sure what changes - the assignment to "mempoint" is a bit tricky to figure out. It seems like "mempoint" represents the physical memory map of the processor with the bottom 12 bits dropped (i.e. 4K pages).

I'm also not quite sure what the code in loadrom() which loads the ROMs is trying to achieve (romload.c) - but it looks like it may be assuming the ROMs are 2MB:

225 »···»···fseek(f,0,SEEK_SET);
226 //                rpclog("Loading %s %08X %08X\n",romfns[c],len,pos);
227 »···»···if ((pos + len) > 0x200000)
228 »···»···»···len = 0x200000 - pos;
229 »···»···if (len > 0)
230 »···»···»···fread(&romb[pos],len,1,f);
231 »···»···fclose(f);
232 »···»···pos+=len;
233 »···»···if (pos >= 0x200000)
234 »···»···»···break;

Agree that more work is needed but I'm not quite sure what.