From 02a2dcac1a41872e1fec6d3b37ddd7ecae57eae4 Mon Sep 17 00:00:00 2001 From: "Christian A. Weber" Date: Thu, 16 Apr 1992 23:00:42 +0000 Subject: Initial revision --- Start.c | 487 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 487 insertions(+) create mode 100644 Start.c (limited to 'Start.c') diff --git a/Start.c b/Start.c new file mode 100644 index 0000000..e0dc229 --- /dev/null +++ b/Start.c @@ -0,0 +1,487 @@ +/**************************************************************************** +** ** +** Start.c - Rettet CHIP-RAM, lädt und startet Exec, Exit. ** +** ** +***************************************************************************** +** ** +** Modification History ** +** -------------------- ** +** ** +** 19-May-89 CHW Created this file from Auto/Start.S ** +** 04-Jun-89 CHW Testet jetzt ob RAMDisk vorhanden ist ** +** 20-Jun-89 CHW Unterstützt jetzt 1MB CHIP-RAM wenn man's hat ** +** 21-Jun-89 CHW ENV-Variable 'RAMDISKBASE' implementiert ** +** 27-Jun-89 CHW Converted to genim2 ** +** 24-Aug-89 CHW Disk-Version implemented ** +** 27-Nov-89 CHW FastRAM implemented ** +** 15-Dec-89 CHW VBR wird nach 0 gelegt ** +** 30-Jan-90 CHW 1MB ChipRAM wird bei $a0000 statt $90000 getestet ** +** 03-Apr-90 CHW CiaKick eingebaut ** +** 24-Jul-90 CHW NoSave option eingebaut ** +** 03-Sep-90 CHW C-Version, ARP Parser, variable MemSize eingebaut ** +** 01-Oct-90 CHW CHIPSIZE-Option funktioniert jetzt ** +** 17-Oct-90 CHW CHIPSIZE-Option funktioniert wirklich :-) ** +** 23-Feb-91 CHW Läuft jetzt mit dem 2.0 ramdrive.device ** +** 09-May-91 RHS RamDrive Grösse wird jetzt richtig gelesen ** +** 16-Jun-91 CHH TimerB Bug behoben. ** +** 16-Jun-91 CHW/CHH Läuft jetzt unter 2.0 ("chip memory" :-() ** +** ** +****************************************************************************/ + +#define VERBOSE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* z.B. für __builtin_memcpy */ +#include /* Für getreg und so */ + +#include + +extern void exit(long); + +extern struct ExecBase *SysBase; +extern struct DosLibrary *DOSBase; +extern BPTR StdErr; /* Standard Error output stream */ +extern BYTE NewOS; +extern struct Custom __far custom; + +extern char ExecModuleStart,ExecModuleEnd; + +struct GfxBase *GfxBase; +struct IntuitionBase *IntuitionBase; + +char ident[] = "$VER: Exec V4.5 (" __DATE__ ") by Christian A. Weber"; +char CLI_Template[] = "NS=NOSAVE/S,NF=NOFAST/S,CS=CHIPSIZE/N"; +char CLI_Help[] = "Usage: Start [NOSAVE] [NOFAST] [CHIPSIZE size]"; +struct +{ + LONG NoSave; + LONG NoFast; + LONG *ChipSizePtr; +} argv; + + +/***************************************************************************/ + +#define ABORT 0x1FFFFA /* Am Ende des CHIP RAMs */ +#define DISKMAGIC 0x43485700 /* Currently 'CHW',0 */ +#define INITMAGIC 0x494E4954 /* 'INIT' */ +#define FFSMAGIC 0x444f5301 /* 'DOS',1 */ +#define local + +struct RUN /* 2.0 RAD Unit-Struktur */ +{ + struct MinNode Node; + void *MemPtr; + UWORD MatchWord; +}; + +struct Mem +{ + struct Mem *Next; + void *Address; + ULONG Size; +} *chipmemlist; /* Liste der geretteten CHIP-Blöcke */ + +UBYTE *radmem; /* Startadresse der RAD-Disk */ +ULONG radsize; /* Grösse der RAD-Disk */ +ULONG radunit; /* Unit-Nummer der RAD-Disk */ + +UBYTE *fastbase; /* Startadresse des FAST-RAMs für Exec */ +LONG fastsize; /* Grösse des FAST-RAMs für Exec */ + +UWORD dmaconsave,intenasave; +ULONG attnflags,vblankfreq,sysbplcon0; +ULONG oldcacr,oldvbr; + +ULONG oldssp,oldusp; /* Gerettete Supervisor- und User-Stackpointer */ +ULONG stacktop; /* Obergrenze des Chip-RAMs für Exec */ + +ULONG GetVBR(void) { return 0; } /* Macht das Sinn?? */ +void SetVBR(ULONG vbr) { } + + +#ifdef DEBUG +/***************************************************************************/ +/* Auf Maustaste warten und dabei Farbe ausgeben */ + +local void Maus(UWORD col) +{ + LONG i; + while((*(UBYTE *)0xbfe001)&0x40) + custom.color[0]=col; + while(!((*(UBYTE *)0xbfe001)&0x40)) + ; + for(i=0; i<200000; ++i) + custom.color[0]=(UWORD)i; + custom.color[0]=0; +} +#endif + +/***************************************************************************/ +/* Gerettetes CHIP-RAM zurückkopieren */ + +local void RestoreChipRAM(void) +{ + struct Mem *mc; + + for(mc=chipmemlist; mc; mc=mc->Next) + memcpy(mc->Address,mc+1,mc->Size); +} + +/***************************************************************************/ +/* Save-Buffers des CHIP-RAMs freigeben */ + +local void FreeChipRAMSaveBuffers(void) +{ + struct Mem *mc,*next; + LONG size=0; + + for(mc=chipmemlist; mc; mc=next) + { + size+=mc->Size; + next=mc->Next; + FreeMem(mc,mc->Size+sizeof(*mc)); + } + chipmemlist = NULL; + printf("Saved Chip-RAM = %ld bytes.\n",size); +} + +/***************************************************************************/ +/* Alles allozierte CHIP-RAM retten und in eine Liste eintragen */ + +local BOOL SaveChipRAM(void) +{ + struct MemHeader *mrh; + struct MemChunk *mc; + struct Mem *dc, *olddc = (struct Mem *)&chipmemlist; + ULONG last=0; + + if(!(mrh=(struct MemHeader *)FindName(&SysBase->MemList,"Chip Memory"))) + { + if(!(mrh=(struct MemHeader *)FindName(&SysBase->MemList,"chip memory"))) + { + Enable(); + DisownBlitter(); + Puts("Can't find the Chip Memory header"); + return FALSE; + } + } + + for (mc = mrh->mh_First;; mc=mc->mc_Next) + { + ULONG size; + if (mc == NULL) + mc = (struct MemChunk *)(SysBase->MaxLocMem - sizeof(*mc)); + + size = (ULONG)mc - (ULONG)last + sizeof(*mc); + if ((ULONG)last < (ULONG)mc) /* avoid crash on A4000 emu */ + break; + +#ifdef VERBOSE + printf("$%06lx-$%06lx (%lu bytes)", last, last+size-1, size); +#endif + + if (dc = AllocMem(size + sizeof(struct Mem), MEMF_FAST)) + { +#ifdef VERBOSE + printf("\t -> $%08lx\n", dc+1); +#endif + dc->Next=NULL; + dc->Address=(void *)last; + dc->Size=size; + CopyMem((void *)last,(void *)(dc+1),size); + last=(ULONG)mc+mc->mc_Bytes; + olddc->Next=dc; olddc=dc; + + if(mc==(struct MemChunk *)(SysBase->MaxLocMem-sizeof(*mc))) + break; + } + else + { + Enable(); + DisownBlitter(); + printf("Can't allocate %lu bytes FAST RAM\n",size+sizeof(struct Mem)); + FreeChipRAMSaveBuffers(); + return FALSE; + } + } + + return TRUE; +} + + +/***************************************************************************/ +/* CIA-Resource ankicken */ + +local void KickResource(char *name) +{ + UBYTE *ciabase=(UBYTE *)FindName(&SysBase->ResourceList,name); + ciabase[0x29] = 0x7F; /* Alle Interrupt-Request-Bits setzen */ +} + +/***************************************************************************/ +/* Alles freigeben, back to DOS */ + +__saveds void ExitRoutine(ULONG D0, ULONG D1, void *A0, void *A1) +{ + int i; + static char text[100]; + putreg(REG_A7,oldusp-256); /* Temporärer Stack auf unserem Userstack */ + custom.intena = 0x7FFF; /* Alle Interrupts sperren */ + custom.dmacon = 0x7FFF; /* DMA abschalten */ + custom.color[0] = 0x173; /* Grünlich */ + + strcpy(text,*(void **)0x110); /* ROMCrack-Text retten */ +#if 0 + memset(NULL,0xAA,stacktop); /* CHIP-RAM löschen mit $AA */ +#endif + custom.color[0] = 0x713; /* Rötlich */ + RestoreChipRAM(); /* Und CHIP-RAM wieder restoren */ + + /* AB HIER IST DAS BETRIEBSSYSTEM WIEDER VORHANDEN */ + + UserState((void *)oldssp); /* Zurück in den Usermode */ + + custom.cop1lc = (ULONG)GfxBase->copinit; /* Bild wieder einschalten */ + custom.dmacon = dmaconsave | DMAF_SETCLR; /* Original dmacon zurückholen */ + custom.intena = intenasave | INTF_SETCLR; /* Dito mit intena */ + + for(i=0; i<8; ++i) + custom.spr[i].dataa = custom.spr[i].datab=0; + + SetVBR(oldvbr); + SetCACR(oldcacr); + + WaitBlit(); + DisownBlitter(); + Enable(); + RemakeDisplay(); + + FreeChipRAMSaveBuffers(); /* Chip-SaveBuffer freigeben */ + + if (fastbase) + { + FreeMem(fastbase,fastsize); + fastbase=NULL; + } + + KickResource(CIABNAME); /* CIA-Resources ankicken (alle Interrupts auslösen) */ + KickResource(CIAANAME); + + *(UBYTE *)0xbfed01=0x82; + + printf("Last message: %s\nD0=%08lx D1=%08lx A0=%08lx A1=%08lx\n",text,D0,D1,A0,A1); + + CloseLibrary((struct Library *)IntuitionBase); + CloseLibrary((struct Library *)GfxBase); + + exit(RETURN_OK); +} + +/***************************************************************************/ + +int GetDriveVars(char *drive) +{ + struct DeviceNode *ldn; + int found=FALSE; + + Forbid(); + + for(ldn=BADDR(((struct DosInfo *)BADDR(((struct RootNode *)DOSBase->dl_Root)->rn_Info))->di_DevInfo); + ldn; ldn=BADDR(ldn->dn_Next)) + { + if((ldn->dn_Type==DLT_DEVICE) && (ldn->dn_Startup>0x40)) + { + struct FileSysStartupMsg *fs = BADDR(ldn->dn_Startup); + struct DosEnvec *de = BADDR(fs->fssm_Environ); + char *name=(UBYTE *)BADDR(ldn->dn_Name); + int i; + + for(i=0; i< *name; ++i) + if((name[i+1]&0xDF) != (drive[i]&0xDF)) goto next; + if((drive[i] != ':') && drive[i] != '\0') goto next; + + radsize = ((de->de_HighCyl) - (de->de_LowCyl) +1 )*de->de_BlocksPerTrack*de->de_Surfaces; + radsize <<= 9; /* blocks -> bytes */ + radunit = fs->fssm_Unit; + found=TRUE; + break; + } +next: ; + } + while(ldn=BADDR(ldn->dn_Next)); + + Permit(); + return found; +} + +/***************************************************************************/ +/* Hauptprogramm */ + +LONG Main(LONG arglen, char *argline) +{ + struct IOStdReq RADIO; + ULONG usestacktop; + + Puts(ident+6); + + GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0); + IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0); + + if(GetDriveVars("EXEC:")==FALSE) + { + Puts("Würden Sie bitte gütigerweise das EXEC mounten?!"); + return RETURN_ERROR; + } + + if(!OpenDevice("ramdrive.device",radunit,(struct IORequest *)&RADIO,0)) + { +radok: + /* Startadresse rausfinden */ + radmem = ((struct RUN *)(RADIO.io_Unit))->MemPtr; + if(((struct RUN *)(RADIO.io_Unit))->MatchWord != 0x4AFC) + Puts("WARNING: No resident tag!"); + + CloseDevice((struct IORequest *)&RADIO); + + if(*(ULONG *)radmem == FFSMAGIC) /* 'DOS1' am Anfang ? */ + { + ULONG execentry; + printf("RAMDrive: $%08lx (%ldK)\n",radmem,radsize>>10); + + usestacktop = stacktop = (ULONG)SysBase->MaxLocMem; + + if(argv.ChipSizePtr) + { + usestacktop = *argv.ChipSizePtr << 10; + if((usestacktop<100000) || (usestacktop>stacktop)) + { + Puts("Bad CHIP size, please try again!"); + return RETURN_ERROR; + } + } + + printf("Chip RAM: $00000000 (%ldK)\n",usestacktop>>10); + + + if(!argv.NoFast) /* Grössten freien FAST-RAM-Block reservieren */ + { + if(fastsize = AvailMem(MEMF_FAST|MEMF_LARGEST) & ~0xff) + { + fastsize -= (stacktop-AvailMem(MEMF_CHIP)+10000); + if(fastsize>=10000L) + { + fastbase = AllocMem(fastsize,MEMF_FAST); + printf("Fast RAM: $%08lx (%ldK)\n",fastbase,fastsize>>10); + } + else + { + fastsize=0; + Puts("Not enough FAST RAM available :-)"); + } + } + else Puts("No FAST RAM available."); + } + + + /* AB HIER DARF IM CHIP-RAM NICHTS MEHR VERÄNDERT WERDEN */ + + OwnBlitter(); + WaitBlit(); + Disable(); + + /* System-Status für MyExec merken/retten etc. */ + + dmaconsave = custom.dmaconr&~DMAF_SPRITE; + intenasave = custom.intenar&~INTF_INTEN; + attnflags = SysBase->AttnFlags; + vblankfreq = SysBase->VBlankFrequency; + sysbplcon0 = GfxBase->system_bplcon0; + oldcacr = GetCACR(); /* Altes CACR retten */ + oldvbr = GetVBR(); /* Altes VBR retten */ + oldusp = getreg(REG_A7); /* Alten User-Stack retten */ + + if(!argv.NoSave) /* CHIP-RAM retten */ + { + if(!SaveChipRAM()) return RETURN_ERROR; + } + else Puts("CHIP RAM will not be saved."); + + SetCACR(0L); /* Alle Cache off */ + SetVBR(NULL); /* VBR nach 0 legen */ + + + /* AB HIER KEIN BETRIEBSSYSTEM MEHR!! */ + + oldssp = (ULONG)SuperState(); /* Supervisor-Mode auf Userstack */ + putreg(REG_A7,usestacktop-80); /* Neuer Supervisor-Stackpointer */ + custom.intena = 0x7FFF; /* Interrupts sperren */ + custom.dmacon = 0x7FFF; /* Und DMA auch */ + + custom.color[0] = 0x400; /* Bildschirm dunkelrot */ +#if 0 + memset(NULL,0,usestacktop); /* CHIP-RAM löschen */ +#endif + memcpy(NULL,&ExecModuleStart,&ExecModuleEnd-&ExecModuleStart); + + for(execentry=0; *(ULONG *)execentry!=INITMAGIC; execentry+=2) ; /* Entry suchen */ + execentry += 4; + + if(argv.NoSave) /* Kein Save -> ABORT macht ColdReboot() */ + { + *(ULONG *)ABORT = 0x4EF80008+execentry; /* JMP<<16+4+4=2.Vektor */ + } + else + { + *(UWORD *)ABORT = 0x4EF9; /* Rücksprung-JMP */ + *(void **)(ABORT+2) = (void *)ExitRoutine; /* Cleanup-Routine */ + } + + custom.color[0] = 0xF00; /* Bildschirm rot */ + + { + register void (* __asm init)( + register __d0 LONG, register __d1 LONG, + register __d2 LONG, register __d3 LONG, + register __d4 LONG, + register __a0 void *,register __a1 void *, + register __a2 void *,register __a3 void *); + + init =(void *)execentry; + + if (0) init( attnflags, /* D0 */ + sysbplcon0, /* D1 */ + vblankfreq, /* D2 */ + 0, /* D3 : Product-Code */ + (LONG)"MainPrg", /* D4 : MainPrg-Name */ + radmem, /* A0 : RAD-Startadresse */ + (void *)radsize, /* A1 : RAD-Grösse */ + fastbase, /* A2 : FAST-Startadresse */ + fastbase+fastsize /* A3 : FAST-Endadresse */ + ); + ExitRoutine(); + /* not reached */ + } + } + else Puts("Du musst eine FFS-RamDisk haben, du Depp!"); + } + else if(!OpenDevice("ffsdrive.device",radunit,(struct IORequest *)&RADIO,0)) + goto radok; + else + Puts("Can't open ramdrive.device or ffsdrive.device"); + + return RETURN_OK; +} + -- cgit v1.2.3