rtoss - Rev 336

Subversion Repositories:
Rev:
/**
 * @file        bios.c
 * @brief       Implementation of BIOS
 */


#include "compiler.h"
#include "bios.h"
#include "biosmem.h"
#include "sxsibios.h"
#include "strres.h"
#include "cpucore.h"
#include "pccore.h"
#include "iocore.h"
#include "lio/lio.h"
#include "vram.h"
#include "fdd/fddfile.h"
#include "fdd/fdd_mtr.h"
#include "fdfmt.h"
#include "dosio.h"
#include "keytable.res"
#include "itfrom.res"
#include "startup.res"
#include "biosfd80.res"


#define BIOS_SIMULATE

static const char neccheck[] = "Copyright (C) 1983 by NEC Corporation";

typedef struct {
        UINT8   port;
        UINT8   data;
} IODATA;

static const IODATA iodata[] = {
                        // DMA
                                {0x29, 0x00}, {0x29, 0x01}, {0x29, 0x02}, {0x29, 0x03},
                                {0x27, 0x00}, {0x21, 0x00}, {0x23, 0x00}, {0x25, 0x00},
                                {0x1b, 0x00}, {0x11, 0x40},

                        // PIT
                                {0x77, 0x30}, {0x71, 0x00}, {0x71, 0x00},
                                {0x77, 0x76}, {0x73, 0xcd}, {0x73, 0x04},
                                {0x77, 0xb6},

                        // PIC
                                {0x00, 0x11}, {0x02, 0x08}, {0x02, 0x80}, {0x02, 0x1d},
                                {0x08, 0x11}, {0x0a, 0x10}, {0x0a, 0x07}, {0x0a, 0x09},
                                {0x02, 0x7d}, {0x0a, 0x71}};

static const UINT8 msw_default[8] =
                                                        {0x48, 0x05, 0x04, 0x00, 0x01, 0x00, 0x00, 0x6e};


static void bios_itfprepare(void) {

const IODATA    *p;
const IODATA    *pterm;

        crtc_biosreset();
        gdc_biosreset();

        p = iodata;
        pterm = iodata + NELEMENTS(iodata);
        while(p < pterm) {
                iocore_out8(p->port, p->data);
                p++;
        }
}

static void bios_memclear(void) {

        ZeroMemory(mem, 0xa0000);
        ZeroMemory(mem + 0x100000, 0x10000);
        if (CPU_EXTMEM) {
                ZeroMemory(CPU_EXTMEM, CPU_EXTMEMSIZE);
        }
        bios0x18_16(0x20, 0xe1);
        ZeroMemory(mem + VRAM0_B, 0x18000);
        ZeroMemory(mem + VRAM0_E, 0x08000);
        ZeroMemory(mem + VRAM1_B, 0x18000);
        ZeroMemory(mem + VRAM1_E, 0x08000);
#if defined(SUPPORT_PC9821)
        ZeroMemory(vramex, sizeof(vramex));
#endif
}

static void bios_reinitbyswitch(void) {

        UINT8   prxcrt;
        UINT8   prxdupd;
        UINT8   biosflag;
        UINT8   extmem;
        UINT8   boot;

        if (!(pccore.dipsw[2] & 0x80)) {
#if defined(CPUCORE_IA32)
                mem[MEMB_SYS_TYPE] = 0x03;              // 80386`
#else
                mem[MEMB_SYS_TYPE] = 0x01;              // 80286
#endif
        }
        else {
                mem[MEMB_SYS_TYPE] = 0x00;              // V30
        }

        mem[MEMB_BIOS_FLAG0] = 0x01;
        prxcrt = 0x08;
        if (!(pccore.dipsw[0] & 0x01)) {                        // dipsw1-1 on
                prxcrt |= 0x40;
        }
        if (gdc.display & (1 << GDCDISP_ANALOG)) {
                prxcrt |= 0x04;                                                 // color16
        }
        if (!(pccore.dipsw[0] & 0x80)) {                        // dipsw1-8 on
                prxcrt |= 0x01;
        }
        if (grcg.chip) {
                prxcrt |= 0x02;
        }
        mem[MEMB_PRXCRT] = prxcrt;

        prxdupd = 0x18;
        if (grcg.chip >= 3) {
                prxdupd |= 0x40;
        }
        if (!(pccore.dipsw[1] & 0x80)) {                        // dipsw2-8 on
                prxdupd |= 0x20;
        }
        mem[MEMB_PRXDUPD] = prxdupd;

        biosflag = 0x20;
        if (pccore.cpumode & CPUMODE_8MHZ) {
                biosflag |= 0x80;
        }
        biosflag |= mem[0xa3fea] & 7;
        if (pccore.dipsw[2] & 0x80) {
                biosflag |= 0x40;
        }
        mem[MEMB_BIOS_FLAG1] = biosflag;
        extmem = pccore.extmem;
        extmem = min(extmem, 14);
        mem[MEMB_EXPMMSZ] = (UINT8)(extmem << 3);
        if (pccore.extmem >= 15) {
                mem[0x0594] = pccore.extmem - 15;
        }
        mem[MEMB_CRT_RASTER] = 0x0f;

        // FDD initialize
        SETBIOSMEM32(MEMD_F2DD_POINTER, 0xfd801ad7);
        SETBIOSMEM32(MEMD_F2HD_POINTER, 0xfd801aaf);
        boot = mem[MEMB_MSW5] & 0xf0;
        if (boot != 0x20) {             // 1MB
                fddbios_equip(3, TRUE);
                mem[MEMB_BIOS_FLAG0] |= 0x02;
        }
        else {                                  // 640KB
                fddbios_equip(0, TRUE);
                mem[MEMB_BIOS_FLAG0] &= ~0x02;
        }
        mem[MEMB_F2HD_MODE] = 0xff;
        mem[MEMB_F2DD_MODE] = 0xff;

#if defined(SUPPORT_CRT31KHZ)
        mem[MEMB_CRT_BIOS] |= 0x80;
#endif
#if defined(SUPPORT_PC9821)
        mem[MEMB_CRT_BIOS] |= 0x04;             // 05/02/03
        mem[0x45c] = 0x40;
#endif

        // FDC
        if (fdc.support144) {
                mem[MEMB_F144_SUP] |= fdc.equip;
        }

        // IDE initialize
        if (pccore.hddif & PCHDD_IDE) {
                mem[MEMB_SYS_TYPE] |= 0x80;             // IDE
                CPU_AX = 0x8300;
                sasibios_operate();
        }
}

static void bios_vectorset(void) {

        UINT    i;

        for (i=0; i<0x20; i++) {
                *(UINT16 *)(mem + (i*4)) = *(UINT16 *)(mem + BIOS_BASE + BIOS_TABLE + (i*2));
                SETBIOSMEM16((i * 4) + 2, BIOS_SEG);
        }
        SETBIOSMEM32(0x1e*4, 0xe8000000);
}

static void bios_screeninit(void) {

        REG8    al;

        al = 4;
        al += (pccore.dipsw[1] & 0x04) >> 1;
        al += (pccore.dipsw[1] & 0x08) >> 3;
        bios0x18_0a(al);
}

static void setbiosseed(UINT8 *ptr, UINT size, UINT seedpos) {

        UINT8   x;
        UINT8   y;
        UINT    i;

        x = 0;
        y = 0;
        for (i=0; i<size; i+=2) {
                x += ptr[i + 0];
                y += ptr[i + 1];
        }
        ptr[seedpos + 0] -= x;
        ptr[seedpos + 1] -= y;
}

void bios_initialize(void) {

        BOOL    biosrom;
        OEMCHAR path[MAX_PATH];
        FILEH   fh;
        UINT    i;
        UINT32  tmp;
        UINT    pos;

        biosrom = FALSE;
        getbiospath(path, str_biosrom, NELEMENTS(path));
        fh = file_open_rb(path);
        if (fh != FILEH_INVALID) {
                biosrom = (file_read(fh, mem + 0x0e8000, 0x18000) == 0x18000);
                file_close(fh);
        }
        if (biosrom) {
                TRACEOUT(("load bios.rom"));
                pccore.rom |= PCROM_BIOS;
                // PnP BIOS‚ð’ׂ·
                for (i=0; i<0x10000; i+=0x10) {
                        tmp = LOADINTELDWORD(mem + 0xf0000 + i);
                        if (tmp == 0x506e5024) {
                                TRACEOUT(("found PnP BIOS at %.5x", 0xf0000 + i));
                                mem[0xf0000 + i] = 0x6e;
                                mem[0xf0002 + i] = 0x24;
                                break;
                        }
                }
        }
        else {
                CopyMemory(mem + 0x0e8000, nosyscode, sizeof(nosyscode));
                if ((!biosrom) && (!(pccore.model & PCMODEL_EPSON))) {
                        CopyMemory(mem + 0xe8dd8, neccheck, 0x25);
                        pos = LOADINTELWORD(itfrom + 2);
                        CopyMemory(mem + 0xf538e, itfrom + pos, 0x27);
                }
                setbiosseed(mem + 0x0e8000, 0x10000, 0xb1f0);
        }

#if defined(SUPPORT_PC9821)
        //getbiospath(path, OEMTEXT("bios9821.rom"), sizeof(path));
        //fh = file_open_rb(path);
        //if (fh != FILEH_INVALID) {
        //      if (file_read(fh, mem + 0x0d8000, 0x10000) == 0x10000) {
        //              // IDE BIOS‚ð’ׂ·
        //              TRACEOUT(("load bios9821.rom"));
        //              STOREINTELWORD(mem + 0x0d8009, 0);
        //      }
        //      file_close(fh);
        //}
        getbiospath(path, OEMTEXT("pc98bank3.bin"), sizeof(path));
        fh = file_open_rb(path);
        if (fh != FILEH_INVALID) {
                if (file_read(fh, mem + 0x0d8000, 0x8000) == 0x8000) {
                        // IDE BIOS‚ð’ׂ·
                        TRACEOUT(("load pc98bank3.bin"));
                        STOREINTELWORD(mem + 0x0d8009, 0);
                }
                file_close(fh);
        }
        /*getbiospath(path, OEMTEXT("b0.rom"), sizeof(path));
        fh = file_open_rb(path);
        if (fh != FILEH_INVALID) {
                if (file_read(fh, mem + 0x0c0000, 0x18000) == 0x18000) {
                }
                file_close(fh);
        }*/

#if defined(BIOS_SIMULATE)
        mem[0xf8e80] = 0x98;
        mem[0xf8e81] = 0x21;
        mem[0xf8e82] = 0x1f;
        mem[0xf8e83] = 0x20;    // Model Number?
        mem[0xf8e84] = 0x2c;
        mem[0xf8e85] = 0xb0;

        //mem[0xf8eaf] = 0x21;          // <- ‚±‚ê‚Á‚ĉ½‚¾‚Á‚¯H
#endif
#endif
        //fh = file_open_c("itf.rom");
        //if (fh != FILEH_INVALID) {
        //      file_read(fh, mem + ITF_ADRS, 0x8000);
        //      file_close(fh);
        //      TRACEOUT(("load itf.rom"));
        //}

#if defined(BIOS_SIMULATE)
        CopyMemory(mem + BIOS_BASE, biosfd80, sizeof(biosfd80));
        if (!biosrom) {
                lio_initialize();
        }
       
        for (i=0; i<8; i+=2) {
                STOREINTELWORD(mem + 0xfd800 + 0x1aaf + i, 0x1ab7);
                STOREINTELWORD(mem + 0xfd800 + 0x1ad7 + i, 0x1adf);
                STOREINTELWORD(mem + 0xfd800 + 0x2361 + i, 0x1980);
        }
        CopyMemory(mem + 0xfd800 + 0x1ab7, fdfmt2hd, sizeof(fdfmt2hd));
        CopyMemory(mem + 0xfd800 + 0x1adf, fdfmt2dd, sizeof(fdfmt2dd));
        CopyMemory(mem + 0xfd800 + 0x1980, fdfmt144, sizeof(fdfmt144));

        SETBIOSMEM16(0xfffe8, 0xcb90);
        SETBIOSMEM16(0xfffec, 0xcb90);
        mem[0xffff0] = 0xea;
        STOREINTELDWORD(mem + 0xffff1, 0xfd800000);

        CopyMemory(mem + 0x0fd800 + 0x0e00, keytable[0], 0x300);
       
        CopyMemory(mem + ITF_ADRS, itfrom, sizeof(itfrom));
        mem[ITF_ADRS + 0x7ff0] = 0xea;
        STOREINTELDWORD(mem + ITF_ADRS + 0x7ff1, 0xf8000000);
        if (pccore.model & PCMODEL_EPSON) {
                mem[ITF_ADRS + 0x7ff1] = 0x04;
        }
        else if ((pccore.model & PCMODELMASK) == PCMODEL_VM) {
                mem[ITF_ADRS + 0x7ff1] = 0x08;
        }
        setbiosseed(mem + 0x0f8000, 0x08000, 0x7ffe);
#else
        fh = file_open_c("itf.rom");
        if (fh != FILEH_INVALID) {
                file_read(fh, mem + ITF_ADRS, 0x8000);
                file_close(fh);
                TRACEOUT(("load itf.rom"));
        }
#endif

        CopyMemory(mem + 0x1c0000, mem + ITF_ADRS, 0x08000);
        CopyMemory(mem + 0x1e8000, mem + 0x0e8000, 0x10000);
}


static void bios_itfcall(void) {

        int             i;

        bios_itfprepare();
        bios_memclear();
        bios_vectorset();
        bios0x09_init();
        bios_reinitbyswitch();
        bios0x18_0c();

        if (!np2cfg.ITF_WORK) {
                for (i=0; i<8; i++) {
                        mem[MEMX_MSW + (i*4)] = msw_default[i];
                }
                CPU_FLAGL |= C_FLAG;
        }
        else {
                CPU_DX = 0x43d;
                CPU_AL = 0x10;
                mem[0x004f8] = 0xee;            // out  dx, al
                mem[0x004f9] = 0xea;            // call far
                SETBIOSMEM16(0x004fa, 0x0000);
                SETBIOSMEM16(0x004fc, 0xffff);
                CPU_FLAGL &= ~C_FLAG;
        }
}


UINT MEMCALL biosfunc(UINT32 adrs) {

        UINT16  bootseg;

        if ((CPU_ITFBANK) && (adrs >= 0xf8000) && (adrs < 0x100000)) {
                // for epson ITF
                return(0);
        }

        //TRACEOUT(("biosfunc(%x, %x)", adrs, adrs-BIOS_BASE));
#if defined(CPUCORE_IA32) && defined(TRACE)
        if (CPU_STAT_PAGING) {
                UINT32 pde = MEMP_READ32(CPU_STAT_PDE_BASE);
                if (!(pde & CPU_PDE_PRESENT)) {
                        TRACEOUT(("page0: PTE not present"));
                }
                else {
                        UINT32 pte = MEMP_READ32(pde & CPU_PDE_BASEADDR_MASK);
                        if (!(pte & CPU_PTE_PRESENT)) {
                                TRACEOUT(("page0: not present"));
                        }
                        else if (pte & CPU_PTE_BASEADDR_MASK) {
                                TRACEOUT(("page0: physical address != 0 (pte = %.8x)", pte));
                        }
                }
        }
#endif

        switch(adrs) {
                case BIOS_BASE + BIOSOFST_ITF:          // ƒŠƒZƒbƒg
                        bios_itfcall();
                        return(1);

                case BIOS_BASE + BIOSOFST_INIT:         // ƒu[ƒg
#if 1           // for RanceII
                        bios_memclear();
#endif
                        bios_vectorset();
#if 1
                        bios0x09_init();
#endif
                        bios_reinitbyswitch();
                        bios_vectorset();
                        bios_screeninit();
                        if (((pccore.model & PCMODELMASK) >= PCMODEL_VX) &&
                                (pccore.sound & 0x7e)) {
                                iocore_out8(0x188, 0x27);
                                iocore_out8(0x18a, 0x3f);
                        }
                        return(1);

                case BIOS_BASE + BIOSOFST_09:
                        CPU_REMCLOCK -= 500;
                        bios0x09();
                        return(1);

                case BIOS_BASE + BIOSOFST_0c:
                        CPU_REMCLOCK -= 500;
                        bios0x0c();
                        return(1);

                case BIOS_BASE + BIOSOFST_12:
                        CPU_REMCLOCK -= 500;
                        bios0x12();
                        return(1);

                case BIOS_BASE + BIOSOFST_13:
                        CPU_REMCLOCK -= 500;
                        bios0x13();
                        return(1);

                case BIOS_BASE + BIOSOFST_18:
                        CPU_REMCLOCK -= 200;
                        bios0x18();
                        return(1);

                case BIOS_BASE + BIOSOFST_19:
                        CPU_REMCLOCK -= 200;
                        bios0x19();
                        return(1);

                case BIOS_BASE + BIOSOFST_CMT:
                        CPU_REMCLOCK -= 200;
                        bios0x1a_cmt();
                        return(0);                                                                                      // return(1);

                case BIOS_BASE + BIOSOFST_PRT:
                        CPU_REMCLOCK -= 200;
                        bios0x1a_prt();
                        return(1);

                case BIOS_BASE + BIOSOFST_1b:
                        CPU_STI;
                        CPU_REMCLOCK -= 200;
                        bios0x1b();
                        return(1);

                case BIOS_BASE + BIOSOFST_1c:
                        CPU_REMCLOCK -= 200;
                        bios0x1c();
                        return(1);

                case BIOS_BASE + BIOSOFST_1f:
                        CPU_REMCLOCK -= 200;
                        bios0x1f();
                        return(1);

                case BIOS_BASE + BIOSOFST_WAIT:
                        CPU_STI;
                        return(bios0x1b_wait());                                                                // ver0.78

                case 0xfffe8:                                   // ƒu[ƒgƒXƒgƒ‰ƒbƒvƒ[ƒh
                        CPU_REMCLOCK -= 2000;
                        bootseg = bootstrapload();
                        if (bootseg) {
                                CPU_STI;
                                CPU_CS = bootseg;
                                CPU_IP = 0x0000;
                                return(1);
                        }
                        return(0);

                case 0xfffec:
                        CPU_REMCLOCK -= 2000;
                        bootstrapload();
                        return(0);
        }

        if ((adrs >= 0xf9950) && (adrs <= 0x0f9990) && (!(adrs & 3))) {
                CPU_REMCLOCK -= 500;
                bios_lio((REG8)((adrs - 0xf9950) >> 2));
        }
        else if (adrs == 0xf9994) {
                if (nevent_iswork(NEVENT_GDCSLAVE)) {
                        CPU_IP--;
                        CPU_REMCLOCK = -1;
                        return(1);
                }
        }
        return(0);
}