This repository has been archived on 2025-05-24. You can view files and clone it, but cannot push or open issues or pull requests.
Files
VARCem/src/rom.c
waltje 8ef54202f9 Another load of cleanups.
Also, all filename handling is now Unicode.
Fixes for many items on the bugs list.
New logo and main icon for the project.
2018-04-01 22:02:37 -04:00

284 lines
6.4 KiB
C

/*
* VARCem Virtual ARchaeological Computer EMulator.
* An emulator of (mostly) x86-based PC systems and devices,
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
* spanning the era between 1981 and 1995.
*
* This file is part of the VARCem Project.
*
* Handling of ROM image files.
*
* NOTES: - pc2386 BIOS is corrupt (JMP at F000:FFF0 points to RAM)
* - pc2386 video BIOS is underdumped (16k instead of 24k)
* - c386sx16 BIOS fails checksum
*
* Version: @(#)rom.c 1.0.10 2018/03/31
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <tommowalker@tommowalker.co.uk>
*
* Copyright 2017,2018 Fred N. van Kempen.
* Copyright 2016-2018 Miran Grca.
* Copyright 2008-2018 Sarah Walker.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the:
*
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include "emu.h"
#include "config.h"
#include "cpu/cpu.h"
#include "mem.h"
#include "rom.h"
#include "plat.h"
/* Return the base path for ROM images. */
wchar_t *
rom_path(wchar_t *str)
{
static wchar_t temp[1024];
/* Get the full path in place. */
wcscpy(temp, emu_path);
wcscat(temp, ROMS_PATH);
plat_append_slash(temp);
wcscat(temp, str);
/* Make sure path is clean. */
pc_path(temp, sizeof_w(temp), NULL);
return(temp);
}
/* Used by the available() functions to check if a file exists. */
int
rom_present(wchar_t *fn)
{
FILE *f;
f = plat_fopen(rom_path(fn), L"rb");
if (f != NULL) {
(void)fclose(f);
return(1);
}
return(0);
}
/* Read a byte from some area in ROM. */
uint8_t
rom_read(uint32_t addr, void *priv)
{
rom_t *rom = (rom_t *)priv;
#ifdef ROM_TRACE
if (rom->mapping.base==ROM_TRACE)
pclog("ROM: read byte from BIOS at %06lX\n", addr);
#endif
return(rom->rom[addr & rom->mask]);
}
/* Read a word from some area in ROM. */
uint16_t
rom_readw(uint32_t addr, void *priv)
{
rom_t *rom = (rom_t *)priv;
#ifdef ROM_TRACE
if (rom->mapping.base==ROM_TRACE)
pclog("ROM: read word from BIOS at %06lX\n", addr);
#endif
return(*(uint16_t *)&rom->rom[addr & rom->mask]);
}
/* Read a double-word from some area in ROM. */
uint32_t
rom_readl(uint32_t addr, void *priv)
{
rom_t *rom = (rom_t *)priv;
#ifdef ROM_TRACE
if (rom->mapping.base==ROM_TRACE)
pclog("ROM: read long from BIOS at %06lX\n", addr);
#endif
return(*(uint32_t *)&rom->rom[addr & rom->mask]);
}
/* Load a ROM BIOS from its chips, interleaved mode. */
int
rom_load_linear(wchar_t *fn, uint32_t addr, int sz, int off, uint8_t *ptr)
{
FILE *f;
f = plat_fopen(rom_path(fn), L"rb");
if (f == NULL) {
pclog("ROM: image '%ls' not found\n", fn);
return(0);
}
/* Make sure we only look at the base-256K offset. */
if (addr >= 0x40000)
addr = 0;
else
addr &= 0x03ffff;
(void)fseek(f, off, SEEK_SET);
(void)fread(ptr+addr, sz, 1, f);
(void)fclose(f);
return(1);
}
/* Load a ROM BIOS from its chips, linear mode with high bit flipped. */
int
rom_load_linear_inverted(wchar_t *fn, uint32_t addr, int sz, int off, uint8_t *ptr)
{
FILE *f;
f = plat_fopen(rom_path(fn), L"rb");
if (f == NULL) {
pclog("ROM: image '%ls' not found\n", fn);
return(0);
}
/* Make sure we only look at the base-256K offset. */
if (addr >= 0x40000)
addr = 0;
else
addr &= 0x03ffff;
(void)fseek(f, 0, SEEK_END);
if (ftell(f) < sz) {
(void)fclose(f);
return(0);
}
(void)fseek(f, off, SEEK_SET);
(void)fread(ptr+addr+0x10000, sz >> 1, 1, f);
(void)fread(ptr+addr, sz >> 1, 1, f);
(void)fclose(f);
return(1);
}
/* Load a ROM BIOS from its chips, interleaved mode. */
int
rom_load_interleaved(wchar_t *fnl, wchar_t *fnh, uint32_t addr, int sz, int off, uint8_t *ptr)
{
FILE *fl = plat_fopen(rom_path(fnl), L"rb");
FILE *fh = plat_fopen(rom_path(fnh), L"rb");
int c;
if (fl == NULL || fh == NULL) {
if (fl == NULL) pclog("ROM: image '%ls' not found\n", fnl);
else (void)fclose(fl);
if (fh == NULL) pclog("ROM: image '%ls' not found\n", fnh);
else (void)fclose(fh);
return(0);
}
/* Make sure we only look at the base-256K offset. */
if (addr >= 0x40000)
addr = 0;
else
addr &= 0x03ffff;
(void)fseek(fl, off, SEEK_SET);
(void)fseek(fh, off, SEEK_SET);
for (c=0; c<sz; c+=2) {
ptr[addr+c] = fgetc(fl);
ptr[addr+c+1] = fgetc(fh);
}
(void)fclose(fh);
(void)fclose(fl);
return(1);
}
/* Read and initialize an option ROM. */
int
rom_init(rom_t *rom, wchar_t *fn, uint32_t addr, int sz, int mask, int off, uint32_t flags)
{
/* Allocate a buffer for the image. */
rom->rom = malloc(sz);
memset(rom->rom, 0xff, sz);
/* Load the image file into the buffer. */
if (! rom_load_linear(fn, addr, sz, off, rom->rom)) {
/* Nope.. clean up. */
free(rom->rom);
rom->rom = NULL;
return(-1);
}
rom->mask = mask;
mem_mapping_add(&rom->mapping,
addr, sz,
rom_read, rom_readw, rom_readl,
mem_write_null, mem_write_nullw, mem_write_nulll,
rom->rom, flags | MEM_MAPPING_ROM, rom);
return(0);
}
int
rom_init_interleaved(rom_t *rom, wchar_t *fnl, wchar_t *fnh, uint32_t addr, int sz, int mask, int off, uint32_t flags)
{
/* Allocate a buffer for the image. */
rom->rom = malloc(sz);
memset(rom->rom, 0xff, sz);
/* Load the image file into the buffer. */
if (! rom_load_interleaved(fnl, fnh, addr, sz, off, rom->rom)) {
/* Nope.. clean up. */
free(rom->rom);
rom->rom = NULL;
return(-1);
}
rom->mask = mask;
mem_mapping_add(&rom->mapping,
addr, sz,
rom_read, rom_readw, rom_readl,
mem_write_null, mem_write_nullw, mem_write_nulll,
rom->rom, flags | MEM_MAPPING_ROM, rom);
return(0);
}