summaryrefslogtreecommitdiff
path: root/Start.c
diff options
context:
space:
mode:
authorChristian A. Weber <chris@gna.ch>1992-04-16 23:00:42 +0000
committerChristian A. Weber <chris@gna.ch>1992-04-16 23:00:42 +0000
commit02a2dcac1a41872e1fec6d3b37ddd7ecae57eae4 (patch)
tree6c39deb2ce8713b42bad5917b870184ed1d73463 /Start.c
parentab216e437899d244ad2ad43cdf2ad0b66b06ca42 (diff)
downloadgameexec-02a2dcac1a41872e1fec6d3b37ddd7ecae57eae4.tar.gz
gameexec-02a2dcac1a41872e1fec6d3b37ddd7ecae57eae4.tar.bz2
gameexec-02a2dcac1a41872e1fec6d3b37ddd7ecae57eae4.zip
Initial revision
Diffstat (limited to 'Start.c')
-rw-r--r--Start.c487
1 files changed, 487 insertions, 0 deletions
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 <proto/exec.h>
+#include <exec/io.h>
+#include <exec/memory.h>
+#include <exec/execbase.h>
+#include <proto/graphics.h>
+#include <proto/intuition.h>
+#include <graphics/gfxbase.h>
+#include <hardware/custom.h>
+#include <hardware/dmabits.h>
+#include <hardware/intbits.h>
+#include <resources/cia.h>
+#include <dos/dosextens.h>
+#include <dos/filehandler.h>
+#include <string.h> /* z.B. für __builtin_memcpy */
+#include <dos.h> /* Für getreg und so */
+
+#include <chlib.h>
+
+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;
+}
+