diff options
author | Christian A. Weber <chris@gna.ch> | 1992-04-16 23:00:42 +0000 |
---|---|---|
committer | Christian A. Weber <chris@gna.ch> | 1992-04-16 23:00:42 +0000 |
commit | 02a2dcac1a41872e1fec6d3b37ddd7ecae57eae4 (patch) | |
tree | 6c39deb2ce8713b42bad5917b870184ed1d73463 | |
parent | ab216e437899d244ad2ad43cdf2ad0b66b06ca42 (diff) | |
download | gameexec-02a2dcac1a41872e1fec6d3b37ddd7ecae57eae4.tar.gz gameexec-02a2dcac1a41872e1fec6d3b37ddd7ecae57eae4.tar.bz2 gameexec-02a2dcac1a41872e1fec6d3b37ddd7ecae57eae4.zip |
Initial revision
-rw-r--r-- | BootBlock | bin | 0 -> 1024 bytes | |||
-rw-r--r-- | CDTV.S | 145 | ||||
-rw-r--r-- | CDisk.S | 1123 | ||||
-rw-r--r-- | Documentation/GameExec.doc | 158 | ||||
-rw-r--r-- | Documentation/README | 70 | ||||
-rw-r--r-- | EndLabel.S | 14 | ||||
-rw-r--r-- | Exec.S | 816 | ||||
-rw-r--r-- | FFS.S | 254 | ||||
-rw-r--r-- | FinalBooter.S | 312 | ||||
-rw-r--r-- | Keyboard.S | 423 | ||||
-rw-r--r-- | LoadSeg.S | 211 | ||||
-rw-r--r-- | Makefile | 110 | ||||
-rw-r--r-- | Memory.S | 416 | ||||
-rw-r--r-- | MyExec.i | 431 | ||||
-rw-r--r-- | PPDecrunch.S | 151 | ||||
-rw-r--r-- | RawDoFmt.S | 351 | ||||
-rw-r--r-- | Rnd.S | 55 | ||||
-rw-r--r-- | SCOPTIONS | 24 | ||||
-rw-r--r-- | Start.c | 487 | ||||
-rw-r--r-- | SysCDisk.S | 303 | ||||
-rw-r--r-- | SysStart.c | 220 | ||||
-rw-r--r-- | protcustom.i | 125 | ||||
-rw-r--r-- | relcustom.i | 168 | ||||
-rw-r--r-- | zeropage.i | 39 |
24 files changed, 6406 insertions, 0 deletions
diff --git a/BootBlock b/BootBlock Binary files differnew file mode 100644 index 0000000..576e1f1 --- /dev/null +++ b/BootBlock @@ -0,0 +1,145 @@ + + IDNT CDTV + SECTION text,CODE + + INCLUDE "MyExec.i" + INCLUDE "exec/macros.i" + INCLUDE "exec/io.i" + + XREF @CreateIO,@DeleteIO,_RawPrintfFunc + XDEF InitCDFunc,ExitCDFunc,PlayCDTrackFunc + XDEF WaitCDTrackFunc + +CD_PLAYTRACK: EQU 43 +CD_MUTE: EQU 56 + +***************************************************************************** +* CDTV-IORequest erstellen und Device öffnen + +InitCDFunc: movem.l d1/a0-a2/a6,-(SP) + + moveq.l #IOSTD_SIZE,d0 + bsr @CreateIO + move.l d0,CDIOReq + beq.s 1$ ; No mem ---> + movea.l d0,a2 + + moveq #0,d0 ; Unit + moveq #0,d1 ; Flags + lea CDTVName(PC),a0 + movea.l a2,a1 + movea.l 4,a6 + JSRLIB OpenDevice + tst.l d0 ; Device OK ? + beq.s 1$ ; yep ---> + bsr.s ExitCDFunc ; Sonst Request freigeben + bra.s 2$ +1$: + movea.l CDIOReq,a1 + move.w #CD_MUTE,IO_COMMAND(a1) + move.l #$7fff,IO_OFFSET(a1) + move.l #1,IO_LENGTH(a1) + move.l #0,IO_DATA(a1) + JSRLIB DoIO + + pea CDDevOKText(PC) + bsr _RawPrintfFunc + addq #4,SP +2$: + movem.l (SP)+,d1/a0-a2/a6 + rts + +***************************************************************************** +* CDTV-Resourcen wieder freigeben + +ExitCDFunc: movem.l d1-d2/a0-a1/a6,-(SP) + + move.l CDIOReq,d2 + beq.s 2$ + movea.l d2,a1 + tst.l IO_DEVICE(a1) + ble.s 1$ + movea.l 4,a6 + JSRLIB CloseDevice +1$: + movea.l d2,a1 ; IO-Request + bsr @DeleteIO ; freigeben + clr.l CDIOReq ; Wichtig! +2$: + movem.l (SP)+,d1-d2/a0-a1/a6 + rts + +***************************************************************************** +* CDTV-Track abspielen + +PlayCDTrackFunc: + movem.l d1-d3/a0-a1/a6,-(SP) + + move.l CDIOReq,-(SP) + move.l d0,-(SP) + pea PlayText(PC) + bsr _RawPrintfFunc + lea 12(SP),SP + + movea.l 4,a6 + move.l CDIOReq,d3 + beq.s 2$ + + ;; movea.l d3,a1 + ;; cmpi.w #CD_PLAYTRACK,IO_COMMAND(a1) ; Schon initialisiert ? + ;; bne.s 1$ ; nein ---> Nicht warten + ;; JSRLIB AbortIO + bsr.s WaitCDTrackFunc +1$: + movea.l d3,a1 + move.w #CD_PLAYTRACK,IO_COMMAND(a1) + move.l d0,IO_OFFSET(a1) ; Gewünschter Track + clr.l IO_LENGTH(a1) + clr.l IO_DATA(a1) + JSRLIB SendIO +2$: + movem.l (SP)+,d1-d3/a0-a1/a6 + rts + +***************************************************************************** +* Auf CD warten + +WaitCDTrackFunc: + movem.l d0-d3/a0-a1/a6,-(SP) + + movea.l 4,a6 + move.l CDIOReq,d3 + beq.s 2$ + + pea WaitText(PC) + bsr _RawPrintfFunc + addq #4,SP + + movea.l d3,a1 + cmpi.w #CD_PLAYTRACK,IO_COMMAND(a1) ; Schon initialisiert ? + bne.s 1$ ; nein ---> Nicht warten + JSRLIB WaitIO +1$: + pea WaitFinText(PC) + bsr _RawPrintfFunc + addq #4,SP +2$: + movem.l (SP)+,d0-d3/a0-a1/a6 + rts + +***************************************************************************** + +CDTVName: dc.b "cdtv.device",0 + +CDDevOKText: dc.b "CDTV device OK",13,10,0 +PlayText: dc.b "PlayCDTrack(%ld), req=$%08lx",13,10,0 +WaitText: dc.b "Waiting for audio to finish ... ",0 +WaitFinText: dc.b "Done.",13,10,0 + + EVEN + + SECTION bss,BSS +CDIOReq: ds.l 1 + + END + @@ -0,0 +1,1123 @@ +***************************************************************************** +** ** +** C - D I S K - The ultimate Amiga Disk Control Software ** +** ** +** (Lese- und Schreibroutinen ohne Blitter) ** +** ** +** by Christian A. Weber, Zürich/Switzwerland ** +** ** +***************************************************************************** +** ** +** Modification History ** +** -------------------- ** +** ** +** 13-Jan-88 V0.01 Project BDisk started ** +** 05-Feb-88 V0.04 BDisk Last updated ** +** 27-May-88 V0.10 CDisk created from BDisk ** +** 17-Aug-88 V1.01 First working version ** +** 25-Aug-88 V1.02 Roottrack-bug fixed ** +** 04-Sep-88 V1.03 Disk length set from 6500 to 6650 ** +** 06-Sep-88 V2.01 Write-Routinen implementiert ** +** 30-Oct-88 V2.02 Derselbe Track wird nicht mehr mehrmals gelesen ** +** 22-Nov-88 V2.03 Write-Bug korrigiert ** +** 29-Jan-89 V2.04 Timeouts vergrössert für 68020 ** +** 10-Apr-89 V2.05 Labels angepasst, cleanup etc. ** +** 26-Apr-89 V2.06 Kein 'MotorOff' wenn Unit nicht gefunden ** +** 29-Jun-89 V2.07 Angepasst an Genim2-Assembler ** +** 01-Aug-89 V3.01 Völlig umgekrempelt, läuft jetzt im Interrupt ** +** 27-Aug-89 V3.10 Läuft nun endlich (fast) fehlerfrei im Interrupt ** +** 30-Aug-89 V3.15 RAMDisk-Routinen auch hier eingebaut ** +** 01-Sep-89 V3.20 Unterstützt FFS-RAMDrive ** +** 02-Sep-89 V3.21 ReadyTimeOut implementiert ** +** 27-Nov-89 V3.22 LoadFastFile() implementiert ** +** 21-Mar-90 V3.23 Code aufgeräumt, alte RAM-Disk rausgeworfen ** +** 29-Dec-90 V3.24 Gecrunchte Files werden automatisch entcruncht ** +** 06-May-91 V4.00 Tada! Schreibroutine eingebaut ** +** 16-Apr-92 V4.01 PP_SAVEMARGIN added, PowerPacker jetzt 100% ** +** ** +***************************************************************************** + + IDNT CDisk + SECTION text,CODE + +CRUNCH + +;;DEBUG +;;LIGHTSHOW + + IFD DEBUG +DERR_DRIVENOTREADY: EQU $21 +DERR_DMATIMEOUT: EQU $22 +DERR_NOSYNC: EQU $23 +DERR_BADCHECKSUM: EQU $24 +DERR_BADTRACK: EQU $25 +DERR_WRONGDISK: EQU $26 +DERR_WRONGPRODUCT: EQU $27 + ENDC + +CUSTOMOFFSET: EQU $19BE + + INCLUDE "MyExec.i" + + INCLUDE "relcustom.i" + ;; INCLUDE "protcustom.i" + + INCLUDE "hardware/intbits.i" + INCLUDE "hardware/cia.i" + + IFD RAMVERSION + XREF ProcessFFSPacket ; Für ramdrive.device + ENDC + + IFD CRUNCH + XREF PPDecrunch + ENDC + + XDEF InitDiskFunc ; Disk-System initialisieren + XDEF SetNoDiskHandlerFunc + XDEF ReadFileFunc ; 'Datei' lesen + XDEF LoadFileFunc ; Speicher reservieren & File lesen + XDEF LoadFastFileFunc ; FAST alloc & File lesen + XDEF WriteFileFunc ; 'Datei' schreiben + XDEF SendPacketFunc ; Asynchronen Lese-Request schicken + +*************************************************************************** + +ciabase: EQU $bfd000-$16ff ; scramble disassemblies +a_pra: EQU $bfe001-ciabase +a_talo: EQU $bfe401-ciabase +a_tahi: EQU $bfe501-ciabase +a_icr: EQU $bfed01-ciabase +a_cra: EQU $bfee01-ciabase +b_prb: EQU $bfd100-ciabase +b_icr: EQU $bfdd00-ciabase + +*************************************************************************** + +TIMERRATE: EQU 2836 ; Taktrate der Diskroutine +DMATIME: EQU 25000 ; Max. # Ticks zum Read/Write von 1 Spur +READYTIME: EQU 2800 ; Max. # Ticks bis DriveReady kommt +READBYTES: EQU 6800 ; Anzahl zu lesende MFM-Words +WRITEBYTES: EQU 6300 ; Anzahl zu schreibende MFM-Words ohne Gap +TRACKBUFSIZE: EQU 16300 ; Größe des gesamten Buffers +GAPBYTES: EQU 1664 ; Größe der Track-Gap in Bytes +TRIALS: EQU 5 ; Anzahl Versuche bei r/w error +MAXUNITS: EQU 4 ; Maximale Anzahl Drives + +DISKMAGIC: EQU $43485700 ; Currently 'CHW',0 +FFSMAGIC: EQU $444f5301 ; 'DOS',1 +FN_HEADER: EQU $7f030000 ; Disk <??> Track <2> Offset <0> + +*************************************************************************** + + *** Die Disk-Header-Struktur, wird von Disk eingelesen + + STRUCTURE DiskHeader,0 + + LONG dh_DiskMagic ; Disk-Magic, muss DISKMAGIC sein + WORD dh_ProductKey ; Identifikation des Produkts + WORD dh_DiskNumber ; Nummer der Disk oder 0 = no disk + STRUCT dh_Reserved,8 ; 8 Bytes Future Expansion + + LABEL dh_SIZEOF + +*************************************************************************** + + *** Die Disk-Unit-Struktur, existiert für jedes Laufwerk + + STRUCTURE DiskUnit,0 + + APTR du_MFMBuffer ; Zeiger auf 16K CHIP-RAM + WORD du_DiskNumber ; Disk-Nummer oder 0 wenn ungültig + WORD du_CurrentTrack ; Aktueller TRACK (0..159) + WORD du_DestTrack ; Ziel-Spur + WORD du_TrackSize ; Anzahl Bytes der gelesenen Spur + WORD du_Sync ; Sync-Wert für dieses Drive + LONG du_FileName ; DiskMaker-Filename + APTR du_DestAddr ; Aktuelle Ladeadresse + LONG du_FileSize ; Größe des aktuellen Files + APTR du_ActPacket ; Zeiger auf aktuelles Packet + WORD du_TimeOutCntr ; TimeOut-Zähler für Read + BYTE du_Status ; Siehe DS_ - Definitionen + BYTE du_OnMask ; Motor On, z.B. $01101111 für df1 + BYTE du_OffMask ; Motor Off, z.B. $11101111 für df1 + BYTE du_RetryCntr ; Zähler für Retry + + LABEL du_SIZEOF ; Größe dieser Struktur + + + *** Werte für DiskUnit.du_Status (IN 2ERSCHRITTEN ALS INDEX!!) + +DS_IDLE: EQU 0 ; Unit hat nichts zu tun +DS_RECALIBRATE: EQU 2 ; Unit ist am auf Track 0 zurücksteppen +DS_STEP: EQU 4 ; Laufwerk ist am steppen +DS_SETTLE: EQU 6 ; Laufwerk hat fertiggesteppt, DMA starten +DS_WAITDMA: EQU 8 ; Wir warten auf's Read/Write-DMA-Ende + +DSF_WRITING: EQU $80 ; Schreib-Flag (MUSS $80 sein für tst.b!) + + +*************************************************************************** +** ** +** I N I T D I S K - Disk-System init, Recalibrate, Timer alloc ... ** +** ** +** Parameter : nix ** +** ** +*************************************************************************** + +InitDiskFunc: movem.l d0-d7/a0-a5,-(SP) + + bsr GetD7A4A5 ; Get BitMask,CiaBase,Custom + clr.l InsertDiskRoutine ; InsertDisker retten + + *** UnitPointer-Tabelle löschen + + lea UnitTab(PC),a0 + moveq #16,d0 ; 4 Pointers + jsr meb_ClearMem(a6) ; löschen + + *** MFM-Buffer holen, Track-Gap und ½ Sync erzeugen für Write + + move.l #TRACKBUFSIZE,d0 ; Amount + jsr meb_AllocMem(a6) ; CHIP-RAM reservieren + movea.l d0,a0 ; A0 : MFM-Buffer + lea GAPBYTES(a0),a1 ; Buffer-Start für Read + move.l a1,MFMBuffer + + move.l d7,d0 ; $55555555 + add.l d0,d0 ; $aaaaaaaa + move.w #TRACKBUFSIZE/4-1,d2 +2$: move.l d0,(a0)+ + dbf d2,2$ + move.w #$4489*2,-(a1) ; ½ SYNC + lsr.w (a1) ; gegen die Cracker + + *** Unit-Strukturen für angeschlossene Laufwerke erstellen + +checkdrives: lea UnitTab(PC),a2 ; Zeiger auf Units + moveq #MAXUNITS-1,d3 ; Anzahl Laufwerke zu suchen + move.b #%11110111,d2 ; D2 := Select-Maske DF0 + bra.s 2$ ; DF0 ist immer da + +1$: bsr CheckUnit ; Testen ob Unit angeschlossen + tst.b d0 ; 3.5"-Drive vorhanden ? + bne.s 3$ ; nein ---> + +2$: moveq.l #du_SIZEOF,d0 ; Größe einer Unit + jsr meb_AllocFastClearMem(a6) ; Unit allozieren + movea.l d0,a3 ; Unit merken + move.l a3,(a2)+ ; und in Tabelle eintragen + + move.l #$4489*6337,d0 ; Gegen Cracker + move.l MFMBuffer,du_MFMBuffer(a3) + ;; clr.w du_DiskNumber(a3) ; Keine Disk in diesem Drive + ;; clr.w du_CurrentTrack(a3) + ;; clr.w du_DestTrack(a3) + ;; clr.w du_TrackSize(a3) ; 0 = ungültig + divs.w #6337,d0 ; Gibt $4489 + move.w d0,du_Sync(a3) + ;; move.b #DS_IDLE,du_Status(a3) ; Drive schläft + move.b d2,du_OffMask(a3) + move.b d2,du_OnMask(a3) + bclr.b #CIAB_DSKMOTOR,du_OnMask(a3) + +3$: rol.b #1,d2 ; SEL für nächstes Drive + dbf d3,1$ ; ---> Für alle Drives + + *** Alle Motoren abschalten + + st.b b_prb(a4) ; Deselect all + bsr ShortDelay + move.b #%10000111,b_prb(a4) ; Select all + bsr ShortDelay + st.b b_prb(a4) ; Deselect all + + *** DiskRequest-Liste initialisieren + + lea meb_DiskList(a6),a0 + jsr meb_NewList(a6) + + *** Timer initialisieren, TimerInterrupt-Handler installieren + + lea MyTimerHandler(PC),a0 + move.l a0,meb_CiaATimerAVector(a6) + andi.b #%11100110,a_cra(a4) ; Timer A Continuous + move.b #TIMERRATE&$ff,a_talo(a4) + move.b #TIMERRATE>>8,a_tahi(a4) + ori.b #%00010001,a_cra(a4) ; Timer A ForceLoad|Start + + move.w #$8008,intena(a5) ; PORTS-Interrupt on + move.b #$81,$bfed01 ; Im CIA ICR auch + move.w #$8010,dmacon(a5) ; Disk DMA enable + + movem.l (SP)+,d0-d7/a0-a5 + rts + +*************************************************************************** + + *** Testen ob Laufwerk mit Select-Maske in D2 vorhanden ist + +CheckUnit: lea b_prb(a4),a0 + moveq #$7f,d0 ; Alle Drives deselektieren + move.b d0,(a0) + bsr ShortDelay + and.b d2,d0 ; Select-Bit löschen + move.b d0,(a0) ; Select Drive, Motor on + bsr ShortDelay + st.b (a0) ; Laufwerk deselektieren + bsr ShortDelay + move.b d2,(a0) ; Select Drive, Motor off + bsr ShortDelay + st.b (a0) ; Laufwerk deselektieren + + moveq #31,d1 ; 32 Bits + moveq.l #0,d0 ; Ergebnis löschen +1$: add.l d0,d0 ; Ergebnis 1 nach links + move.b d2,(a0) ; Laufwerk selektieren + bsr ShortDelay + btst.b #5,a_pra(a4) ; Disk Ready ? + beq.s 2$ ; RDY==0 ---> Drive vorhanden + bset #0,d0 ; Sonst Bit 0 in D0 setzen +2$: st.b (a0) ; Motor ausschalten + bsr ShortDelay + dbf d1,1$ ; loop ---> + rts + + +*************************************************************************** +** ** +** S E T N O D I S K H A N D L E R - NoDisk-Handler setzen ** +** ** +** Parameter : A0.L: InsertDisk-Handler oder 0 ** +** ** +*************************************************************************** + +SetNoDiskHandlerFunc: + move.l a0,InsertDiskRoutine + rts + + +*************************************************************************** +** ** +** R E A D F I L E - Datei von Disk an angegebene Adresse laden ** +** ** +** Parameter : D0.L : DiskAdresse (Disk/Track/Offset) der Datei ** +** A0.L : Ladeadresse ** +** ** +** Resultat : nix ** +** ** +*************************************************************************** + +ReadFileFunc: movem.l d1/a0-a1,-(SP) + moveq #0|DPF_REPLYBYTE,d1 ; LESEN + bra.s APost ; Paket aufgeben + + +*************************************************************************** +** ** +** W R I T E F I L E - Existierende 'Datei' auf Disk überschreiben ** +** ** +** Parameter : D0.L : DiskAdresse (Disk/Track/Offset) der Datei ** +** A0.L : Adresse der Daten für das File ** +** ** +** Resultat : nix ** +** ** +*************************************************************************** + +WriteFileFunc: movem.l d1/a0-a1,-(SP) + move.b #DPF_WRITE|DPF_REPLYBYTE,d1 ; SCHREIBEN + bra.s APost ; Paket aufgeben + + +*************************************************************************** +** ** +** L O A D F I L E - Speicher reservieren, Datei von Disk lesen ** +** ** +** Parameter : D0.L : DiskAdresse (Disk/Track/Offset) der Datei ** +** ** +** Resultat : D0.L : Adresse des Files, 0 if error ** +** Z-Bit: gelöscht wenn OK, gesetzt wenn Error ** +** ** +*************************************************************************** + +LoadFileFunc: movem.l d1/a0-a1,-(SP) + moveq #DPF_REPLYBYTE|DPF_ALLOCMEM,d1 ; Packet Flags + bra.s APost ; Paket aufgeben + +LoadFastFileFunc: + movem.l d1/a0-a1,-(SP) + moveq #DPF_REPLYBYTE|DPF_ALLOCFASTMEM,d1 ; Packet Flags + ;; bra.s APost ; Paket aufgeben + + +APost: lea -dp_SIZEOF-2(SP),SP ; DiskPacket erstellen + move.l a0,dp_Address(SP) ; Ladeadresse eintragen + movea.l SP,a0 ; A0 : Packet + move.l d0,dp_FileName(a0) ; Dateinamen eintragen + lea dp_SIZEOF(SP),a1 ; A1 : End-Flag + clr.b (a1) ; löschen + move.l a1,dp_Reply(a0) + move.b d1,dp_Flags(a0) ; DPF_REPLYBYTE [|DPF_WRITE] usw. + bsr.s SendPacketFunc +1$: tst.b (a1) ; Warten bis File geladen/geschrieben + beq.s 1$ + move.l dp_Address(SP),d0 ; Resultat: Adresse + lea dp_SIZEOF+2(SP),SP ; DiskPacket freigeben + movem.l (SP)+,d1/a0-a1 + rts + + +*************************************************************************** +** ** +** S E N D P A C K E T - Asynchronen Read-Request aufgeben ** +** ** +** Parameter : A0.L : Zeiger auf struct DiskPacket ** +** ** +** Resultat : nix ** +** ** +*************************************************************************** + +SendPacketFunc: movem.l d7/a0-a1/a4-a5,-(SP) + bsr GetD7A4A5 ; Für ProcessNextRequest() + movea.l a0,a1 ; Packet + lea meb_DiskList(a6),a0 + jsr meb_AddTail(a6) ; Packet anhängen + bsr.s ProcessNextRequest ; System ankicken + movem.l (SP)+,d7/a0-a1/a4-a5 + rts + + +*************************************************************************** + + *** Nächsten Request aus Diskliste verarbeiten + +ProcessNextRequest: + movem.l d0-d2/a0-a2/a3,-(SP) + move.l ActUnit(PC),d0 ; Working? (tst.l ActUnit(PC)) + bne .EndProcReq ; ja ---> + lea meb_DiskList(a6),a0 + jsr meb_RemHead(a6) ; setzt CCR + beq .EndProcReq ; Kein Request pending ---> + movea.l d0,a2 ; A2 : Aktuelles Packet + + *** Falls RAM-Disk erlaubt: RAMDisk-Request bearbeiten + + moveq.l #0,d2 + move.b dp_FileName(a2),d2 ; D2 : DiskNumber + + IFD RAMVERSION + movea.l a2,a0 ; A0: Packet + movea.l meb_RAMDiskBase(a6),a1 ; Filename=RAM-Basis + cmpi.l #FFSMAGIC,(a1) ; RAM-Disk in Ordnung ? + beq.s 1$ ; ja ---> + MSG <"RAMDISK CORRUPT, A0=PACKET, A1=BASE"> +1$: bsr ProcessFFSPacket ; Packet (A0) bearbeiten (FFS) + bsr ReplyPacket ; Packet (A0) beantworten + bra .EndProcReq ; ---> + ENDC + + *** Drives nach gewünschter Disk absuchen + +.SearchDisk: moveq.l #MAXUNITS-1,d0 ; 4 Units maximal + lea UnitTab(PC),a1 ; Start des Pointer-Arrays +4$: move.l (a1)+,d1 ; Get next unit + beq.s 5$ ; 0 ---> Unit überhüpfen + movea.l d1,a3 + cmp.w du_DiskNumber(a3),d2 ; Disk in diesem Drive ? + beq.s .DiskFound ; ja ---> +5$: dbf d0,4$ ; sonst nächstes Drive testen + + *** Disk nicht gefunden: Header aller Drives einlesen + + moveq.l #MAXUNITS-1,d0 ; 4 Units maximal + lea UnitTab(PC),a1 ; Start des Pointer-Arrays +6$: move.l (a1)+,d1 ; Get next unit + beq.s 7$ ; 0 ---> Unit überhüpfen + movea.l d1,a3 + bsr GetHeader ; DiskHeader einlesen + cmp.w du_DiskNumber(a3),d2 ; Disk in diesem Drive ? + beq.s .DiskFound ; ja ---> +7$: dbf d0,6$ ; sonst nächstes Drive testen + + *** Disk nicht gefunden: User-Routine aufrufen oder weiter probieren + + move.l InsertDiskRoutine(PC),d1 ; von InitDisk() + beq.s 8$ + movea.l d1,a1 + move.l d2,d0 ; Disk-Nummer für User + move.l dp_FileName(a2),d1 ; Filename für User + jsr (a1) ; User-Routine aufrufen +8$: + bra.s .SearchDisk ; ---> Loop + + *** Disk gefunden: Packet an Unit (a3) schicken + +.DiskFound: move.l a2,du_ActPacket(a3) ; Dieses Packet war's! + move.l dp_FileName(a2),du_FileName(a3) + move.l dp_Address(a2),du_DestAddr(a3) + bsr.s StartUnit + +.EndProcReq: movem.l (SP)+,d0-d2/a0-a2/a3 + rts + +*************************************************************************** + + *** Header einer Disk (a3) lesen und eintragen + +GetHeader: movem.l d0-d2/a0-a1,-(SP) + lea -dh_SIZEOF-16(SP),SP ; Platz für Header + + clr.w du_DiskNumber(a3) ; Markierung für RawRead() + move.l #FN_HEADER,du_FileName(a3) ; Header-'Name' + bsr.s StartUnit + + move sr,d0 ; ** DEBUG ** + move #$2000,sr ; ** DEBUG ** +1$: stop #$2000 ; Auf Interrupt warten + cmpi.b #DS_IDLE,du_Status(a3) ; Fertig ? + bne.s 1$ ; nein ---> + move d0,sr ; ** DEBUG ** + + movea.l du_MFMBuffer(a3),a0 + lea 2+16(a0),a0 ; Start des DiskHeaders + movea.l SP,a1 ; Destination + moveq #dh_SIZEOF,d0 ; Anzahl Bytes + bsr MFMDecode + + cmpi.l #DISKMAGIC,dh_DiskMagic(SP) + bne.s 99$ ; Keine CDisk-Disk ---> + move.w meb_ProductCode(a6),d0 + beq.s 2$ ; Produkt-Egal-Magic ---> + cmp.w dh_ProductKey(SP),d0 + bne.s 99$ +2$: move.w dh_DiskNumber(SP),du_DiskNumber(a3) ; Tada! + +99$: lea dh_SIZEOF+16(SP),SP ; Header freigeben + movem.l (SP)+,d0-d2/a0-a1 + rts + + +*************************************************************************** + + *** Unit (a3) starten + +StartUnit: move.l d0,-(SP) + clr.l du_FileSize(a3) ; Länge := 0 + move.b #TRIALS,du_RetryCntr(a3) ; # Versuche setzen + move.w du_FileName(a3),d0 ; Disk# & Track (.W) + andi.w #$ff,d0 + move.w d0,du_DestTrack(a3) + move.b #$7f,b_prb(a4) ; Motor on + bsr ShortDelay + move.b du_OnMask(a3),b_prb(a4) ; Motor on & Select + move.b #DS_STEP,du_Status(a3) ; Schreiten! + tst.w du_CurrentTrack(a3) + bgt.s 1$ ; Spur > 0 ---> + move.b #DS_RECALIBRATE,du_Status(a3) ; 1. Mal: recalibrate +1$: move.l a3,ActUnit ; Tada! + move.l (SP)+,d0 + rts + +*************************************************************************** + + *** Packet (A0) beantworten + +ReplyPacket: movem.l a0-a2,-(SP) + movea.l a0,a2 ; A2 : Packet + + IFD CRUNCH + bclr.b #DPB_CRUNCHED,dp_Flags(a2) + beq.s 1$ + movea.l dp_Address(a2),a0 ; A0 : Start der gecrunchten Daten + move.l dp_FileSize(a2),d0 ; D0 : File-Länge gecruncht + move.l (a0),dp_FileSize(a2) ; Echte Länge für User + bsr PPDecrunch ; File decrunchen +1$: + ENDC + movea.l dp_Reply(a2),a1 ; A1 : User's Reply-Adresse + btst.b #DPB_REPLYHANDLER,dp_Flags(a2) + beq.s 2$ + movea.l a2,a0 ; A0 : Packet für User + jsr (a1) ; ReplyHandler aufrufen + bra.s 99$ ; ---> +2$: + btst.b #DPB_REPLYBYTE,dp_Flags(a2) + beq.s 3$ + st.b (a1) ; ReplyByte setzen + ;; bra.s 99$ ; ---> +3$: +99$: movem.l (SP)+,a0-a2 + rts + + +*************************************************************************** +** ** +** TimerInterrupt-Handler: Kommandos auswerten und ausführen ** +** ** +*************************************************************************** + +MyTimerHandler: movem.l d0-d7/a0-a5,-(SP) + move.l ActUnit(PC),d0 ; Gibt's Arbeit ? + beq.s 99$ ; nein ---> + bsr GetD7A4A5 ; Get BitMask,Custom,CiaBase + movea.l d0,a3 ; a3 : Unit + move.b du_Status(a3),d0 ; Action to take + andi.w #$000f,d0 ; Flag-Bits interessieren nicht + lea .ComTable(PC),a0 ; Command offset table + adda.w 0(a0,d0.w),a0 ; plus actual command offset + IFD LIGHTSHOW + move.w #$ff0,$dff180 + ENDC + jsr (a0) ; Go do the code + IFD LIGHTSHOW + move.w #$000,$dff180 + ENDC +99$: movem.l (SP)+,d0-d7/a0-a5 + rts + +.ComTable: dc.w DoIdle-.ComTable ; DS_IDLE + dc.w DoReCalibrate-.ComTable ; DS_RECALIBRATE + dc.w DoStep-.ComTable ; DS_STEP + dc.w DoSettle-.ComTable ; DS_SETTLE + dc.w DoWaitDMA-.ComTable ; DS_WAITDMA + +*************************************************************************** + + *** Kommando DS_IDLE: nix machen + +DoIdle: + IFD LIGHTSHOW + move.w #$f00,color(a5) ; rot + ENDC + rts + +*************************************************************************** + + *** Kommando DS_RECALIBRATE: Auf Track 0 zurückfahren + +DoReCalibrate: + IFD LIGHTSHOW + move.w #$0f0,color(a5) ; grün + ENDC + clr.w du_TrackSize(a3) ; Track ist ungültig + btst.b #CIAB_DSKTRACK0,a_pra(a4) ; Track 0 ? + beq.s .ReCalFin ; ja ---> + bset.b #CIAB_DSKDIREC,b_prb(a4) ; Nach Aussen + bclr.b #CIAB_DSKSTEP,b_prb(a4) ; Steppen + bsr ShortDelay + bset.b #CIAB_DSKSTEP,b_prb(a4) + bra ShortDelay ; ---> + +.ReCalFin: clr.w du_CurrentTrack(a3) ; Hier sind wir jetzt + move.b #DS_STEP,du_Status(a3) ; Und wieder steppen + rts + +*************************************************************************** + + *** Kommando DS_STEP: Ziel-Track ansteuern + +DoStep: + IFD LIGHTSHOW + move.w #$ff0,color(a5) ; gelb + ENDC + move.w du_DestTrack(a3),d1 ; Destination Track + cmpi.w #80,d1 ; == Root-Track ? + bne.s 1$ ; nein ---> + addq.w #2,du_DestTrack(a3) ; sonst überhüpfen + bra.s DoStep ; und nochmal das ganze +1$: + move.w du_CurrentTrack(a3),d0 ; Hier sind wir + ;; cmp.w d1,d0 ; Sind wir schon richtig ? + ;; bne.s 2$ ; nein ---> + ;; tst.w du_TrackSize(a3) ; Spur schon gelesen ? + ;; beq.s 2$ ; nein ---> + ;; move.b #DS_WAITDMA,du_Status(a3) ; Sonst sofort Statuswechsel + ;; move.w #INTF_SETCLR|INTF_DSKBLK,intreq(a5) ; Interrupt auslösen + ;; bra.s 99$ ; ---> + ;; 2$: + lsr.w #1,d0 ; Nur Cylindernr interessiert + lsr.w #1,d1 ; Nur Cylindernr interessiert + cmp.w d1,d0 + beq.s .TrackFound + blt.s .StepIn + +.StepOut: subq.w #2,du_CurrentTrack(a3) + btst.b #CIAB_DSKTRACK0,a_pra(a4) ; Track 0 ? + beq.s 99$ ; ja ---> fertig + bset.b #CIAB_DSKDIREC,b_prb(a4) + bra.s .Step + +.StepIn: addq.w #2,du_CurrentTrack(a3) + bclr.b #CIAB_DSKDIREC,b_prb(a4) + ;; bra.s .Step + +.Step: clr.w du_TrackSize(a3) ; Track ist nicht gelesen + bclr.b #CIAB_DSKSTEP,b_prb(a4) + bsr ShortDelay + bset.b #CIAB_DSKSTEP,b_prb(a4) + bsr ShortDelay + bra.s 99$ ; ---> fertig + +.TrackFound: move.w du_DestTrack(a3),d0 ; Wir sind am Ziel + move.w d0,du_CurrentTrack(a3) + btst #0,d0 ; Seite ermitteln + bne.s 3$ + bset.b #CIAB_DSKSIDE,b_prb(a4) ; Seite 0 + bra.s 4$ +3$: bclr.b #CIAB_DSKSIDE,b_prb(a4) ; Seite 1 +4$: move.b #DS_SETTLE,du_Status(a3) +99$: + rts + +*************************************************************************** + + *** Kommando DS_SETTLE: DMA für nächste Spur starten + +DoSettle: + IFD LIGHTSHOW + move.w #$00f,color(a5) ; blau + ENDC + movea.l du_MFMBuffer(a3),a0 ; A0: The Buffer + clr.l (a0) ; Falls gar nix gelesen wird + move.w du_Sync(a3),dsksync(a5) ; SYNC-Wort + move.w #$0c00,d0 + move.w #INTF_DSKBLK,intreq(a5) ; DSKBLK-Intreq löschen + move.w d0,adkcon(a5) ; Precomp 0 + lea dsklen-14(a5),a1 + tst.b du_Status(a3) ; Schreiben ? + bpl.s 1$ ; Noe ---> + + add.w #$9100-$0c00,d0 ; $9100 (MFMPRECOMP|FAST) + lea -GAPBYTES(a0),a0 ; Gap-Bytes auch schreiben + move.w #(WRITEBYTES+GAPBYTES/2)|$C000,d1 ; Words to write + move.b #DS_WAITDMA|DSF_WRITING,du_Status(a3) ; Statusübergang + + ;; btst.b #CIAB_DSKPROT,a_pra(a4) ; Disk schreibgeschützt ? + ;; bne.s 2$ ; nein ---> + ;; moveq #ER_WRITEPROT,d0 + ;; bra.s + + bra.s 2$ +1$: + add.w #$9500-$0c00,d0 ; $9500 (MFMPRECOMP|WORDSYNC|FAST) + move.w #READBYTES|$8000,d1 ; Words to read + move.b #DS_WAITDMA,du_Status(a3) ; Statusübergang +2$: + move.l a0,dskpt(a5) ; Lese- bzw. Schreib-Adresse + move.w d0,adkcon(a5) + bsr ShortDelay ; Das brauchts glaub + move.w d1,dsklen(a5) ; Anzahl Words zu lesen/schreiben + move.w d1,14(a1) ; =DskLen, DMA starten + + move.w #DMATIME,du_TimeOutCntr(a3) ; Lesezeit setzen + +99$: rts + +*************************************************************************** + + *** Kommando DS_WAITDMA: Warten bis Disk-DMA fertig, dann processing + +DoWaitDMA: + IFD LIGHTSHOW + move.w #$f0f,color(a5) ; pink + ENDC + BTSTW INTB_DSKBLK,intreqr(a5) ; Spur fertig gelesen? + bne.s .ProcTrack ; ja ---> + cmpi.w #DMATIME-READYTIME,du_TimeOutCntr(a3) + bgt.s 0$ ; Noch kein Ready-TimeOut ---> + IFD DEBUG + moveq #DERR_DRIVENOTREADY,d0 + ENDC + btst.b #CIAB_DSKRDY,a_pra(a4) ; Drive ready ? + bne.s 1$ ; nein ---> Error +0$: + IFD DEBUG + moveq #DERR_DMATIMEOUT,d0 + ENDC + subq.w #1,du_TimeOutCntr(a3) ; Schon TimeOut ? + bpl .DoWaitDMAEnd ; Noch nicht ---> fertig +1$: + move.w #0,dsklen(a5) ; DMA OFF (NICHT clr!) + bra .ReadRetry ; Retry oder Error + + *** Gelesene Spur verarbeiten: Test ob 1. Sync OK + +.ProcTrack: move.w #INTF_DSKBLK,intreq(a5) ; DSKBLK-Intreq löschen + move.w #0,dsklen(a5) ; DMA OFF (NICHT clr!) + + movea.l du_MFMBuffer(a3),a2 ; A2 : MFM-Buffer + IFD DEBUG + moveq #DERR_NOSYNC,d0 + ENDC + move.w du_Sync(a3),d1 + cmp.w (a2),d1 ; 2. Sync-Wort OK ? + bne .ReadRetry ; Retry oder Error + + *** Anzahl codierte LONGS des Tracks berechnen und eintragen & D2 + +.GetSize: lea 2(a2),a0 ; Start der Daten nach Sync + movem.l (a0),d1/d2 ; 1. Headerlangwort + and.l d7,d1 + and.l d7,d2 + add.l d2,d2 + or.l d1,d2 ; D2: Anzahl Datenbytes + move.w d2,du_TrackSize(a3) ; in Unit-Struktur eintragen + + *** Checksumme des Tracks errechnen & prüfen + + bsr CalcCheckSum ; D0:=Checksumme, A0 := Adr + move.l d0,d1 ; D1: Ist-Checksumme + + movem.l (a0),d0/d2 ; Soll-Checksumme + and.l d7,d0 + and.l d7,d2 + add.l d2,d2 + or.l d0,d2 ; D2: Soll-Checksumme + + IFD DEBUG + moveq #DERR_BADCHECKSUM,d0 + ENDC + cmp.l d2,d1 ; Checksumme richtig ? + bne .ReadRetry ; nein ---> Retry oder Error +2$: + *** Testen ob es der richtige Track ist + +.CheckTrackNo: movem.l 2+8(a2),d1/d2 ; 2. Headerlangwort + and.l d7,d1 + and.l d7,d2 + add.l d2,d2 + or.l d2,d1 ; D1 : 2. HeaderLong + + IFD DEBUG + moveq #DERR_BADTRACK,d0 + ENDC + cmp.b du_CurrentTrack+1(a3),d1 ; Richtige Spur ? + bne .ReCalibrate ; nein ---> + + *** Testen ob's die richtige Disknummer ist + + lsr.w #8,d1 + move.w du_DiskNumber(a3),d0 + beq .ReadFinished ; Bei GetHeader(): fertig! + cmp.b d0,d1 ; Richtige Disk ? + beq.s 3$ ; ja ---> + IFD DEBUG + moveq #DERR_WRONGDISK,d0 + ENDC + move.w d1,du_DiskNumber(a3) ; Neue Disknummer eintragen + bra .ReadError ; ---> Request zurückpushen +3$: + swap d1 ; DiskKey + move.w meb_ProductCode(a6),d0 + beq.s 4$ ; Product-Egal-Magic + cmp.w d0,d1 ; richtige Disk ? + beq.s 4$ ; ja ---> + clr.w du_DiskNumber(a3) + IFD DEBUG + moveq #DERR_WRONGPRODUCT,d0 + ENDC + bra .ReadError ; ---> Request zurückpushen +4$: + *** Testen ob's die 1. Spur des Files ist, ggf. File-Länge nach D5 + + tst.l du_FileSize(a3) ; Länge schon eingetragen ? + bne.s .ProcDataTrack ; ja ---> + + move.w du_FileName+2(a3),d2 ; File-Byte-Offset + add.w d2,d2 ; D2 : MFM-Offset + movem.l 2+16(a2,d2.w),d0/d5 ; kodierte File-Länge + and.l d7,d0 ; MFM-decodieren + and.l d7,d5 + add.l d5,d5 + or.l d0,d5 ; D5 : Länge des Files + + *** Testen ob File gecruncht ist, ggf. Flag setzen und rumwursteln + + movea.l du_ActPacket(a3),a0 ; A0 : Packet + IFD CRUNCH + bclr.l #31,d5 ; File gecruncht ? + beq.s 41$ ; nein ---> + bset.b #DPB_CRUNCHED,dp_Flags(a0) ; Crunch-Flag setzen + + movem.l 2+16+8(a2,d2.w),d0/d6 ; 1. Langwort im File + and.l d7,d0 ; MFM-decodieren + and.l d7,d6 + add.l d6,d6 + or.l d0,d6 ; D6 : Ungecrunchte Länge + moveq.l #PP_SAVEMARGIN,d0 ; Für auf-sich-selber-decrunchen + add.l d0,d6 ; Alloc-Länge += Sicherheitsbereich + bra.s 42$ +41$: move.l d5,d6 ; Nicht gecruncht +42$: + ELSEIF + move.l d5,d6 ; D6 : Amount für AllocMem() + ENDC + move.l d5,du_FileSize(a3) ; Lade-Länge eintragen + move.l d5,dp_FileSize(a0) ; Lade-Länge für Decruncher + + *** Testen ob Speicher reserviert werden muss, ggf. reservieren + + bclr.b #DPB_ALLOCMEM,dp_Flags(a0) ; CHIP-Alloc gewünscht ? + beq.s 5$ ; nein ---> + move.l d6,d0 ; Amount + jsr meb_AllocMem(a6) + bra.s 6$ ; ---> +5$: + bclr.b #DPB_ALLOCFASTMEM,dp_Flags(a0) ; FAST-Alloc gewünscht? + beq.s 61$ ; nein ---> + move.l d6,d0 ; Amount + jsr meb_AllocFastMem(a6) +6$: move.l d0,dp_Address(a0) ; Adresse ins Packet + move.l d0,du_DestAddr(a3) ; Adresse in DiskUnit +61$: + *** 1. Spur (ab File-Start+4) kodieren / dekodieren + + lea 18+8(a2,d2.w),a0 ; File-Data-Start im Puffer + moveq.l #0,d0 + move.w du_TrackSize(a3),d0 ; Länge dieses Tracks + sub.w du_FileName+2(a3),d0 ; minus Start-Offset + subq.l #4,d0 ; minus Längen-Langwort + bra.s 7$ ; ---> + + *** Daten-Spur ab Track-Start kodieren / dekodieren + +.ProcDataTrack: + lea 18(a2),a0 ; Track-Data-Start im Puffer + moveq.l #0,d0 + move.w du_TrackSize(a3),d0 ; Länge dieses Tracks +7$: cmp.l du_FileSize(a3),d0 ; weniger als 1 Track ? + blt.s 8$ ; nein ---> + move.l du_FileSize(a3),d0 ; Sonst begrenzen +8$: + tst.b du_Status(a3) ; Haben wir soeben geschrieben ? + bmi.s 10$ ; ja ---> + + movea.l du_ActPacket(a3),a1 + tst.b dp_Flags(a1) ; Kodieren oder dekodieren? + movea.l du_DestAddr(a3),a1 ; Destination (doesn't change ccr) + bpl.s 9$ + bsr MFMEncode ; D0 Bytes A1 nach A0 kodieren + move.b #DS_SETTLE|DSF_WRITING,du_Status(a3) ; Schreiben!! + bra .DoWaitDMAEnd ; ---> + +9$: bsr MFMDecode ; D0 Bytes A0 nach A1 dekodieren + + *** Nächsten Track zum Lesen vorbereiten + +10$: add.l d0,du_DestAddr(a3) ; INC address + sub.l d0,du_FileSize(a3) ; DEC verbleibende Länge + ble .ReadFinished ; Fertig ---> (Tada!) + addq.w #1,du_DestTrack(a3) ; Nächste Spur + move.b #DS_STEP,du_Status(a3) ; Schreiten + bra .DoWaitDMAEnd ; ---> + + *** ReadError: RetryCounter runterzählen und ggf. retry + +.ReadRetry: clr.w du_TrackSize(a3) ; Spur ungültig + move.b #DS_STEP,du_Status(a3) ; Retry without bumping + bra.s 11$ ; ---> + +.ReCalibrate: move.b #DS_RECALIBRATE,du_Status(a3) ; Bump + +11$: subq.b #1,du_RetryCntr(a3) ; Namal probiere ? + bgt .DoWaitDMAEnd ; ja ---> + +.ReadError: + IFD DEBUG + movea.l du_ActPacket(a3),a0 ; Für MSG + MSG <"Read Error D0=Error A0=Packet A2=MFM A3=Unit"> + ELSEIF + move.w #$fff,$dff180 ; Weiss=Failure + ENDC + clr.w du_DiskNumber(a3) ; Ungültige Diskette + lea meb_DiskList(a6),a0 + move.l du_ActPacket(a3),d0 ; Packet ? + beq.s 12$ ; nein ---> + movea.l d0,a1 + jsr meb_AddHead(a6) ; Request nochmals bearbeiten +12$: + *** Lese-Abschluss bei Error/Success, quittieren falls Success + +.ReadFinished: move.b #DS_IDLE,du_Status(a3) ; Nix mehr tun + clr.l ActUnit ; Drive freigeben + st.b b_prb(a4) ; Motor off + bsr ShortDelay + move.b du_OffMask(a3),b_prb(a4); Motor off & Select + bsr ShortDelay + st.b b_prb(a4) ; Drive deselektieren + bsr ShortDelay + + tst.w du_DiskNumber(a3) ; War alles OK ? + beq.s .Kick ; nein ---> + move.l du_ActPacket(a3),d0 + beq.s .Kick ; kein Packet ---> + movea.l d0,a0 + bsr ReplyPacket ; Packet (A0) beantworten + +.Kick: bsr ProcessNextRequest ; Nächsten Request ankicken + +.DoWaitDMAEnd: rts + + + +***************************************************************************** +* Checksumme des Tracks berechnen +* IN: A2=MFM-Buffer-Start (2. SYNC), A3=Unit +* OUT: D0=Checksumme, A0=Adresse der Checksumme im MFM-Buffer + +CalcCheckSum: movem.l d1-d2,-(SP) ; A0 NICHT retten! + lea 2(a2),a0 ; Start der Daten nach Sync + move.w du_TrackSize(a3),d2 ; Tracklänge in Bytes + lsr.w #1,d2 ; /2 gibt # MFM-Longs + addq.w #3,d2 ; 2 Headerlongs - 1 für dbf + moveq #0,d0 ; D0: Checksumme +.SumLoop: move.l (a0)+,d1 + eor.l d1,d0 + dbf d2,.SumLoop + and.l d7,d0 ; Taktbits ausblenden + movem.l (SP)+,d1-d2 + rts + +***************************************************************************** +* MFM-Dekodierung (CDisk-Format) +* D0 = # Bytes, D7=$55555555, A0=Source (MFM), A1=Destination + +MFMDecode: movem.l d0-d5/a0-a1,-(SP) + move.w d0,d5 ; Anzahl Bytes + andi.w #7,d5 ; D5 := Anzahl Rest-Bytes + lsr.w #3,d0 ; D0 := Anzahl LONGS/2 + bra.s 2$ ; für dbf + +1$: movem.l (a0)+,d1/d2/d3/d4 ; 4 MFM-Longs gibt 8 Bytes + and.l d7,d1 + and.l d7,d2 + and.l d7,d3 + and.l d7,d4 + add.l d2,d2 + add.l d4,d4 + or.l d2,d1 + or.l d4,d3 + move.l d1,(a1)+ + move.l d3,(a1)+ +2$: dbf d0,1$ + + bclr #2,d5 ; mehr als 1 LONG noch ? + beq.s 3$ ; nein ---> + movem.l (a0)+,d1/d2 ; 1 Langwort mehr für Rest + and.l d7,d1 + and.l d7,d2 + add.l d2,d2 + or.l d2,d1 + move.l d1,(a1)+ +3$: + movem.l (a0)+,d1/d2 ; 1 Langwort mehr für Rest + and.l d7,d1 + and.l d7,d2 + add.l d2,d2 + or.l d2,d1 + +4$: subq.w #1,d5 + bmi.s 5$ + rol.l #8,d1 ; Nächstes Byte + move.b d1,(a1)+ + bra.s 4$ +5$: + movem.l (SP)+,d0-d5/a0-a1 + rts + +***************************************************************************** +* MFM-Kodierung (CDisk-Format) +* D0 = # Bytes, D7=$55555555, A0=Destination, A1=Source (MFM), A2=MFM-BufferStart + +MFMEncode: movem.l d0-d1/a0-a1,-(SP) + move.l d0,d1 ; Anzahl Bytes + lsr.w #2,d1 ; Anzahl Longs + bra.s 2$ ; für dbf +1$: move.l (a1)+,d0 ; 1 Source-Longwort + bsr.s PutD0 ; codieren und nach (A0)++ +2$: dbf d1,1$ + + bsr CalcCheckSum ; Prüfsumme der Spur berechnen + bsr PutD0 ; und eintragen + moveq #0,d0 ; Abschluß-AAAAAAAA + bsr PutD0 ; eintragen (wozu? hmmmm..) + + movem.l (SP)+,d0-d1/a0-a1 + ;; bra SetClockBits + + *** Im ganzen Track Taktbits setzen/löschen, D7=BitMask + +SetClockBits: movem.l d0-d3/a0,-(SP) + lea 2(a2),a0 ; A0 : MFM-Buffer (OHNE SYNC!!) + move.w #WRITEBYTES/2,d3 ; 1 LONG mehr anpassen +1$: move.l (a0),d0 + and.l d7,d0 ; Alle Taktbits löschen + move.l d0,d2 + eor.l d7,d2 ; Datenbits invertieren + move.l d2,d1 + lsr.l #1,d1 ; D1: invert. Daten nach rechts + bset.l #31,d1 + lsl.l #1,d2 ; D2: invert. Daten nach links + addq.w #1,d2 ; = bset #0,d2 + and.l d2,d1 + or.l d1,d0 ; nur 1 falls zwischen 2 Nullen + btst.b #0,-1(a0) ; Grenztest nach unten + beq.s 2$ + bclr.l #31,d0 +2$: move.l d0,(a0)+ + dbf d3,1$ + movem.l (SP)+,d0-d3/a0 + rts + + *** D0.L MFM codieren und in (A0)++ eintragen + +PutD0: move.l d0,(a0)+ + lsr.l #1,d0 + move.l d0,(a0)+ + rts + +************************************************************************** + + *** Wichtige Register initialisieren + +GetD7A4A5: movem.l InitVals(PC),d7/a4/a5 + rts + +InitVals: dc.l $55555555 ; D7 + dc.l ciabase ; A4 + dc.l custom ; A5 + +************************************************************************** + + *** Kurz verzögern, nach Schreiben in Hardware-Register + +ShortDelay: move.l d0,-(SP) + moveq #2,d0 ; 3 Rasterzeilen + bsr.s WaitLines + move.l (SP)+,d0 + rts + +************************************************************************** + + *** Genau D0.L * 64 Mikrosekunden warten (+- 64 µs) + +WaitLines: movem.l d0/d1,-(SP) +1$: move.b vhposr(a5),d1 +2$: cmp.b vhposr(a5),d1 + beq.s 2$ + dbf d0,1$ + movem.l (SP)+,d0/d1 + rts + + +*************************************************************************** +* D A T E N (auch im CODE-Segment wegen PC-relativ) * +*************************************************************************** + +MFMBuffer: ds.l 1 ; MFM-Buffer + GAPBYTES +UnitTab: ds.l MAXUNITS ; Unit-Zeiger-Array +ActUnit: ds.l 1 ; Zeiger auf aktive Unit +InsertDiskRoutine: ds.l 1 ; User's InsertDisk handler + + + END diff --git a/Documentation/GameExec.doc b/Documentation/GameExec.doc new file mode 100644 index 0000000..e9818bf --- /dev/null +++ b/Documentation/GameExec.doc @@ -0,0 +1,158 @@ +GAME EXEC - The ultimate Amiga operating system for game development +--------- + +Version 4.4, 16-Apr-92 + +© 1987-92 Christian A. Weber, Christian B. Haller, René Straub, Roman Werner + + + + *** Erlaubte Einträge in MyExecBase: + + APTR meb_SuperStackUpper ; SuperStack am Anfang (READ ONLY!) + WORD meb_AttnFlags ; Kopie von ExecBase->AttnFlags + WORD meb_SystemBplcon0 ; Kopie von gfxbase->system_bplcon0 + BYTE meb_VBlankFrequency ; Kopie von ExecBase->VBlankFrequency + BYTE meb_expad2 + + BYTE meb_ActualKey ; RawKeyCode + BYTE meb_ActualQualifiers ; Qualifier-Bits, (BitNr=KeyCode-$60) + BYTE meb_ActualASCIIKey ; ASCII-Code + BYTE meb_CheatFlag ; >0 falls Cheat mode on + + STRUCT meb_BobList,lh_SIZEOF ; für die Bobroutine + APTR meb_TripleScreen ; für die Bobroutine + WORD meb_SignalSet ; für die Bobroutine + + LONG meb_UserData1 ; Frei für den User, am Anfang 0 + LONG meb_UserData2 ; Frei für den User, am Anfang 0 + + STRUCT meb_exreserved,6 ; + pad auf LONG, NICHT benutzen! + + *** Level 3 Interrupt-Vektoren, zum Patchen oder 0 reinschreiben + + UWORD meb_VBLIntPad + UWORD meb_VBLIntJump + APTR meb_VBLIntVector + + UWORD meb_CopperIntPad + UWORD meb_CopperIntJump + APTR meb_CopperIntVector + + *** Cia-Interrupt-Vektoren, zum Patchen oder 0 reinschreiben + + APTR meb_CiaATimerAVector + APTR meb_CiaATimerBVector + APTR meb_CiaAAlarmVector + APTR meb_CiaASerialVector + APTR meb_CiaAFlagVector + + APTR meb_CiaBTimerAVector + APTR meb_CiaBTimerBVector + APTR meb_CiaBAlarmVector + APTR meb_CiaBSerialVector + APTR meb_CiaBFlagVector + + + *** System-Funktionen (use at your own risk!) + + ULONG meb_SecretMagic ; PRIVAT + FUNCTION InitExec ; (ExecEvent) (CRP) + FUNCTION ColdReboot ; () () + FUNCTION InitChipMem ; (Address,Size) (A0/D0) + FUNCTION InitFastMem ; (Address,Size) (A0/D0) + FUNCTION InitDisk ; (Product) (D0) + FUNCTION InitKey ; () () + FUNCTION SetCache ; (NewCacheBits) (D0) + + *** Debug-Funktionen + + FUNCTION Debug ; () () + + *** Speicherverwaltung + + FUNCTION AllocMem ; (Amount) (D0) + FUNCTION AllocClearMem ; (Amount) (D0) + FUNCTION AllocFastMem ; (Amount) (D0) + FUNCTION AllocFastClearMem ;(Amount) (D0) + FUNCTION FreeMem ; (Address) (A1) + FUNCTION AvailMem ; () () + FUNCTION AvailFastMem ; () () + FUNCTION CheckMem ; () () + FUNCTION CopyMem ; (Src,Dest,Len) (A0/A1/D0) + FUNCTION CopyMemQuick ; (Src,Dest,Len) (A0/A1/D0) + FUNCTION ClearMem ; (Address,Len) (A0/D0) + + *** Semaphoren + + FUNCTION Disable ; () () + FUNCTION Enable ; () () + FUNCTION OwnBlitter ; () () + FUNCTION DisownBlitter ; () () + + *** Listenverwaltung + + FUNCTION NewList ; (List) (A0) + FUNCTION Enqueue ; (List,Node) (A0/A1) + FUNCTION Remove ; (Node) (A1) + FUNCTION AddHead ; (List,Node) (A0/A1) + FUNCTION AddTail ; (List,Node) (A0/A1) + FUNCTION RemHead ; (List) (A0) + + *** Tastatur + + FUNCTION GetKey ; () () + FUNCTION WaitKey ; () () + FUNCTION FlushKeyBuf ; () () + FUNCTION SetMap ; (KeyMap oder 0) (A0) + FUNCTION SetResetHandler ; (Handler) (A0) + FUNCTION SetCheatText ; (RawKeyCodes) (A0) + + *** Ausgabe + + FUNCTION RawDoFmt ; (wie normal :-)) (...) + FUNCTION RawPrintf ; (Stack) (...) + FUNCTION PlayCDTrack ; (TrackNumber) (D0) + FUNCTION WaitCDTrack ; (nüt) () + + *** Zufall + + FUNCTION Randomize ; (Value1,Value2) (D0/D1) + FUNCTION Random ; (Limit) (D0) + + *** Disk-Routinen + + FUNCTION SetNoDiskHandler ;(Routine) (A0) + FUNCTION ReadFile ; (Name,Address) (D0/A0) + FUNCTION WriteFile ; (Name,Address) (D0/A0) + FUNCTION LoadFile ; (Name) (D0) + FUNCTION LoadFastFile ; (Name) (D0) + FUNCTION LoadSeg ; (Name) (D0) + FUNCTION UnLoadSeg ; (Segment) (A1) + FUNCTION BufReadFile ; (Name,Address (D0/A0) + FUNCTION BufLoadFile ; (Name) (D0) + FUNCTION DeleteFileNode ; (Name) (D0) + FUNCTION DeleteFileList ; () () + FUNCTION SendPacket ; (Packet) (A0) + + *** Bob-Routinen + + FUNCTION WaitBlit ; (Custom) (A5) + FUNCTION InitDrawBob ; (BitMap) (A0) + FUNCTION AddBob ; (NewBob) (A1) + FUNCTION RemBob ; (Bob) (A0) + FUNCTION RemAllBobs ; () () + FUNCTION RestoreBobList ; (BitMap) (A1) + FUNCTION DrawBobList ; (BitMap) (A1) + FUNCTION RestoreOneBob ; (Bob,BitMap) (A0/A1) + FUNCTION DrawOneBob ; (Bob,BitMap) (A0/A1) + FUNCTION AnimateOneBob ; (Bob) (A0) + FUNCTION MoveOneBob ; (Bob) (A0) + FUNCTION TestPoint ; (X,Y) (D0/D1) + FUNCTION SetMovePrg ; (Bob,MPrg,Speed,Step) (A0/A1/D0/D1) + FUNCTION SetAnimPrg ; (Bob,APrg,Speed) (A0/A1/D0) + FUNCTION SetGlobalClip ; (X,Y) (D0/D1) + FUNCTION HandleCollision ; () () + FUNCTION CollOneBob ; (Bob) (A0) + FUNCTION FlashBob ; (Bob,Time,Color) (A0/D0/D1) + FUNCTION GetBobData ; (Bob) (A0)->A2 diff --git a/Documentation/README b/Documentation/README new file mode 100644 index 0000000..264a52b --- /dev/null +++ b/Documentation/README @@ -0,0 +1,70 @@ +GAME EXEC - The ultimate Amiga operating system for game development +--------- + +Version 4.4, 16-Apr-92 + +© 1987-92 Christian A. Weber, Christian B. Haller, René Straub, Roman Werner + + +Features +-------- + +- Powerful debugging function, such as debug output to serial port or calling + ROMCrack, the ultimate Kickstart-based monitor/disassembler by SCA + +- Memory managment (Allocate, clear, copy Chip + Fast mem) + +- Semaphores (Disable/Enable interrupts, Own/Disown blitter in System mode) + +- Linked List management + +- Keyboard handler including support for custom keymaps + +- Output formatting (printf-style) + +- Optional CDTV functions: play audio tracks + +- Random number generator + +- Powerful interrupt-driven floppy disk routines supporting up to 4 dives + supporting PowerPacker-compressed files and loading in the background + +- BOBOL® the ultimate Bob Animation System: Bob rendering, double/triple + buffering, Animation, collision testing, clipping etc. using a powerful + control languange + + +Versions +-------- + +There are 3 versions of Game Exec: + +- Standard version: Runs completely without Amiga OS + +- System version (SysStart): runs within Amiga OS (used for development) + this version optionally supports the CDTV + +- Ram version (runs without Amiga OS, but uses a FFS ram disk instead of floppy) + + +Modification History +-------------------- + +18-May-89 CHW Recreated this file! +20-Jun-89 CHW Supports 1MB CHIP RAM +29-Jun-89 CHW Auf Genim2 umgeschrieben +22-Aug-89 CHW AddHead() added +27-Aug-89 CHW AddHead() rettet nun die Register (!^%#$@) +13-Sep-89 CHW CopyMem() rettet nun D0 (grmbl!) +06-Nov-89 CHW SetCache() added +27-Nov-89 CHW FastMem support routines added +04-Feb-90 CHW Zero-Handler & other Guru handlers added +11-Feb-90 CHW Supervisor-Stack ist jetzt im FAST-RAM +28-Mar-90 CHW ColdReboot() implementiert, ABORT springt dahin +18-Sep-90 CHW CheckMem() implementiert und so +20-Oct-90 CHW Config-File entfernt, MainPrg muss am Anfang sein +30-Dec-90 CHW Gecrunchte Files werden automatisch entcruncht +06-Jan-91 CHH BufLoadFile testet ob genug RAM vorhanden ist +11-Feb-91 CHH BufReadFile eingebaut +18-Feb-91 CHW Multitasking-fähige Version +06-May-91 CHW Diskroutine kann jetzt schreiben diff --git a/EndLabel.S b/EndLabel.S new file mode 100644 index 0000000..bebbaf8 --- /dev/null +++ b/EndLabel.S @@ -0,0 +1,14 @@ + IDNT EndLabel + + XREF __MyExecBase + XDEF __H2_end,_MyExecBase + + + SECTION data,DATA + +_MyExecBase: dc.l __MyExecBase + dc.b "EXECEND." ; Endmarkierung + + SECTION last,BSS + ds.l 1 ; Sonst exportiert Genam __H2_end nicht ?! +__H2_end: @@ -0,0 +1,816 @@ +************************************************************************** +** ** +** MYEXEC - Verschiedene Routinen die so manches Programm braucht ** +** ** +** by Christian A. Weber, Zurich/Switzwerland ** +** ** +************************************************************************** +** ** +** Modification History ** +** -------------------- ** +** ** +** 18-May-89 CHW Recreated this file! ** +** 20-Jun-89 CHW Supports 1MB CHIP RAM ** +** 29-Jun-89 CHW Auf Genim2 umgeschrieben ** +** 22-Aug-89 CHW AddHead() added ** +** 27-Aug-89 CHW AddHead() rettet nun die Register (!^%#$@) ** +** 13-Sep-89 CHW CopyMem() rettet nun D0 (grmbl!) ** +** 06-Nov-89 CHW SetCache() added ** +** 27-Nov-89 CHW FastMem support routines added ** +** 04-Feb-90 CHW Zero-Handler & other Guru handlers added ** +** 11-Feb-90 CHW Supervisor-Stack ist jetzt im FAST-RAM ** +** 28-Mar-90 CHW ColdReboot() implementiert, ABORT springt dahin ** +** 18-Sep-90 CHW CheckMem() implementiert und so ** +** 20-Oct-90 CHW Config-File entfernt, MainPrg muss am Anfang sein ** +** 30-Dec-90 CHW Gecrunchte Files werden automatisch entcruncht ** +** 06-Jan-91 CHH BufLoadFile testet ob genug RAM vorhanden ist ** +** 11-Feb-91 CHH BufReadFile eingebaut ** +** 18-Feb-91 CHW Multitasking-fähige Version ** +** 06-May-91 CHW Diskroutine kann jetzt schreiben ** +** ** +************************************************************************** + + IDNT Exec + SECTION text,CODE + + INCLUDE "MyExec.i" + INCLUDE "exec/macros.i" + INCLUDE "zeropage.i" + INCLUDE "hardware/custom.i" + INCLUDE "hardware/dmabits.i" + INCLUDE "hardware/intbits.i" + + +STACKSIZE: EQU 5432 ; Grösse des Super-Stacks + +ROMCRACKEXCEPT: EQU $fc2ff4+(2*6) ; ROMCrack Exception-Einspr. +ROMCRACKSPEC: EQU $fc2ff4+(4*6) ; ROMCrack Special-Einsprung + +INITMAGIC: EQU 'INIT' ; steht vor InitExecFunc() +FFSMAGIC: EQU $444f5301 + +FN_MAINPRG: EQU $01030010 ; Disk 1, Track 3, 1. File + +************************************************************************** + + XREF _custom,__H2_end + + XREF InitChipMemFunc,InitFastMemFunc + XREF AllocMemFunc,AllocClearMemFunc + XREF AllocFastMemFunc,AllocFastClearMemFunc + XREF AvailMemFunc,AvailFastMemFunc,CheckMemFunc + XREF FreeMemFunc,ClearMemFunc,CopyMemQuickFunc,CopyMemFunc + XREF InitKeyFunc,GetKeyFunc,WaitKeyFunc,FlushKeyBufFunc + XREF SetMapFunc,SetResetHandlerFunc,SetCheatTextFunc + XREF RawDoFmtFunc,_RawPrintfFunc + XREF RandomizeFunc,RandomFunc + + XREF InitDiskFunc,SetNoDiskHandlerFunc,ReadFileFunc + XREF WriteFileFunc,LoadFileFunc,LoadFastFileFunc + XREF LoadSegFunc,UnLoadSegFunc,SendPacketFunc + XREF InitRAMLib,BufReadFileFunc,BufLoadFileFunc + XREF DeleteFileNodeFunc,DeleteFileListFunc + + XREF WaitBlit,InitDrawBob,AddBob,RemBob,RemAllBobs + XREF RestoreBobList,DrawBobList + XREF RestoreOneBob,DrawOneBob + XREF AnimateOneBob,MoveOneBob,TestPoint + XREF SetMovePrg,SetAnimPrg,SetGlobalClip + XREF HandleCollision,CollOneBob,FlashBob,GetBobData + IFD SYSTEM + XREF ExitKeyFunc + XREF InitCDFunc,ExitCDFunc,PlayCDTrackFunc,WaitCDTrackFunc + ENDC + + XDEF __MyExecBase,_InitExec,_idstring + + XDEF InitExecFunc,ColdRebootFunc,SetCacheFunc,DebugFunc + XDEF NewListFunc,EnqueueFunc,RemoveFunc + XDEF AddHeadFunc,AddTailFunc,RemHeadFunc + XDEF DisableFunc,EnableFunc + +************************************************************************** + + *** Die Zero-Page mit den vielen Vektoren + +__MyExecBase: +Null: DC.L 0 ; $00 := 0 für Sprites usw. + BRA.W JumpZero ; $04 Falls jemand nach 0 springt ... + DC.L Guru2Handler ; $08 + DC.L Guru3Handler ; $0C + DC.L Guru4Handler ; $10 + DC.L Guru5Handler ; $14 + DC.L Guru6Handler ; $18 + DC.L Guru7Handler ; $1C + DC.L Guru8Handler ; $20 + DC.L Guru9Handler ; $24 + DC.L GuruAHandler ; $28 + DC.L GuruBHandler ; $2C + DC.L GuruCHandler ; $30 + DC.L GuruDHandler ; $34 + DC.L GuruEHandler ; $38 + DC.L GuruFHandler ; $3C + DCB.L 9,0 ; $40-$60 ; Reserved exceptions + DC.L DebugFunc ; $64 ; Interrupt Level 1 + DC.L CiaAServer ; $68 ; Interrupt Level 2 + DC.L VBLServer ; $6C ; Interrupt Level 3 + DC.L DebugFunc ; $70 ; Interrupt Level 4 + DC.L DebugFunc ; $74 ; Interrupt Level 5 + DC.L CiaBServer ; $78 ; Interrupt Level 6 + DC.L ColdRebootFunc ; $7C ; Interrupt Level 7 + DCB.L 16,0 ; $80-$BC ; Trap-Vectors 0-15 + DC.B "CHW!" ; $C0 ; Kennung für Booter! + DCB.L 15,0 ; $C4-$FC ; Reserviert + + *** Tada! Die ExecBase-Struktur + + DC.L 0 ; Nicht debuggen! + DC.L 'ICH!' ; ROMCrackMagic für Mem + DC.L $1d0000 ; ROMCrackBSS + DC.L $1e0000 ; ROMCrackChipMem + DC.L ROMCrackText ; ROMCrack's Debug-Text + + *** Private Einträge + + DCB.B mh_SIZEOF,0 ; MemoryRegionHeader + DCB.B mh_SIZEOF,0 ; FastMemoryRegionHeader + DC.L 0 ; RAMDiskBase + DC.L 0 ; RAMDiskSize + DC.L FN_MAINPRG ; MainPrgName + DC.L $affebad,356789 ; LastRnd1,LastRnd2 + DCB.B lh_SIZEOF,0 ; DiskList + DCB.B lh_SIZEOF,0 ; FileList (für RAMLib) + DC.W 0 ; Product-Code + DC.B -1 ; IDNestCnt + DC.B 0 ; ExecFlags + + *** Erlaubte Einträge + + DC.L 0 ; SuperStackUpper + DC.W 0 ; AttnFlags + DC.W 0 ; SystemBplcon0 + DC.B 0 ; VBlankFrequency + DC.B 0 ; expad2 + + DC.B 0 ; ActualKey + DC.B 0 ; ActualQualifiers + DC.B 0 ; ActualASCIIKey + DC.B 0 ; CheatFlag + + DCB.B lh_SIZEOF,0 ; BobList + DC.L 0 ; TripleScreen: Zeiger auf 3. BitMap + DC.W 0 ; SignalSet (für Bobroutine) + + DC.L 0 ; UserData1 + DC.L 0 ; UserData2 + + DCB.B 6,0 ; exreserved, pad auf LONG + + DC.W 0 ; LONG-Align + DC.W $4EF9 ; VBL-Jmp + DC.L 0 ; VBL-Vektor + + DC.W 0 ; LONG-Align + DC.W $4EF9 ; Copper-Jmp + DC.L 0 ; Copper-Vektor + + DCB.L 2*5,0 ; Cia-Interruptvektoren + + DC.L INITMAGIC ; Steht vor InitExecFunc() +_InitExec: + BRA.W InitExecFunc ; MUSS 1. Funktion sein: FinalBooter.S + BRA.W ColdRebootFunc ; MUSS 2. Funktion sein: FinalBooter.S + BRA.W InitChipMemFunc + BRA.W InitFastMemFunc + BRA.W InitDiskFunc + BRA.W InitKeyFunc + BRA.W SetCacheFunc + + BRA.W DebugFunc + + BRA.W AllocMemFunc + BRA.W AllocClearMemFunc + BRA.W AllocFastMemFunc + BRA.W AllocFastClearMemFunc + BRA.W FreeMemFunc + BRA.W AvailMemFunc + BRA.W AvailFastMemFunc + BRA.W CheckMemFunc + BRA.W CopyMemFunc + BRA.W CopyMemQuickFunc + BRA.W ClearMemFunc + + BRA.W DisableFunc + BRA.W EnableFunc + BRA.W OwnBlitterFunc + BRA.W DisownBlitterFunc + + BRA.W NewListFunc + BRA.W EnqueueFunc + BRA.W RemoveFunc + BRA.W AddHeadFunc + BRA.W AddTailFunc + BRA.W RemHeadFunc + + BRA.W GetKeyFunc + BRA.W WaitKeyFunc + BRA.W FlushKeyBufFunc + BRA.W SetMapFunc + BRA.W SetResetHandlerFunc + BRA.W SetCheatTextFunc + + BRA.W RawDoFmtFunc + BRA.W _RawPrintfFunc + BRA.W PlayCDTrackFunc + BRA.W WaitCDTrackFunc + + BRA.W RandomizeFunc + BRA.W RandomFunc + + BRA.W SetNoDiskHandlerFunc + BRA.W ReadFileFunc + BRA.W WriteFileFunc + BRA.W LoadFileFunc + BRA.W LoadFastFileFunc + BRA.W LoadSegFunc + BRA.W UnLoadSegFunc + BRA.W BufReadFileFunc + BRA.W BufLoadFileFunc + BRA.W DeleteFileNodeFunc + BRA.W DeleteFileListFunc + BRA.W SendPacketFunc + + BRA.W WaitBlit + BRA.W InitDrawBob + BRA.W AddBob + BRA.W RemBob + BRA.W RemAllBobs + BRA.W RestoreBobList + BRA.W DrawBobList + BRA.W RestoreOneBob + BRA.W DrawOneBob + BRA.W AnimateOneBob + BRA.W MoveOneBob + BRA.W TestPoint + BRA.W SetMovePrg + BRA.W SetAnimPrg + BRA.W SetGlobalClip + BRA.W HandleCollision + BRA.W CollOneBob + BRA.W FlashBob + BRA.W GetBobData + + + IFNE (*-Null)-__EXECBASESIZE + Fail "ExecBase structure size mismatch!" + ENDC + + + BRA.W UndefdFunc + BRA.W UndefdFunc + BRA.W UndefdFunc + BRA.W UndefdFunc + + + DCB.B 7,0 +VersTag: DC.B 0,"$VER: " + +_idstring: +ROMCrackText: DC.B "GAME EXEC Operating System V4.4 (16-Apr-92)",0 + DC.B "Copyright (c) 1989 - 1992 by Christian A. Weber," + DC.B "Bruggerweg 2, CH-8037 Zuerich, Switzerland.",10,0 + DC.B "All Rights Reserved.",10,0 + DC.B "Greetings to Chris Haller, René Straub, Roman Werner",10,0 + DCB.B 27,0 + +ExceptText: DC.B "Exception " +exno: DC.B "xx",0 + +JumpZeroText: DC.B "Caught jump to 0",0 +UndefdText: DC.B "Undef'd routine",0 + EVEN + + +************************************************************************** +** E X E C - I N I T I A L I S I E R U N G +************************************************************************** + + *** SYSTEM: + *** D0=AttnFlags, D1=SystemBplcon0, D2=VBlankFrequency, + *** D3=Product Code, A0=CHIPRAM-Base, A1=CHIPRAM-Ende, + *** A2=FASTRAM-Base, A3=FASTRAM-Ende D4=MainPrg-Name + + *** SONST: + *** D0=AttnFlags, D1=SystemBplcon0, D2=VBlankFrequency, + *** D3=Product Code, A0=RAMDiskBase, A1=RAMDiskSize, + *** A2=FASTRAM-Base, A3=FASTRAM-Ende A7=CHIPRAM-Ende-8 + +InitExecFunc: + IFND SYSTEM + move #$2700,sr + ENDC + lea _custom,a5 + lea __MyExecBase(PC),a6 + + *** System-Status initialisieren (NUR 1x , NICHT BEI RESTART!) + + tst.b meb_VBlankFrequency(a6) ; ExecBase schon installiert? + bne.s .NotFirst ; ja ---> + + move.w d0,meb_AttnFlags(a6) + move.w d1,meb_SystemBplcon0(a6) + move.b d2,meb_VBlankFrequency(a6) + move.w d3,meb_ProductCode(a6) + IFND DISKVERSION + move.l d4,meb_MainPrgName(a6) + ENDC + + IFD SYSTEM + move.l (SP)+,ColdRebootJmp+2 ; Return-Adresse + move.l a0,meb_ChipMRHeader+mh_Lower(a6) + move.l a1,meb_ChipMRHeader+mh_Upper(a6) + ELSEIF + move.l a0,meb_RAMDiskBase(a6) ; Muss 0 sein falls kein RAM! + move.l a1,meb_RAMDiskSize(a6) ; Muss 0 sein falls kein RAM! + + move.l #__H2_end,d0 ; Ende von Exec's BSS + addq.l #7,d0 + andi.b #$f8,d0 ; Modulo-8 aufrunden + move.l d0,meb_ChipMRHeader+mh_Lower(a6) + move.l SP,meb_ChipMRHeader+mh_Upper(a6) + ENDC + move.l a2,meb_FastMRHeader+mh_Lower(a6) + move.l a3,meb_FastMRHeader+mh_Upper(a6) + + *** StackPointer initialisieren (ins FAST-RAM falls vorhanden) + + lea meb_FastMRHeader+mh_Upper(a6),a0 + tst.l (a0) + bne.s 1$ ; FAST-RAM vorhanden ---> + lea meb_ChipMRHeader+mh_Upper(a6),a0 +1$: + move.l (a0),d0 ; Alte Obergrenze + move.l d0,meb_SuperStackUpper(a6) ; nach StackPointer + sub.l #STACKSIZE,d0 ; Stack-Grösse wegzählen + move.l d0,(a0) ; Neue Obergrenze setzen + + *** VBL und Copper-Interrupt-Server installieren falls SYSTEM + + IFD SYSTEM + move.l a6,-(SP) + movea.l 4,a6 + + moveq #INTB_VERTB,d0 + lea MyVertInt(PC),a1 + JSRLIB AddIntServer + + moveq #INTB_COPER,d0 + lea MyCopInt(PC),a1 + JSRLIB AddIntServer + + movea.l (SP)+,a6 + + bsr InitCDFunc + ENDC + +.NotFirst: + + *** Speicherverwaltung initialisieren + + movea.l meb_SuperStackUpper(a6),SP ; StackPointer holen + + movea.l meb_ChipMRHeader+mh_Lower(a6),a0 + move.l meb_ChipMRHeader+mh_Upper(a6),d0 + sub.l a0,d0 ; D0 := Länge + jsr meb_ClearMem(a6) ; ** DEBUG ** Cracker-Schutz: Speicher mit Muster füllen + jsr meb_InitChipMem(a6) + + movea.l meb_FastMRHeader+mh_Lower(a6),a0 + move.l meb_FastMRHeader+mh_Upper(a6),d0 + sub.l a0,d0 ; D0 := Länge + beq.s 2$ ; Kein FAST-RAM ---> + jsr meb_ClearMem(a6) ; ** DEBUG ** Cracker-Schutz: Speicher mit Muster füllen + jsr meb_InitFastMem(a6) +2$: + *** Jenes Zeugs initialisieren + + IFND SYSTEM + move.w #$7fff,intena(a5) ; Alle Interrupts off + move.w #$7fff,intreq(a5) ; Interrupt-Requests löschen + move #$2000,sr ; Interrupt Level 0 + move.w #INTF_SETCLR|INTF_INTEN|INTF_VERTB|INTF_COPER,intena(a5) + move.w #$7fff,dmacon(a5) ; Alle DMAs off + move.w #DMAF_SETCLR|DMAF_MASTER,dmacon(a5) + ENDC + jsr meb_InitKey(a6) ; Tastatur on + jsr meb_InitDisk(a6) ; Diskroutine on + bsr InitRAMLib ; RAMLib initialisieren + + *** 1. File einladen & starten + + move.l meb_MainPrgName(a6),d0 ; 1. Modul + jsr meb_LoadSeg(a6) ; meinprg laden + movea.l d0,a0 ; Muss A0 sein, User weiss es! + jmp (a0) ; A6 muss MyExecBase sein! + +************************************************************************** + + *** System resetten (wir sind im Supervisor) + +ColdRebootFunc: + IFD SYSTEM + bsr ExitCDFunc + bsr ExitKeyFunc + + move.l a6,-(SP) + movea.l 4,a6 + + moveq #INTB_VERTB,d0 + lea MyVertInt(PC),a1 + JSRLIB RemIntServer + + moveq #INTB_COPER,d0 + lea MyCopInt(PC),a1 + JSRLIB RemIntServer + + movea.l (SP)+,a6 + +ColdRebootJmp: jmp (1$).L ; Zum Patchen +1$: + ENDC + + IFD DISKVERSION + btst #AFB_68020,meb_AttnFlags+1(a6) ; MMU ? + beq.s 2$ ; nein ---> + clr.l -(SP) ; Code für MMU off + move.l SP,a0 + dc.w $f010,$4000 ; pmove (a0),tc +2$: nop + nop + lea 2,a0 + RESET + jmp (a0) + ENDC + + IFD RAMVERSION + jmp $1FFFFA ; ABORT + ENDC + + +************************************************************************** +* Level 3 Interrupt Server + + IFD SYSTEM + +VBLServer: EQU 0 + +MyVertInt: dc.l 0,0 + dc.b 0,60 + dc.l _idstring + dc.l __MyExecBase + dc.l 1$ + + * D1/A0-A1/A5-A6 = Scratch + +1$: lea _custom,a5 + movea.l a1,a6 ; _MyExecBase + tst.l meb_VBLIntVector(a6) + beq.s 2$ + jsr meb_VBLIntJump(a6) +2$: movea.l a5,a0 ; Custom für Gfx-IntServer + moveq.l #0,d0 ; Set Z bit + rts + +MyCopInt: dc.l 0,0 + dc.b 0,60 + dc.l _idstring + dc.l __MyExecBase + dc.l 1$ + +1$: lea _custom,a5 + movea.l a1,a6 ; _MyExecBase + tst.l meb_CopperIntVector(a6) + beq.s 2$ + jsr meb_CopperIntJump(a6) +2$: moveq.l #0,d0 ; Set Z bit + rts + + ELSEIF + +VBLServer: movem.l a5/a6,-(SP) + lea _custom,a5 ; User weiss das! + lea __MyExecBase(PC),a6 ; User weiss das! + btst.b #INTB_VERTB,intreqr+1(a5) + beq.s 2$ + tst.l meb_VBLIntVector(a6) + beq.s 1$ + jsr meb_VBLIntJump(a6) +1$: move.w #INTF_VERTB,intreq(a5) +2$: + btst.b #INTB_COPER,intreqr+1(a5) + beq.s 4$ + tst.l meb_CopperIntVector(a6) + beq.s 3$ + jsr meb_CopperIntJump(a6) +3$: move.w #INTF_COPER,intreq(a5) +4$: + movem.l (SP)+,a5/a6 + rte + ENDC + +************************************************************************** +* CIA Interrupt Server + + IFD SYSTEM + +CiaAServer: EQU 0 +CiaBServer: EQU 0 + + ELSEIF + +CiaAServer: movem.l d0/d2/a0/a2/a5/a6,-(SP) ; ACHTUNG: unten gleich! + lea _custom,a5 ; User weiss das! + lea __MyExecBase(PC),a6 ; User weiss das! + move.w #$0008,intreq(a5) ; Interruptrequest löschen + move.b $bfed01,d2 ; ICAA ICR auslesen + lea meb_CiaATimerAVector(a6),a2 ; Vektor-Basis + bra.s CiaCommon + +CiaBServer: movem.l d0/d2/a0/a2/a5/a6,-(SP) ; ACHTUNG: oben gleich! + lea _custom,a5 ; User weiss das! + lea __MyExecBase(PC),a6 ; User weiss das! + move.w #$2000,intreq(a5) ; Interruptrequest löschen + move.b $bfdd00,d2 ; ICAB ICR auslesen + lea meb_CiaBTimerAVector(a6),a2 ; Vektor-Basis + ;; bra.s CiaCommon + +CiaCommon: lsr.b #1,d2 ; Timer A Interrupt ? + bcc.s 1$ ; Nein ---> + move.l (a2),d0 ; Vektor gültig ? + beq.s 1$ ; nein ---> + movea.l d0,a0 + jsr (a0) +1$: + lsr.b #1,d2 ; Timer B Interrupt ? + bcc.s 2$ ; Nein ---> + move.l 4(a2),d0 ; Vektor gültig ? + beq.s 2$ ; nein ---> + movea.l d0,a0 + jsr (a0) +2$: + lsr.b #1,d2 ; Alarm Interrupt ? + bcc.s 3$ ; Nein ---> + move.l 8(a2),d0 ; Vektor gültig ? + beq.s 3$ ; nein ---> + movea.l d0,a0 + jsr (a0) +3$: + lsr.b #1,d2 ; Serial Interrupt ? + bcc.s 4$ ; Nein ---> + move.l 12(a2),d0 ; Vektor gültig ? + beq.s 4$ ; nein ---> + movea.l d0,a0 + jsr (a0) +4$: + lsr.b #1,d2 ; Flag Interrupt ? + bcc.s 5$ ; Nein ---> + move.l 16(a2),d0 ; Vektor gültig ? + beq.s 5$ ; nein ---> + movea.l d0,a0 + jsr (a0) +5$: + movem.l (SP)+,d0/d2/a0/a2/a5/a6 + rte + + ENDC + +************************************************************************** +** E X C E P T I O N - H A N D L E R +************************************************************************** + + *** Die Einsprünge von den ZeroPage-Vektoren: + +GuruHandler: bsr.s CalcGuru +;;Guru1Handler: bsr.s CalcGuru +Guru2Handler: bsr.s CalcGuru +Guru3Handler: bsr.s CalcGuru +Guru4Handler: bsr.s CalcGuru +Guru5Handler: bsr.s CalcGuru +Guru6Handler: bsr.s CalcGuru +Guru7Handler: bsr.s CalcGuru +Guru8Handler: bsr.s CalcGuru +Guru9Handler: bsr.s CalcGuru +GuruAHandler: bsr.s CalcGuru +GuruBHandler: bsr.s CalcGuru +GuruCHandler: bsr.s CalcGuru +GuruDHandler: bsr.s CalcGuru +GuruEHandler: bsr.s CalcGuru +GuruFHandler: bsr.s CalcGuru + nop ; Damit letzter Offset != 0 + +CalcGuru: subi.l #GuruHandler,(SP) ; Vektornummer erzeugen + lsr.w 2(SP) + cmpi.w #$4ef9,ROMCRACKSPEC ; Ist's unsere Kickstart? + bne.s 1$ ; Nein ---> + jmp ROMCRACKEXCEPT +1$: move.l #ExceptText,meb_ROMCrackDebugText+__MyExecBase + move.w 2(SP),d0 + lsr.w #4,d0 + add.b #'0',d0 + move.b d0,exno + move.w 2(SP),d0 + and.w #15,d0 + add.b #'0',d0 + move.b d0,exno+1 + bra ColdRebootFunc + + +************************************************************************** +* Handler für JMP 0 + +JumpZero: move.l #JumpZeroText,meb_ROMCrackDebugText+__MyExecBase + bra.s DebugFunc + + *** ROMCrack aufrufen + +UndefdFunc: move.l #UndefdText,$110 + +DebugFunc: cmpi.w #$4ef9,ROMCRACKSPEC ; Ist's unsere Kickstart? + bne.s 1$ ; Nein ---> + jmp ROMCRACKSPEC +1$: bra ColdRebootFunc + + +************************************************************************** +** E X E C - R O U T I N E N +************************************************************************** + +************************************************************************** +* Cache D0 setzen + +SetCacheFunc: + IFD SYSTEM + XREF @SetCACR + bra @SetCACR + ELSEIF + btst.b #AFB_68020,meb_AttnFlags+1(a6) ; Cache vorhanden ? + beq.s 1$ ; nein ---> + dc.w $4E7B,$0002 ; movec d0,cacr +1$: rts + ENDC + +************************************************************************** +* Blitter reservieren + +OwnBlitterFunc: + IFD SYSTEM + XREF _GfxBase + move.l a6,-(SP) + movea.l _GfxBase,a6 + JSRLIB OwnBlitter + JSRLIB WaitBlit + movea.l (SP)+,a6 + ELSEIF +PlayCDTrackFunc: +WaitCDTrackFunc: + ENDC + rts + +************************************************************************** +* Blitter freigeben + +DisownBlitterFunc: + IFD SYSTEM + move.l a6,-(SP) + movea.l _GfxBase,a6 + JSRLIB WaitBlit + JSRLIB DisownBlitter + movea.l (SP)+,a6 + ENDC + rts + +************************************************************************** +* Neue Liste initialisieren, A0: Liste + +NewListFunc: move.l a0,lh_Head(a0) + addq.l #lh_Tail,(a0) ; Head zeigt auf Tail + clr.l lh_Tail(a0) ; Tail ist immer 0 + move.l a0,lh_TailPred(a0) ; TailPred zeigt auf Head + rts + +************************************************************************** +* Node in Liste einfügen (nach Priorität), A0: Liste, A1: Node + +EnqueueFunc: movem.l d0-d1/a0,-(SP) + bsr.s DisableFunc + move.b ln_Pri(a1),d1 + move.l lh_Head(a0),d0 +1$: movea.l d0,a0 + move.l ln_Succ(a0),d0 + beq.s 2$ ; Ende der Liste ---> + cmp.b ln_Pri(a0),d1 ; Priorität kleiner oder gleich ? + ble.s 1$ ; ja ---> weitersuchen +2$: move.l ln_Pred(a0),d0 + move.l a1,ln_Pred(a0) + move.l a0,ln_Succ(a1) + move.l d0,ln_Pred(a1) + movea.l d0,a0 + move.l a1,ln_Succ(a0) + bsr.s EnableFunc + movem.l (SP)+,d0-d1/a0 + rts + +************************************************************************** +* Node aus Liste entfernen, A1: Node + +RemoveFunc: movem.l a0/a1,-(SP) + bsr.s DisableFunc + movea.l ln_Succ(a1),a0 + movea.l ln_Pred(a1),a1 + move.l a0,ln_Succ(a1) + move.l a1,ln_Pred(a0) + bsr.s EnableFunc + movem.l (SP)+,a0/a1 + rts + +************************************************************************** +* Node an den Anfang der Liste anhängen, A0: Liste, A1: Node + +AddHeadFunc: movem.l d0/a0/a1,-(SP) + bsr.s DisableFunc + move.l lh_Head(a0),d0 + move.l a1,lh_Head(a0) + movem.l d0/a0,ln_Succ(a1) + movea.l d0,a0 + move.l a1,ln_Pred(a0) + bsr.s EnableFunc + movem.l (SP)+,d0/a0/a1 + rts + +************************************************************************** +* Interrupts sperren mit IDNestCnt und so + +DisableFunc: + IFD SYSTEM + move.l a6,-(SP) + movea.l 4,a6 + JSRLIB Disable + movea.l (SP)+,a6 + ELSEIF + move.w #$4000,$dff09a ; Master interrupt off + addq.b #1,meb_IDNestCnt(a6) ; INC counter + ENDC + rts + +************************************************************************** +* Interrupts zulassen mit IDNestCnt und so + +EnableFunc: + IFD SYSTEM + move.l a6,-(SP) + movea.l 4,a6 + JSRLIB Enable + movea.l (SP)+,a6 + ELSEIF + subq.b #1,meb_IDNestCnt(a6) + bge.s 1$ + move.w #$c000,$dff09a +1$: + ENDC + rts + +************************************************************************** +* Node ans Ende der Liste anhängen, A0: Liste, A1: Node + +AddTailFunc: movem.l d0/a0/a1,-(SP) + bsr.s DisableFunc + lea lh_Tail(a0),a0 + move.l ln_Pred(a0),d0 + move.l a1,ln_Pred(a0) + move.l a0,ln_Succ(a1) + move.l d0,ln_Pred(a1) + move.l d0,a0 + move.l a1,ln_Succ(a0) + bsr.s EnableFunc + movem.l (SP)+,d0/a0/a1 + rts + +************************************************************************** +* Ersten Node aus Liste entfernen, A0: Liste gibt D0: Node, CCR + +RemHeadFunc: movem.l a0/a1,-(SP) + bsr.s DisableFunc + move.l lh_Head(a0),a1 + move.l ln_Succ(a1),d0 + beq.s 1$ + move.l d0,lh_Head(a0) + exg d0,a1 + move.l a0,ln_Pred(a1) +1$: bsr.s EnableFunc + movem.l (SP)+,a0/a1 + tst.l d0 + rts + +************************************************************************** + + END @@ -0,0 +1,254 @@ +*************************************************************************** +** ** +** FFS.S - FastFileSystem-Laderoutine (2. Generation) ** +** ** +*************************************************************************** +** ** +** Modification History ** +** -------------------- ** +** ** +** Steinzeit RS Created this file! ** +** 01-Sep-89 CHW Adaptiert für Exec (Packet-Interface) ** +** ??-Nov-89 CHW File-Size/512-Bytes-Guru-Bug fixed (GRRRR!) ** +** 18-Sep-90 CHW 74-Block-Bug gefunden, (2 Tage futsch! #@$*&!) ** +** ** +** 19-Sep-90 CHW Neu programmiert, ist 200 Bytes kürzer worden :-) ** +** 29-Dec-90 CHW Pure-Flag bedeutet File ist gecruncht ** +** ** +*************************************************************************** + + OPT OW6+ + + IDNT FastFileSystem + SECTION text,CODE + + INCLUDE "MyExec.i" + +CRUNCH + IFD RAMVERSION + + + XDEF ProcessFFSPacket + +*************************************************************************** + +BLOCKSIZE: EQU 512 ; Grösse eines Disk-Blocks in Bytes +ST.FILE: EQU -3 ; SubTyp eines Files + + STRUCTURE FileHeaderBlock,0 + + ULONG fh_Type ; 0 T.SHORT + ULONG fh_OwnKey ; 1 Zeiger auf sich selbst + ULONG fh_HighSeq ; 2 Anzahl hier vermerkter Datenblöcke + ULONG fh_DataSize ; 3 Anzahl der benutzten Datenblöcke + ULONG fh_FirstData ; 4 Erster Datenblock + ULONG fh_CheckSum ; 5 Checksumme + STRUCT fh_BlockPtrs,4*72 ; 6 Zeiger auf Datenblöcke (rückwärts!) + LABEL fh_BlockPtrEnd ; 78 + ULONG fh_unused78 ; 78 + ULONG fh_unused79 ; 79 + ULONG fh_Protect ; 80 Protection-Bits + ULONG fh_FileSize ; 81 Grösse der Datei in Bytes + STRUCT fh_Comment,4*23 ; 82 Kommentar als BCPL-String + ULONG fh_Days ; 105 Datum und Zeit der Erstellung + ULONG fh_Mins ; 106 + ULONG fh_Ticks ; 107 + STRUCT fh_Name,4*16 ; 108 Dateiname als BCPL-String + ULONG fh_HashChain ; 124 + ULONG fh_Parent ; 125 Zeiger auf Ursprungs-Directory + ULONG fh_Extension ; 126 Null oder Zeiger auf Extension + ULONG fh_SecondaryType ; 127 Sekundärtyp (ST.FILE) + + LABEL fh_SIZEOF + + IFNE fh_SIZEOF-BLOCKSIZE + FAIL "Bad FileHeaderBlock structure!" + ENDC + +*************************************************************************** +* CDisk-Packet (A0) abarbeiten (File aus der RAMDisk laden) + +ProcessFFSPacket: + movem.l d0-d2/d7/a0-a3/a5,-(SP) + movea.l a0,a2 ; A2 : Packet + move.l #BLOCKSIZE,d7 ; D7 : BlockSize (immer) + + move.l d7,d0 ; 1 Block + jsr meb_AllocFastMem(a6) ; reservieren + movea.l d0,a5 ; a5 : Block-Buffer + + movea.l dp_FileName(a2),a0 + bsr FindFile ; Fileheader suchen + bne.s 1$ ; OK ---> + MSG <"FFS: File not found, A0=name A2=packet"> + jmp meb_ColdReboot(a6) +1$: + bsr GetBlock ; Fileheader laden + moveq.l #ST.FILE,d0 + cmp.l fh_SecondaryType(a5),d0 ; Ist's ein File ? + beq.s 2$ ; ja ---> + MSG <"FFS: Not a file, A0=name A2=packet"> + jmp meb_ColdReboot(a6) +2$: + move.l fh_FileSize(a5),d2 ; D2 : Datei-Größe in Bytes + move.l d2,dp_FileSize(a2) ; ins Packet eintragen + + IFD CRUNCH + btst.b #5,fh_Protect+3(a5) ; Pure-Bit gesetzt ? + beq.s .NotCrunched + bset.b #DPB_CRUNCHED,dp_Flags(a2) + move.l fh_FirstData(a5),d0 ; 1. Datenblock + bsr GetBlock + moveq.l #PP_SAVEMARGIN,d2 ; Sicherheitsabstand + add.l (a5),d2 ; Plus ungecrunchte Länge + movea.l dp_FileName(a2),a0 + bsr FindFile ; Fileheader suchen + bsr GetBlock ; Fileheader laden +.NotCrunched: + ENDC + btst.b #DPB_ALLOCMEM,dp_Flags(a2) ; CHIP-Alloc gewünscht ? + beq.s .NoChipAlloc ; nein ---> + move.l d2,d0 ; File-Länge + jsr meb_AllocMem(a6) + bra.s .AllocCont ; ---> +.NoChipAlloc: + btst.b #DPB_ALLOCFASTMEM,dp_Flags(a2) ; FAST-Alloc gewünscht? + beq.s .NoFastAlloc ; nein ---> + move.l d2,d0 ; File-Länge + jsr meb_AllocFastMem(a6) +.AllocCont: move.l d0,dp_Address(a2) ; Adresse ins Packet +.NoFastAlloc: + IFD CRUNCH + move.l fh_FileSize(a5),d2 ; D2 : Datei-Größe in Bytes + ENDC + movea.l dp_Address(a2),a1 ; A1 : Ziel-Adresse +.ExtLoop: move.l fh_HighSeq(a5),d1 ; D1 : Datablock-Zähler + lea fh_BlockPtrEnd(a5),a3 ; A3 : Datenblockpointer-Zeiger + bra.s .BlockDBF ; Für DBF +.BlockLoop: move.l -(a3),d0 + cmp.l d7,d2 ; Weniger als ein Block übrig ? + blo.s .LastBlock ; ja ---> Spezialfall + movea.l a1,a0 ; Destination + bsr ReadBlock ; Datenblock nach (A0) lesen + adda.l d7,a1 ; destination += BLOCKSIZE + sub.l d7,d2 ; file size -= BLOCKSIZE +.BlockDBF dbf d1,.BlockLoop + + move.l fh_Extension(a5),d0 ; File-Extension vorhanden ? + beq.s .End ; nein ---> fertig + bsr GetBlock ; Extension-Block nach (a5) + bra.s .ExtLoop ; ---> Loop + +.LastBlock bsr GetBlock ; letzten Block nach (a5) + movea.l a5,a0 ; Source + move.l d2,d0 ; Size + jsr meb_CopyMem(a6) ; Daten kopieren +.End: + movea.l a5,a1 ; Hilfs-Block + jsr meb_FreeMem(a6) ; freigeben + + movem.l (SP)+,d0-d2/d7/a0-a3/a5 + rts + +*************************************************************************** +* File mit Namen (A0) finden und Header-Blocknummer nach D0 / CCR + +FindFile: movem.l d1-d3/a0-a2,-(SP) + + move.l meb_RAMDiskSize(a6),d0 ; Grösse der Disk + lsr.l #5,d0 ; /BLOCKSIZE/2 gibt Mitte + lsr.l #5,d0 + bsr GetBlock ; Rootblock einlesen + + bsr CalcHash ; Hashwert von (A0) berechnen + beq.s .FileNotFound ; ungültig ---> + move.l 0(a5,d0.w),d0 ; D0 : FileHeader-Blocknummer + +.BlockLoop: beq.s .FileNotFound ; Nummer ungültig ---> + bsr GetBlock ; Fileheaderblock einlesen + + movea.l a0,a1 ; Filename + lea fh_Name(a5),a2 ; Name im Fileheader + moveq.l #0,d3 + move.b (a2)+,d3 ; Stringlänge + bra.s .Dbf +.CmpLoop: move.b (a1)+,d1 + move.b (a2)+,d2 + andi.b #$df,d1 ; ToUpper + andi.b #$df,d2 ; ToUpper + cmp.b d2,d1 + bne.s .NextHash ; Nicht gleich ---> weitersuchen +.Dbf: dbf d3,.CmpLoop + +.FileNotFound: tst.l d0 ; CCR richtig setzen + movem.l (SP)+,d1-d3/a0-a2 + rts + +.NextHash: move.l fh_HashChain(a5),d0 ; Liste durchackern + bra.s .BlockLoop ; ---> Loop + +*************************************************************************** +* Hashwert des C-Strings (A0) berechnen + +CalcHash: movem.l d1/a0-a1,-(SP) + moveq.l #0,d0 ; Hashwert resetten + tst.b (a0) + beq .End + + movea.l a0,a1 ; Hash := strlen(name) +1$: tst.b (a1)+ + beq.s 2$ + addq.l #1,d0 + bra.s 1$ +2$: +.Loop: moveq.l #0,d1 + move.b (a0)+,d1 ; Nächstes Zeichen + beq.s 4$ ; Null ---> fertig + cmpi.w #'a',d1 + blo.s 3$ + cmpi.w #'z',d1 + bhi.s 3$ + andi.b #$df,d1 ; char = ToUpper(char) +3$: + mulu.w #13,d0 ; Hash *= 13 + add.l d1,d0 ; Hash += char + andi.l #$7ff,d0 ; Hash &= $7FF + bra.s .Loop +4$: + divu.w #72,d0 ; Hash %= 72 + swap d0 + ext.l d0 + addq.l #6,d0 ; Hash += 6 (Tabellenanfang) + +.End: lsl.l #2,d0 ; Hash *= 4, affect Z bit + movem.l (SP)+,d1/a0-a1 + rts + +*************************************************************************** +* Einen Block (D0=Blocknummer) in Buffer (A5) einlesen + +GetBlock: move.l a0,-(SP) + movea.l a5,a0 + bsr.s ReadBlock + movea.l (SP)+,a0 + rts + +*************************************************************************** +* Einen Block (D0=Blocknummer) an Adresse (A0) einlesen + +ReadBlock: movem.l d0/a0-a1,-(SP) + lsl.l #5,d0 ; Blocknr *BLOCKSIZE = Offset + lsl.l #4,d0 + move.l a0,a1 ; Destination + movea.l d0,a0 ; Offset + add.l meb_RAMDiskBase(a6),a0 ; Plus Basis-Adresse + move.l d7,d0 ; Länge: 1 Block + jsr meb_CopyMem(a6) + movem.l (SP)+,d0/a0-a1 + rts + + ENDC + +*************************************************************************** + + END diff --git a/FinalBooter.S b/FinalBooter.S new file mode 100644 index 0000000..aa7f0c5 --- /dev/null +++ b/FinalBooter.S @@ -0,0 +1,312 @@ +************************************************************************** +** ** +** FinalBooter - Lädt und startet Exec. ** +** ** +************************************************************************** +** ** +** 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 ** +** 30-Aug-89 CHW Adapted from Start to FinalBooter ** +** 27-Nov-89 CHW Fast-RAM implemented ** +** 15-Dec-89 CHW Code cleaned up, setzt jetzt VBR auf 0 if 68010+ ** +** 28-Mar-90 CHW Abort springt nach ColdReset() statt $fc0002 ** +** 01-Mar-91 CHW Benutzt jetzt die System-Includefiles ** +** ** +************************************************************************** + + OPT O+,OW-,O5- + + IDNT FinalBooter + SECTION text,CODE + + INCLUDE "exec/types.i" + INCLUDE "exec/macros.i" + INCLUDE "exec/memory.i" + INCLUDE "exec/nodes.i" + INCLUDE "exec/ports.i" + INCLUDE "exec/io.i" + INCLUDE "exec/execbase.i" + INCLUDE "devices/trackdisk.i" + INCLUDE "graphics/rastport.i" + INCLUDE "hardware/custom.i" + +SUPERSTACK: EQU $80000-8 ; LONGWORD-aligned +INITMAGIC: EQU 'INIT' +EXECTRACKS: EQU 3 ; Anzahl Tracks für Exec +EXECSIZE: EQU (EXECTRACKS*11-2)*512 +ABORT: EQU $1FFFFA + +TRIALS: EQU 3 ; 3x versuchen pro Drive + + XREF @Exit,_custom + XDEF @Main + +************************************************************************** + + DCB.B 8,0 + DC.B "Copyright (c) 1988-1993 by " + DC.B "Christian A. Weber, Zürich, Switzerland. " + DC.B "All rights reserved.",0 + DCB.B 6+8,0 + EVEN +@Main: + *** Evtl. Warn-Requester ausgeben + + subq.l #2,d0 ; CLI mit Args ? + bpl.b 1$ ; ja ---> no warning + bsr ShowWarning + beq.b .Exit ; Cancel ---> +1$: + *** Globale Register initialisieren + + movem.l InitRegs(PC),d5/d6/d7/a4/a5 + movea.l 4,a6 + + *** Exec einladen + + moveq #4*TRIALS-1,d4 ; Anzahl Versuche * Units -1 + moveq #0,d3 ; Aktuelle Unit +.ReadIt: bsr ReadExec ; Exec laden + bne.b .Okay ; OK ---> + addq.w #1,d3 ; INC unit + andi.w #3,d3 ; immer rund herum + dbf d4,.ReadIt ; ---> Loop +.Exit: moveq #20,d0 ; Error-Code + bra @Exit ; ---> Raus +.Okay: + *** System-Status für MyExec merken etc. + + move.w AttnFlags(a6),d3 ; FÜR MYEXEC! + move.b VBlankFrequency(a6),d2 ; FÜR MYEXEC! + + lea GfxName(PC),a1 + JSRLIB OldOpenLibrary + movea.l d0,a0 + move.w 164(a0),d4 ; FÜR MYEXEC! + + *** Chip-RAM-Obergrenze ermitteln und nach A4 + +MegaTest: lea $1000(a4),a1 ; SuperStack+$1000 + JSRLIB TypeOfMem + andi.w #MEMF_CHIP,d0 ; auch Chip ? + beq.b 1$ ; Nein, nur 512K ---> + adda.l #$10000,a4 ; 64K mehr + bra.b MegaTest ; Weiter probieren +1$: + *** Grössten Fast-RAM-Block reservieren und nach A2, Ende nach A3 + + JSRLIB Disable ; INTERRUPTS FUER IMMER WEG! + +_getfast: suba.l a2,a2 ; Default: No FAST RAM + suba.l a3,a3 ; Grösse 0 + move.l #MEMF_FAST|MEMF_LARGEST,d1 + JSRLIB AvailMem ; FAST-RAM-Grösse bestimmen + cmpi.l #300000,d0 ; genug damit sich's lohnt ? + blo.b 1$ ; nein ---> + movea.l d0,a3 ; Size + moveq.l #MEMF_FAST,d1 + JSRLIB AllocMem + movea.l d0,a2 ; A2: FastRAM-Base + adda.l d0,a3 ; A3: FastRAM-End +1$: + *** Supervisor-Mode, Interrupts sperren + +_supie: move.w d7,dmacon(a5) + move.w d7,intena(a5) + lea 1$(PC),a5 + JSRLIB Supervisor +1$: lea _custom,a5 + move #$2700,sr + movea.l a4,SP ; SupieStack init + btst #AFF_68010,d3 ; 68010+ ? + beq.b 2$ ; nein ---> + suba.l a0,a0 + DC.L $4E7B8801 ; movec.l a0,vbr +2$: + *** MyExec installieren und starten + +_installexec: movea.l d5,a0 ; Source: Exec-Ladeadresse + suba.l a1,a1 ; Destination: 0 + move.l d6,d0 ; ExecSize + ;; bra.b 2$ ; Für dbf, macht aber nix aus +1$: move.b (a0)+,(a1)+ +2$: dbf d0,1$ + + move.l d3,d0 ; AttnFlags + move.l d4,d1 ; Bplcon0 + move.l MyProduct(PC),d3 ; Von DiskMaker eingetragen + suba.l a0,a0 ; WICHTIG FüR CDISK !! + suba.l a1,a1 ; WICHTIG FüR CDISK !! + + suba.l a4,a4 +3$: cmpi.l #INITMAGIC,(a4) + beq.b 4$ + addq.l #2,a4 ; WORD-weise schreiten + bra.b 3$ +4$: + move.l a4,d6 ; Adresse der Vektoren-4 + add.l #$4ef80008,d6 ; JMP<<16+4+4 (=2. Einspr.) + move.l d6,ABORT ; JMP ColdReset().W + move.w #$000,color(a5) + jmp 4(a4) ; Tada! (=1. Einspr.) + +************************************************************************** + +ReadExec: + + *** IO-Request und Port initialisieren + +_initio: lea MyPort,a0 ; A0 : The Port + move.l ThisTask(a6),MP_SIGTASK(a0) + move.b #NT_MSGPORT,LN_TYPE(a0) + ;; move.b #PA_SIGNAL,MP_FLAGS(a0) + move.b #17,MP_SIGBIT(a0) + + lea MyIO,a2 ; A2 : The IO-Request + move.b #NT_MESSAGE,LN_TYPE(a2) + move.w #IOSTD_SIZE,MN_LENGTH(a2) + move.l a0,MN_REPLYPORT(a2) + + lea MP_MSGLIST(a0),a0 ; Die Message-Liste + move.l a0,LH_HEAD(a0) ; Macro NewList + addq.l #LH_TAIL,(a0) + ;; clr.l LH_TAIL(a0) + move.l a0,LH_TAILPRED(a0) + + *** Trackdisk.device öffnen + + move.l d3,d0 ; Unit number + moveq #0,d1 ; Flags + lea TrackDiskName(PC),a0 + movea.l a2,a1 ; IOStdRequest Struktur + JSRLIB OpenDevice + tst.l d0 ; OK ? + bne.b .ReadError ; nein ---> + + *** Exec von Track 0 einlesen + + move.w #CMD_READ,IO_COMMAND(a2) + move.l d6,IO_LENGTH(a2) ; ExecSize + move.l d5,IO_DATA(a2) ; ExecAdr + moveq.l #64,d0 + lsl.l #4,d0 ; Gibt 1024 + move.l d0,IO_OFFSET(a2) + movea.l a2,a1 ; IO-Request + JSRLIB DoIO + tst.b d0 ; Error ? + bne.b .ReadError ; ja ---> + + *** Motor abschalten + + move.w #TD_MOTOR,IO_COMMAND(a2) + clr.l IO_LENGTH(a2) ; Motor off + movea.l a2,a1 ; IO-Request + JSRLIB DoIO + + *** Test ob's unser Exec ist + + movea.l d5,a0 + tst.l (a0) ; Ist's unser Exec ? + bne.b .ReadError ; nein ---> + cmpi.l #'CHW!',$c0(a0) ; Sicher ? + beq.b .ExecOK ; ja ---> Success + +.ReadError: moveq #0,d2 ; Error-Code: FAIL + bra.b 1$ ; ---> + +.ExecOK: moveq #1,d2 ; Error-Code: SUCCESS + +1$: movea.l a2,a1 + tst.l IO_DEVICE(a1) + bmi.b 2$ + JSRLIB CloseDevice +2$: move.l d2,d0 ; Set/Reset Z bit + rts + +************************************************************************** + +ShowWarning: lea IntuiName(PC),a1 + movea.l 4,a6 + JSRLIB OldOpenLibrary + movea.l d0,a6 + + suba.l a0,a0 ; Window + lea body(PC),a1 + lea ptext(PC),a2 + lea ntext(PC),a3 + moveq.l #0,d0 ; pflag + moveq.l #0,d1 ; nflag + move.w #530,d2 ; width + moveq.l #78,d3 ; height + JSRLIB AutoRequest + tst.l d0 ; Z == CANCEL ? 1:0 + rts + +************************************************************************** + +GfxName: dc.b "graphics.library",0 +IntuiName: dc.b "intuition.library",0 +TrackDiskName: dc.b "trackdisk.device",0 + + EVEN + +InitRegs: dc.l ExecBSS ; D5 : Exec-Ladeadresse + dc.l EXECSIZE ; D6 : Exec-LadeGröße + dc.l $7fff ; D7 : Int/DMADisable-Maske + dc.l SUPERSTACK ; A4 : SuperStack + dc.l _custom ; A5 : Custom + + +ProdMagic: dc.l 'PROD' ; Muss vor MyProduct stehen +MyProduct: dc.l 0 ; Wird von DiskMaker eingesetzt + + EVEN +body: dc.b 2,1,RP_JAM1,0 + dc.w 14,8 + dc.l 0,bodytext,body2 + +body2: dc.b 2,1,RP_JAM1,0 + dc.w 14,18 + dc.l 0,body2text,body3 + +body3: dc.b 2,1,RP_JAM1,0 + dc.w 14,28 + dc.l 0,body3text,0 + +ptext: dc.b 2,1,RP_JAM2,0 + dc.w 6,3 + dc.l 0,ptexttext,0 + +ntext: dc.b 2,1,RP_JAM2,0 + dc.w 6,3 + dc.l 0,ntexttext,0 + +bodytext: dc.b "WARNING: This program will shut down the Amiga's",0 +body2text: dc.b "------- multi-tasking system. Finish all running",0 +body3text: dc.b " programs before selecting 'START GAME' !",0 +ptexttext: dc.b "START GAME",0 +ntexttext: dc.b "CANCEL",0 + + + SECTION bss,BSS + +MyIO: ds.b IOSTD_SIZE+32 + +MyAttnFlags: ds.w 1 +MySysBplcon0: ds.w 1 +MyVBlankFreq: ds.w 1 + +MyPort: ds.b MP_SIZE+32 + + EVEN +ExecBSS: ds.b EXECSIZE+32 ; Hierhin wird's geladen + + + END diff --git a/Keyboard.S b/Keyboard.S new file mode 100644 index 0000000..50fdb2d --- /dev/null +++ b/Keyboard.S @@ -0,0 +1,423 @@ +************************************************************************** +** ** +** Keyboard.S - Routinen zum Keyboard-Handling ohne System ** +** ** +************************************************************************** +** ** +** Modification History ** +** -------------------- ** +** ** +** 13-Jun-88 Created this file! ** +** 29-May-89 SetMap function added ** +** 06-Jun-89 SetResetHandler function added ** +** 10-Nov-89 Numeric pad keys ()/*+- implemented ** +** 30-Mar-90 HELP key no longer used to exit/reset ** +** 30-Sep-90 Shift-Sternchen (Numeric Pad) ist ROMCrack-Einsprung ** +** 27-Feb-91 System-taugliche Version falls SYSTEM definiert ** +** ** +************************************************************************** + + IDNT Keyboard + SECTION text,CODE + + INCLUDE "MyExec.i" + INCLUDE "hardware/custom.i" + + IFD SYSTEM + INCLUDE "exec/macros.i" + INCLUDE "exec/io.i" + INCLUDE "devices/input.i" + INCLUDE "devices/inputevent.i" + ENDC + + XREF _custom,__MyExecBase + + IFD SYSTEM + XREF _idstring,@CreateIO,@DeleteIO + XDEF ExitKeyFunc + ENDC + XDEF InitKeyFunc + XDEF GetKeyFunc,WaitKeyFunc,FlushKeyBufFunc + XDEF SetMapFunc,SetResetHandlerFunc,SetCheatTextFunc + +KEYBUFSIZE: EQU 40 ; Grösse des Tastaturpuffers in Bytes + +************************************************************************** +* Keyboard-Interrupt bzw. Input-Handler initialisieren + +InitKeyFunc: + IFD SYSTEM + movem.l d1/a0-a2/a6,-(SP) + moveq.l #IOSTD_SIZE,d0 + bsr @CreateIO + move.l d0,InputIOReq + beq.s 1$ + movea.l d0,a2 + + moveq #0,d0 ; Unit + moveq #0,d1 ; Flags + lea InputName(PC),a0 + movea.l a2,a1 + movea.l 4,a6 + JSRLIB OpenDevice + + movea.l a2,a1 + move.w #IND_ADDHANDLER,IO_COMMAND(a1) + move.l #MyInterrupt,IO_DATA(a1) + JSRLIB DoIO +1$: + movem.l (SP)+,d1/a0-a2/a6 + ELSEIF + move.l a0,-(SP) + lea KeyboardServer(PC),a0 + move.l a0,meb_CiaASerialVector(a6) + move.w #$8008,_custom+intena ; Interrupt zulassen + move.b #$88,$bfed01 ; Im CIA ICR auch + move.l (SP)+,a0 + ENDC + rts + +************************************************************************** +* Keyboard-Inputhandler wieder rausschmeissen + + IFD SYSTEM +ExitKeyFunc: movem.l d1-d2/a0-a1/a6,-(SP) + move.l InputIOReq,d2 + beq.s 1$ + movea.l d2,a1 + move.w #IND_REMHANDLER,IO_COMMAND(a1) + move.l #MyInterrupt,IO_DATA(a1) + movea.l 4,a6 + JSRLIB DoIO + + movea.l d2,a1 + JSRLIB CloseDevice + + movea.l d2,a1 ; IO-Request + ;; MSG <"Trying to DeleteIO (a1)"> + ;; bsr @DeleteIO ; freigeben + clr.l InputIOReq +1$: + movem.l (SP)+,d1-d2/a0-a1/a6 + rts + ENDC + +************************************************************************** + + *** ASCII-Zeichen aus Tastaturpuffer lesen, Null falls nix gedrückt + +GetKeyFunc: movem.l d1/a0,-(SP) + IFD SYSTEM + btst.b #EXECB_RESETREQUEST,meb_ExecFlags(a6) + beq.s 1$ + jmp meb_ColdReboot(a6) +1$: + ENDC + moveq.l #0,d0 ; Default: Null + move.w KeyBufPtr,d1 + beq.s .NoKey + subq.w #1,d1 + jsr meb_Disable(a6) + move.w d1,KeyBufPtr + lea KeyBuf,a0 + move.b (a0),d0 ; nächstes Zeichen +2$: move.b 1(a0),(a0)+ ; Puffer verschieben + dbf d1,2$ + jsr meb_Enable(a6) +.NoKey: tst.b d0 ; key ok ? Z=0 : Z=1 + movem.l (SP)+,d1/a0 + rts + +************************************************************************** + + *** ASCII-Zeichen aus Tastaturpuffer lesen, warten falls nix parat + +WaitKeyFunc: bsr GetKeyFunc + bne.s 1$ + move.b $bfe001,d0 + not.b d0 + andi.b #3,d0 ; Knopf Port 0 oder 1 gedrückt ? + beq.s WaitKeyFunc ; Nein ---> loop + moveq #0,d0 ; Gedrücktes Zeichen: 0 +1$: rts + +************************************************************************** + + *** Tastaturpuffer leeren + +FlushKeyBufFunc: + clr.w KeyBufPtr + clr.b meb_ActualQualifiers(a6) ; ** DEBUG ** billiges trick! + rts + +************************************************************************** + + *** Keymap (A0) setzen, Default falls A0 == 0 + +SetMapFunc: movem.l d0/a0,-(SP) + move.l a0,d0 ; A0 == 0 ? + bne.s 1$ ; nein ---> + lea DefaultKeyMap(PC),a0 +1$: move.l a0,KeyMapPtr + movem.l (SP)+,d0/a0 + rts + +************************************************************************** + + *** ResetHandler (A0) setzen, Default falls A0 == 0 + +SetResetHandlerFunc: + movem.l d0/a0,-(SP) + move.l a0,d0 ; A0 == 0 ? + bne.s 1$ ; nein ---> + lea meb_ColdReboot(a6),a0 +1$: move.l a0,ResetHandler + movem.l (SP)+,d0/a0 + rts + +************************************************************************** + + *** Cheat-Text (A0) setzen, Default falls A0 == 0 + +SetCheatTextFunc: + movem.l d0/a0,-(SP) + move.l a0,d0 ; A0 == 0 ? + bne.s 1$ ; nein ---> + lea DefaultCheatText,a0 +1$: move.l a0,CheatTextPtr + move.l a0,CheatPtr + movem.l (SP)+,d0/a0 + rts + +************************************************************************** + + *** IRQ-Routine der Tastatur, wird bei IRQ 2 (PORTS) angesprungen + +KeyboardServer: + IFD SYSTEM + btst #8,$dff016 ; Mittlere Maustaste ? + bne.s 0$ ; nee + move.l a0,d0 ; Sonst Handler beenden + rts + +0$: movem.l d1/a0-a3/a5-a6,-(SP) + lea _custom,a5 + movea.l a1,a6 ; A6: MyExecBase + movea.l a0,a1 ; A1: EventChain + suba.l a2,a2 ; A2: Vorheriges event + movea.l a0,a3 ; A3: Neue chain + +1$: cmpi.b #IECLASS_RAWKEY,ie_Class(a1) + bne.s 2$ + move.w ie_Code(a1),d0 + bsr RawKeyConvert + bsr CheatTest + bra.s .delink +2$: + cmpi.b #IECLASS_RAWMOUSE,ie_Class(a1) + bne.s 4$ + +.delink: move.l a2,d0 ; 1. Event ? + beq.s 3$ ; ja ---> + move.l ie_NextEvent(a1),ie_NextEvent(a2) + bra.s 4$ +3$: movea.l ie_NextEvent(a1),a3 +4$: + movea.l ie_NextEvent(a1),a1 ; Nächstes Event + move.l a1,d0 ; Liste fertig ? + bne.s 1$ ; nein ---> Loop + + bsr ResetTest ; Reset-Handler nötig ? + + move.l a3,d0 + movem.l (SP)+,d1/a0-a3/a5-a6 + rts + ELSEIF + movem.l d0-d7/a0-a5,-(SP) + lea _custom,a5 + + moveq #0,d0 + move.b $bfec01,d0 ; read SDR + bset.b #6,$bfee01 ; Quittierung starten + not.b d0 + ror.b #1,d0 ; up/down code ins Bit 7 + bsr RawKeyConvert + bsr CheatTest + +;; IFD RAMVERSION + cmpi.b #$5D,d0 ; Sternchen aufm Zahlenblock ? + bne.s .NoRC ; nein ---> + move.b meb_ActualQualifiers(a6),d1 + andi.b #3,d1 ; left or right shift ? + beq.s .NoRC ; nein ---> + movem.l (SP)+,d0-d7/a0-a5 + move.l ((6+1)*4)+2(SP),a0 ; Rücksprungadresse vom Interrupt + jsr meb_Debug(a6) ; ROMCrack aufrufen + movem.l d0-d7/a0-a5,-(SP) +.NoRC: +;; ENDC + moveq #15,d0 ; 16 * 64 Mikrosec. warten +bratfett: move.b vhposr(a5),d1 +1$: cmp.b vhposr(a5),d1 + beq.s 1$ + dbf d0,bratfett + + bclr.b #6,$bfee01 ; Quittierung beenden + bsr ResetTest ; Reset-Handler nötig ? + + movem.l (SP)+,d0-d7/a0-a5 + rts + ENDC + +************************************************************************** + + *** Raw-Code (D0.B) nach ActualKey und auch nach ASCII wandeln + +RawKeyConvert: ext.w d0 ; auf WORD erweitern für Index + bmi keyup ; Key Up ---> + +keydown: cmpi.b #$60,d0 ; shift, alt, ctrl amiga etc. ? + blt.s 1$ ; nein ---> + cmpi.b #$68,d0 ; > $68 (Error, etc.) ? + bge keyerror ; ja ---> + bset.b d0,meb_ActualQualifiers(a6) ; entspr. Bit setzen (0-7) + bra keyend +1$: + move.b d0,meb_ActualKey(a6) ; Raw-Code eintragen + move.b meb_ActualQualifiers(a6),d1 + andi.b #7,d1 ; left, right shift or caps lock? + beq.s 2$ ; nein ---> + addi.w #$60,d0 ; shift: Daten aus Tabelle 2 +2$: movea.l KeyMapPtr,a0 ; Zeiger auf aktuelle Keymap + move.b 0(a0,d0.w),d0 + move.b d0,meb_ActualASCIIKey(a6) + beq.s keyend ; wenn 0: ignorieren + move.w KeyBufPtr,d1 ; D0 in den Tastaturpuffer + cmpi.w #KEYBUFSIZE,d1 ; Tastaturpuffer voll? + bge.s 3$ ; ja --> Key ignorieren + lea KeyBuf,a0 + move.b d0,0(a0,d1.w) + addq.w #1,KeyBufPtr ; Anzahl erhöhen +3$: bra.s keyend ; ---> + +keyup: bclr #7,d0 ; Up/Down-Bit löschen + cmpi.b #$60,d0 ; shift, alt, ctrl amiga etc. ? + blt.s dokeyup ; nein ---> + cmpi.b #$68,d0 ; > $68 (Error, etc.) ? + bge.s keyerror ; ja ---> + bclr.b d0,meb_ActualQualifiers(a6) ; entspr. Bit löschen (0-7) + bra.s keyend + +keyerror: clr.b meb_ActualQualifiers(a6) +dokeyup: clr.b meb_ActualKey(a6) + clr.b meb_ActualASCIIKey(a6) +keyend: rts + +************************************************************************** +* Testet Tastatur, ob CHEAT Mode angeschaltet werden soll + +CheatTest: move.l CheatPtr,a0 ; nächstes Zeichen, das kommt + move.b meb_ActualKey(a6),d0 ; Tastaturcode holen + beq.s 3$ ; nichts gedrückt ---> + cmp.b (a0)+,d0 ; richtiges Zeichen? + bne.s 2$ ; nein ---> + move.l a0,CheatPtr ; dort gehts weiter + tst.b (a0) ; alle Zeichen eingegeben? + bne.s 3$ ; nein ---> + not.b meb_CheatFlag(a6) ; Flag umdrehen + move.w #10000,d0 +1$: move.w #$eef,color(a5) ; kurzes Flackern + tst.w vhposr(a5) ; Processor independant + dbf d0,1$ + move.w #$000,color(a5) +2$: move.l CheatTextPtr,CheatPtr ; wieder vorne anfangen +3$: rts + +************************************************************************** + + *** Testet ob 2 der 3 Reset-Tasten gedrückt sind + +ResetTest: move.b meb_ActualQualifiers(a6),d0 + andi.b #%11001000,d0 ; Nur Ctrl, LeftAmiga, RightAmiga + cmpi.b #%11000000,d0 + beq.s 1$ + cmpi.b #%10001000,d0 + beq.s 1$ + cmpi.b #%01001000,d0 + bne.s 2$ +1$: + IFD SYSTEM + bset.b #EXECB_RESETREQUEST,meb_ExecFlags(a6) + ELSEIF + movea.l ResetHandler,a0 + jsr (a0) + ENDC +2$: + rts + +************************************************************************** + + *** KeyMap Ohne Shift (auch im CODE-Segment!) + +DefaultKeyMap: + dc.b 96,049,050,051,052,053,054,055 ; 00-07 `1234567 + dc.b 56,057,048,045,061,092,000,048 ; 08-0F 890-=\ 0 + dc.b 113,119,101,114,116,121,117,105 ; 10-17 qwertyui + dc.b 111,112,091,093,000,049,050,051 ; 18-1F op[] 123 + dc.b 97,115,100,102,103,104,106,107 ; 20-27 asdfghjk + dc.b 108,059,039,036,000,052,053,054 ; 28-2F l;'$ 456 ($ on VSM) + dc.b 60,122,120,099,118,098,110,109 ; 30-37 <zxcvbnm (< on VSM) + dc.b 44,046,047,000,046,055,056,057 ; 38-3F ,./ .789 + dc.b 32,008,009,010,010,027,127,000 ; 40-47 SPCBSTABCR CRESCDELnix + dc.b 00,000,045,000,016,017,019,018 ; 48-4F nixnix-nix UPDWNFWBW + dc.b 241,242,243,244,245,246,247,248 ; 50-57 f1-f8 + dc.b 249,250,040,041,047,042,043,021 ; 58-5F f9f10() /*+HELP (numpad) + + *** Mit Shift + + dc.b 126,033,064,035,036,037,094,038 ; 00-07 ~!@#$%^& + dc.b 42,040,041,000,043,124,000,048 ; 08-0F *()_+| 0 + dc.b 81,087,069,082,084,089,085,073 ; 10-17 QWERTYUI + dc.b 79,080,123,125,000,049,050,051 ; 18-1F OP{} 123 + dc.b 65,083,068,070,071,072,074,075 ; 20-27 ASDFGHJK + dc.b 76,058,034,092,000,052,053,054 ; 28-2F L:"Pfund 456 (Pfund on VSM) + dc.b 62,090,088,067,086,066,078,077 ; 30-37 >ZXCVBNM (> on VSM) + dc.b 60,062,063,000,000,055,056,057 ; 38-3F <>? 789 + dc.b 32,008,009,000,000,000,127,000 ; 40-47 SPCBSTABCR CRESCDELnix + dc.b 00,000,000,000,016,017,019,018 ; 48-4F nixnixPADnix UPDWNFWBW + dc.b 00,000,000,000,000,000,000,000 ; 50-57 f1-f8 + dc.b 00,000,000,000,000,000,000,021 ; 58-5F f9f10 5*nix HELP + +************************************************************************** + + IFD SYSTEM +InputName: dc.b "input.device",0 + EVEN + ENDC + + SECTION Keyboard,DATA + +CheatTextPtr: dc.l DefaultCheatText ; Zeiger auf Anfang +CheatPtr: dc.l DefaultCheatText ; Zeiger auf akt. Zeichen + +DefaultCheatText: + dc.b $21,$33,$20,$37,$20,$24,$17,$33,0 ; scamagic + EVEN + +ResetHandler: dc.l __MyExecBase+meb_ColdReboot +KeyMapPtr: dc.l DefaultKeyMap ; Zeiger auf aktuelle KeyMap +KeyBufPtr: dc.w 0 +KeyBuf: dcb.b KEYBUFSIZE+2,0 + EVEN + + IFD SYSTEM +MyInterrupt: dc.l 0,0 + dc.b 0,120 + dc.l _idstring ; LN_NAME + dc.l __MyExecBase ; IS_DATA + dc.l KeyboardServer ; IS_CODE + +InputIOReq: dc.l 0 + ENDC + + END diff --git a/LoadSeg.S b/LoadSeg.S new file mode 100644 index 0000000..97040d0 --- /dev/null +++ b/LoadSeg.S @@ -0,0 +1,211 @@ +************************************************************************** +** ** +** Modification History ** +** -------------------- ** +** ** +** 15-May-89 CHW Created this file! ** +** 24-Oct-90 CHW Schrottet die Memoryliste nicht mehr ** +** ** +************************************************************************** + + IDNT LoadSeg + SECTION text,CODE + + INCLUDE "MyExec.i" + + XREF AllocMemFunc,FreeMemFunc + XREF LoadFileFunc,LoadFastFileFunc + + XDEF LoadSegFunc,UnLoadSegFunc + +SEGMAGIC: EQU 'SEG2' ; Neues Format +RELOCMAGIC: EQU 'RLOC' + +*************************************************************************** + + IFD sakdksdhgksdjhg + +'struct' SpecialFile +{ + ULONG ID; /* Segment-Start-Magic SPECIAL_SEGID */ + ULONG CodeSize; /* CODE-Size (FAST-RAM) in Bytes */ + ULONG DataSize; /* DATA-Size (CHIP-RAM) in Bytes */ + ULONG BSSSize; /* BSS-Size, mindestens 4 Bytes FAST RAM */ + + BYTE Code[0]; /* CodeSize Bytes, geht ins FAST RAM */ + + ULONG rloc1; /* muss SPECIAL_RELOC sein */ + ULONG Numccrelocs; /* Anzahl folgende Relocs */ + BYTE CCRelocs[0]; /* Im Code nach Code relocs */ + + ULONG rloc2; /* muss SPECIAL_RELOC sein */ + ULONG Numcdrelocs; /* Anzahl folgende Relocs */ + BYTE CDRelocs[0]; /* Im Code nach Data relocs */ + + ULONG rloc3; /* muss SPECIAL_RELOC sein */ + ULONG Numcbrelocs; /* Anzahl folgende Relocs */ + BYTE CBRelocs[0]; /* Im Code nach BSS relocs */ + + + BYTE Data[0]; /* DataSize Bytes, geht ins CHIP RAM */ + + ULONG rloc4; /* muss SPECIAL_RELOC sein */ + ULONG Numdcrelocs; /* Anzahl folgende Relocs */ + BYTE DCRelocs[0]; /* Im Data nach Code relocs */ + + ULONG rloc5; /* muss SPECIAL_RELOC sein */ + ULONG Numddrelocs; /* Anzahl folgende Relocs */ + BYTE DDRelocs[0]; /* Im Data nach Data relocs */ + + ULONG rloc6; /* muss SPECIAL_RELOC sein */ + ULONG Numdbrelocs; /* Anzahl folgende Relocs */ + BYTE DBRelocs[0]; /* Im Data nach BSS relocs */ +}; + + ENDC + +*************************************************************************** + + *** D0 : Filename + +LoadSegFunc: movem.l d1-d6/a0-a5,-(SP) + move.l #-RELOCMAGIC,d5 + bsr LoadFastFileFunc ; File ins FAST RAM einladen + movea.l d0,a2 ; A2 : File-Base + move.l a2,d6 ; D6 : File-Base für später + neg.l d5 ; Gegen Cracker + + *** Parameter aus FileHeader holen + + move.l #~SEGMAGIC,d0 + not.l d0 ; Gegen Cracker + cmp.l (a2)+,d0 ; Kennung OK ? + beq.s 1$ ; ja ---> + MSG <"Not an object module, D6=File"> + jmp meb_ColdReboot(a6) +1$: + movem.l (a2)+,d2-d4 ; D2 : CODESIZE, D3: DATASIZE + ; D4 : BSSSIZE + + *** Speicher für Code, Data und BSS allozieren + + move.l d2,d0 ; CODE-Size + addq.l #8,d0 ; Platz für DATA- und BSS-Zeiger + jsr meb_AllocFastMem(a6) ; FAST RAM reservieren + movea.l d0,a3 ; A3 : CODE-Segment + + move.l d3,d0 ; DATA-Size + jsr meb_AllocMem(a6) ; CHIP RAM reservieren + movea.l d0,a4 ; A4 : DATA-Segment + move.l a4,(a3)+ ; in Code-Segment merken + + move.l d4,d0 ; BSS-Size + jsr meb_AllocClearMem(a6) ; BSS wird gelöscht + movea.l d0,a5 ; A5 : BSS-Segment + move.l a5,(a3)+ ; in Code-Segment merken + + *** Code ins Code-Segment rüberkopieren, FilePtr auf Relocs + + movea.l a2,a0 ; Source: File + movea.l a3,a1 ; Destination: Code-Segment + move.l d2,d0 ; Code-Size + jsr meb_CopyMem(a6) ; Segment kopieren + adda.l d2,a2 ; File-Zeiger vorrücken + + *** Code to Code/Data/BSS Relocs ausführen + *** Relocs sind 16bit signed deltas oder 0 und dann 32bit signed + + cmp.l (a2)+,d5 ; Magic vorhanden ? + bne BadReloc ; nein ---> Error + move.l (a2)+,d0 ; Anzahl Code-Code-Relocs + move.l a3,d1 ; Zu addierender Wert + movea.l a3,a0 ; Zu relozierender Code + bsr DoReloc + + cmp.l (a2)+,d5 ; Magic vorhanden ? + bne BadReloc ; nein ---> Error + move.l (a2)+,d0 ; Anzahl Code-Data-Relocs + move.l a4,d1 ; Zu addierender Wert + movea.l a3,a0 ; Zu relozierender Code + bsr DoReloc + + cmp.l (a2)+,d5 ; Magic vorhanden ? + bne BadReloc ; nein ---> Error + move.l (a2)+,d0 ; Anzahl Code-BSS-Relocs + move.l a5,d1 ; Zu addierender Wert + movea.l a3,a0 ; Zu relozierender Code + bsr DoReloc + + *** Data ins Data-Segment rüberkopieren, FilePtr auf Relocs + + movea.l a2,a0 ; Source: File + movea.l a4,a1 ; Destination: Data-Segment + move.l d3,d0 ; Data-Size + jsr meb_CopyMem(a6) ; Segment kopieren + adda.l d3,a2 ; File-Zeiger vorrücken + + *** Data to Code/Data/BSS Relocs ausführen + + cmp.l (a2)+,d5 ; Magic vorhanden ? + bne BadReloc ; nein ---> Error + move.l (a2)+,d0 ; Anzahl Data-Code-Relocs + move.l a3,d1 ; Zu addierender Wert + movea.l a4,a0 ; Zu relozierender Code + bsr DoReloc + + cmp.l (a2)+,d5 ; Magic vorhanden ? + bne BadReloc ; nein ---> Error + move.l (a2)+,d0 ; Anzahl Data-Data-Relocs + move.l a4,d1 ; Zu addierender Wert + movea.l a4,a0 ; Zu relozierender Code + bsr DoReloc + + cmp.l (a2)+,d5 ; Magic vorhanden ? + bne BadReloc ; nein ---> Error + move.l (a2)+,d0 ; Anzahl Data-BSS-Relocs + move.l a5,d1 ; Zu addierender Wert + movea.l a4,a0 ; Zu relozierender Code + bsr DoReloc + + *** Ur-File freigeben + + movea.l d6,a1 ; File + jsr meb_FreeMem(a6) +LoadSegEnd: + move.l a3,d0 ; The File + movem.l (SP)+,d1-d6/a0-a5 + rts + +BadReloc: MSG <"Bad reloc, D6=File"> + jmp meb_ColdReboot(a6) + + + *** D0=Anzahl, D1=Offset, A0=Segment, A2=File, wird vorgerückt + +DoReloc: movem.l d1-d3,-(SP) + moveq.l #0,d2 ; Reloc-Pointer resetten + bra.s 3$ ; Für dbf +1$: move.w (a2)+,d3 ; Nächste Adresse + ext.l d3 ; auf Langwort erweitern + bne.s 2$ ; nicht 0 ---> 16bit-delta + move.l (a2)+,d3 ; sonst 32bit-delta +2$: add.l d3,d2 ; Delta-Wert addieren + add.l d1,0(a0,d2.l) ; Tada! +3$: dbf d0,1$ + movem.l (SP)+,d1-d3 + rts + +*************************************************************************** + + *** A1 : Segmentliste von LoadSeg() + +UnLoadSegFunc: movem.l a0-a1,-(SP) + movea.l a1,a0 + movea.l -(a0),a1 ; A1 : BSS-Segment + jsr meb_FreeMem(a6) ; Segment freigeben + movea.l -(a0),a1 ; A1 : Data-Segment + jsr meb_FreeMem(a6) ; Segment freigeben + movea.l a0,a1 ; A1 : CodeSegment + jsr meb_FreeMem(a6) ; Segment freigeben + movem.l (SP)+,a0-a1 + rts diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bc8b7c1 --- /dev/null +++ b/Makefile @@ -0,0 +1,110 @@ +########################################################################## +# # +# Makefile für das mega-geniale Game-Exec-Betriebssystem von CHW :-) # +# # +# Created: 18-May-89 CHW Last update: 23-Feb-91 CHW # +# # +########################################################################## + + +CC = SC +CFLAGS = + +ASM = Genam +AFLAGS = -l -iINCLUDE: + +LD = Slink +LFLAGS = ADDSYM NOICONS + + + +.c.o: + $(CC) $(CFLAGS) $*.c + +.S.or: + -@Delete $@ + $(ASM) $(AFLAGS) $*.S -o$*.or -eRAMVERSION=1 + +.S.os: + -@Delete $@ + $(ASM) $(AFLAGS) $*.S -o$*.os -eSYSTEM=1 + +.S.o: + -@Delete $@ + $(ASM) $(AFLAGS) $*.S -o$*.o -eDISKVERSION=1 + + + +RAMMODS = Exec.or Memory.or LoadSeg.or Keyboard.or CDisk.or RAMLib.or\ + PPDecrunch.or RawDoFmt.or DrawBob.or Rnd.or FFS.or EndLabel.or + +SYSMODS = Exec.os Memory.os LoadSeg.os Keyboard.os SysCDisk.os RAMLib.os\ + PPDecrunch.os RawDoFmt.os DrawBob.os Rnd.os CDTV.os EndLabel.os + +DISKMODS = Exec.o Memory.o LoadSeg.o Keyboard.o CDisk.o RAMLib.o\ + PPDecrunch.o RawDoFmt.o DrawBob.o Rnd.o FFS.o EndLabel.o + + + +All: Track0 Start SysStart FinalBooter Disk-Validator + +$(RAMMODS): myexec.i +$(DISKMODS): myexec.i +$(SYSMODS): myexec.i +DrawBob.o: DrawBob.i + + +RAMExec.S: $(RAMMODS) + $(LD) $(LFLAGS) FROM $(RAMMODS) TO T:__exectmp LIB LIB:small.lib + AbsLoad >NIL: -a0 -o T:__exectmp2 T:__exectmp + HexDump -L -X _ExecModuleStart -Y _ExecModuleEnd -O$@ T:__exectmp2 + @Delete T:__exectmp T:__exectmp2 + +Track0: $(DISKMODS) + $(LD) $(LFLAGS) FROM $(DISKMODS) TO T:__exectmp LIB LIB:small.lib + AbsLoad >NIL: -a0 -o T:__exectmp2 T:__exectmp + Join BootBlock T:__exectmp2 as Track0 + @Delete T:__exectmp T:__exectmp2 QUIET + +Start: start.o RAMExec.o + -@Delete $@ + $(LD) $(LFLAGS) FROM CCLIB:argsstartup20.o start.o ramexec.o TO $* \ + LIB CCLIB:ch.lib LIB:sc.lib LIB:small.lib + +SysStart: sysstart.o $(SYSMODS) + -@Delete $@ + $(LD) $(LFLAGS) FROM CCLIB:argsstartup20.o Sysstart.o $(SYSMODS) TO $* \ + LIB CCLIB:ch.lib LIB:sc.lib LIB:small.lib + +FinalBooter: FinalBooter.o + -@Delete $@ + $(LD) $(LFLAGS) FROM cclib:TinyStartup.o $*.o TO T:__exectmp LIB cclib:ch.lib LIB:small.lib + AbsLoad -©cb -o$@ T:__exectmp + @Delete T:__exectmp + +Disk-Validator: FinalBooter.S + -@Delete $@ + $(ASM) FinalBooter.S -o$@ -eBCPL=1 + + +clean: + Delete *.o *.os *.or Track0 Start SysStart FinalBooter Disk-Validator ramexec.s + + +install: + Copy MyExec.i DrawBob.i INCUSR: CLONE + Copy Start C+:Proprietary/ CLONE + Copy SysStart C+:Proprietary/ CLONE + + +dist: Start Track0 + -@Delete Exec.LHA + @lha -x -a a Exec.LHA Start Track0 MyExec.i DrawBob.i + @lha -x -a v Exec.LHA + +srcdist: Start BootBlock CDisk.o CDisk.r + -@Delete ExecSource.LHA + @lha -x -a a ExecSource.LHA *.S *.c + @lha -x -a d ExecSource.LHA ramexec.s + @lha -x -a a ExecSource.LHA BootBlock CDisk.o CDisk.r *.i Makefile + @lha -x -a v ExecSource.LHA diff --git a/Memory.S b/Memory.S new file mode 100644 index 0000000..ae6b75c --- /dev/null +++ b/Memory.S @@ -0,0 +1,416 @@ +************************************************************************** +** ** +** MEMORY - Die schnellste, beste, kürzeste Speicherverwaltung :-) ** +** ** +** by Christian A. Weber, Zurich/Switzwerland ** +** ** +************************************************************************** +** ** +** Modification History ** +** -------------------- ** +** ** +** 15-May-89 CHW Created this file! ** +** 27-Nov-89 CHW Fast-Memory added ** +** 30-Jul-90 CHW Chip allocation for AllocFastMem() works now ** +** 18-Sep-90 CHW Chip allocation for AllocFastMem() really works ** +** 20-Nov-90 CHH NoMemHandler eingebaut ** ** +** ** +************************************************************************** + + OPT OW6+ + + IDNT Memory + SECTION text,CODE + + INCLUDE "MyExec.i" + + XREF MyNoMemHandler + + XDEF InitChipMemFunc,InitFastMemFunc + XDEF AllocMemFunc,AllocClearMemFunc + XDEF AllocFastMemFunc,AllocFastClearMemFunc + XDEF FreeMemFunc,CopyMemQuickFunc,CopyMemFunc,ClearMemFunc + XDEF AvailMemFunc,AvailFastMemFunc,CheckMemFunc + +*************************************************************************** + + *** ChipMemHeader init, A0=Adresse, D0=Size des freien Blocks + +InitChipMemFunc: + movem.l d0/a0-a1,-(SP) + lea meb_ChipMRHeader(a6),a1 + bra.s DoInitMem + + *** FastMemHeader init, A0=Adresse, D0=Size des freien Blocks + +InitFastMemFunc: + movem.l d0/a0-a1,-(SP) + lea meb_FastMRHeader(a6),a1 + ;; bra.s DoInitMem + +DoInitMem: move.l a0,mh_Lower(a1) + move.l a0,mh_First(a1) + move.l d0,mh_Free(a1) + move.l d0,mc_Bytes(a0) + clr.l mc_Next(a0) + adda.l d0,a0 + move.l a0,mh_Upper(a1) + + movem.l (SP)+,d0/a0-a1 + rts + +*************************************************************************** + + *** D0: Amount, gibt D0: Adresse oder ruft AllocChipMem() auf + +AllocFastMemFunc: + movem.l d1-d2/a0-a3,-(SP) + move.l d0,d1 ; Amount retten + + tst.l meb_FastMRHeader+mh_Free(a6) ; Fast RAM vorhanden ? + beq.s ChipEntry ; nein ---> + + lea meb_FastMRHeader(a6),a0 ; The MemoryRegionHeader + bsr DoAlloc ; Speicher holen + bne.s 1$ ; OK ---> + move.l d1,d0 ; Amount + bra.s ChipEntry ; ---> CHIP RAM holen +1$: + movem.l (SP)+,d1-d2/a0-a3 + rts + +*************************************************************************** + + *** D0: Amount, gibt D0: Adresse oder Guru + *** Wenn nicht genuegen Speicher vorhanden ist, wird ein evt. + *** vorhandener Handler angesprungen + +AllocMemFunc: movem.l d1-d2/a0-a3,-(SP) + move.l d0,d1 ; Amount retten +ChipEntry: move.l d0,ActAmount + lea meb_ChipMRHeader(a6),a0 ; The MemoryRegionHeader + bsr DoAlloc ; ---> + movem.l (SP)+,d1-d2/a0-a3 + ;; tst.l d0 + beq.s .NotEnough ; nicht genug ---> + rts + +.NotEnough: movem.l d1-d7/a0-a6,-(SP) + move.l ActAmount,d1 + bsr MyNoMemHandler + tst.w d0 + beq .MemAlert + movem.l (SP)+,d1-d7/a0-a6 + move.l ActAmount,d0 + bra AllocMemFunc + + +.MemAlert: movem.l (SP)+,d1-d7/a0-a6 + move.l d1,d0 ; Amount für MSG + lea meb_ChipMRHeader(a6),a0 ; MemoryRegionHeader für MSG + move.l meb_ChipMRHeader+mh_Free(a6),d7 ; Free für MSG + movea.l (SP)+,a5 ; PC für MSG + lea AvailMemFunc,a1 + MSG <'AllocMem: No mem, D0=amount, D7=free, A0=MRH, A1=AvailFunc A5=PC'> + jmp meb_ColdReboot(a6) + +*************************************************************************** + + *** D0: Amount, A0: MRH gibt D0: Adresse oder 0, rettet keine Regs! + +DoAlloc: tst.l d0 ; 0 Bytes reservieren ? + beq .AllocError ; ja ---> Guru + addq.l #4,d0 ; Remember-Size + addq.l #7,d0 + andi.b #$f8,d0 ; Bytezahl modulo 8 aufrunden + jsr meb_Disable(a6) + ;; cmp.l mh_Free(a0),d0 ; Amount > freier Speicher ? + ;; bhi .NotEnoughMemory ; ja ---> Guru + lea mh_First(a0),a2 ; Zeiger auf 1. freien Chunk + +.AllocLoop: move.l (a2),d2 ; Link zum nächsten Chunk + beq.s .NotEnoughMemory ; Liste zu Ende ---> Guru + movea.l d2,a1 ; Nächster Blockanfang + cmp.l mc_Bytes(a1),d0 ; Chunklänge > Amount ? + bls.s 1$ ; ja ---> Chunk gefunden! + movea.l a1,a2 ; Nächster Blockanfang + bra.s .AllocLoop ; ---> Loop +1$: + beq.s 2$ ; Chunklänge == Amount ---> + lea 0(a1,d0.l),a3 ; Anfang des Restchunks + move.l (a1),(a3) ; Link eintragen + move.l mc_Bytes(a1),d2 ; Länge des freien Blocks + sub.l d0,d2 ; minus amount + move.l d2,mc_Bytes(a3) ; gibt Länge des Restchunks + move.l a3,(a2) ; Vorherigen Link korrigieren + bra.s 3$ ; ---> + +2$: move.l (a1),(a2) ; Link zurückkopieren +3$: + sub.l d0,mh_Free(a0) ; Frei-Zähler anpassen + move.l d0,(a1)+ ; Grösse für FreeMem eintragen + move.l a1,d0 ; Allozierter Bereich +.AllocEnd: + jsr meb_Enable(a6) ; versabbert CCR! + tst.l d0 + rts + +.NotEnoughMemory: + moveq.l #0,d0 + bra.s .AllocEnd + +.AllocError: movem.l (SP)+,d1-d2/a0-a3 + movea.l (SP)+,a5 + MSG <'AllocMem: Got request for 0 bytes, A0=MRH, A5=PC'> + jmp meb_ColdReboot(a6) + +************************************************************************** + + *** FAST-Speicher reservieren und löschen + +AllocFastClearMemFunc: + movem.l d1/a0,-(SP) + move.l d0,d1 ; Amount retten + bsr AllocFastMemFunc + bra.s DoAllocClear ; ---> + +************************************************************************** + + *** CHIP-Speicher reservieren und löschen + +AllocClearMemFunc: + movem.l d1/a0,-(SP) + move.l d0,d1 ; Amount retten + bsr AllocMemFunc +DoAllocClear: movea.l d0,a0 ; Adresse + move.l d1,d0 ; Länge + bsr ClearMemFunc + move.l a0,d0 ; Adresse + movem.l (SP)+,d1/a0 + rts + +*************************************************************************** + + *** Speicherbereich (A1) freigeben + +FreeMemFunc: movem.l d0-d2/a0-a2,-(SP) + jsr meb_Disable(a6) + move.l a1,d0 ; Null ? + beq .FreeEnd ; ja ---> + + cmp.l meb_ChipMRHeader+mh_Upper(a6),d0 ; Ist's CHIP-RAM ? + bhs.s 1$ ; nein ---> + lea meb_ChipMRHeader(a6),a0 ; The MemoryRegionHeader + bra.s 2$ +1$: + lea meb_FastMRHeader(a6),a0 +2$: + move.l -(a1),d0 ; Länge des Blocks + beq .FreeError ; ja ---> Guru + move.l a1,d1 ; Freizugebender Block + + lea mh_First(a0),a2 ; Zeiger auf 1. freien Chunk + move.l (a2),d2 ; Link zum nächsten Chunk + beq.s 5$ ; Ende der Liste ---> + +3$: cmpa.l d2,a1 ; Start des freizugebenden Chunks + bcs.s 4$ ; < Anfang des Blocks ---> + beq .FreeError ; == Anfang ---> Guru + movea.l d2,a2 ; Link zum nächsten Chunk + move.l (a2),d2 ; Neuer Link + bne.s 3$ ; Liste geht weiter ---> Loop +4$: + moveq #mh_First,d1 ; war 16 (?) + add.l a0,d1 ; + MemoryRegionHeader + cmp.l a2,d1 ; zeigt A2 auf mh_First ? + beq.s 5$ ; ja ---> Spezialfall + + move.l mc_Bytes(a2),d2 ; Länge des freien Chunks + add.l a2,d2 ; + Anfang = Chunk-Ende + cmp.l a1,d2 ; Anfang des freizugebenden Chunks + beq.s 6$ ; == Ende des freien Chunks ---> + bhi.s .FreeError ; im freien Bereich ---> Guru + +5$: move.l (a2),(a1) ; Neuen Blockheader erzeugen + move.l a1,(a2) + move.l d0,mc_Bytes(a1) + bra.s 7$ ; ---> +6$: + add.l d0,mc_Bytes(a2) ; Blocklänge += Freibytes + move.l a2,a1 ; Blockanfang +7$: + tst.l (a1) ; Link eingetragen ? + beq.s 8$ ; nein ---> + move.l mc_Bytes(a1),d2 ; Blocklänge + add.l a1,d2 ; + Anfang = Ende+1 + cmp.l (a1),d2 ; mit Linkadresse vergleichen + bhi.s .FreeError ; Linkadr. kleiner ---> Guru + bne.s 8$ ; Linkadresse grösser ---> + move.l (a1),a2 ; Nächsten Chunk einlinken + move.l (a2),(a1) + move.l mc_Bytes(a2),d2 + add.l d2,mc_Bytes(a1) +8$: + add.l d0,mh_Free(a0) ; Frei-Zähler anpassen + +.FreeEnd: jsr meb_Enable(a6) + movem.l (SP)+,d0-d2/a0-a2 + rts + +.FreeError: movem.l (SP)+,d0-d2/a0-a2 + movea.l (SP)+,a5 + MSG <'FreeMem: MemList corrupt, A0=MRH, A5=PC'> + jmp meb_ColdReboot(a6) + +*************************************************************************** + +CheckMemFunc: movem.l d0-d1/a0-a1,-(SP) + jsr meb_Disable(a6) + + lea meb_ChipMRHeader(a6),a0 ; The MemoryRegionHeader + bsr.s CheckMemList + + tst.l meb_FastMRHeader+mh_First(a6) ; FAST RAM vorhanden ? + beq.s 1$ + lea meb_FastMRHeader(a6),a0 + bsr.s CheckMemList +1$: + jsr meb_Enable(a6) + movem.l (SP)+,d0-d1/a0-a1 + rts + + *** Speicherliste (A0) testen, Message falls korrupt + +CheckMemList: moveq.l #0,d1 ; Free-Count löschen + lea mh_First(a0),a1 ; Zeiger auf 1. freien Chunk + +.CheckLoop: move.l mc_Next(a1),d0 ; Link zum nächsten Chunk + beq.s 1$ ; Ende der Liste ---> + cmp.l a1,d0 ; Next < actual ? + bls.s .CheckError ; ja ---> Error + movea.l d0,a1 + add.l mc_Bytes(a1),d1 ; FreeCount += bytes + bra.s .CheckLoop +1$: + cmp.l mh_Free(a0),d1 ; FreeCount richtig ? + bne.s .CheckError + rts + +.CheckError: move.l mh_Free(a0),d0 ; Soll-Wert + MSG <'CheckMem: List corrupt, D0=soll, D1=ist, A0=MRH, A1=Chunk'> + jmp meb_ColdReboot(a6) + +************************************************************************** + + *** Speicher schnell kopieren, WORD-aligned, Länge % 4 = 0 + +CopyMemQuickFunc: + movem.l d0-d1/a0-a1,-(SP) + moveq #0,d1 ; Kein Byte-Rest + bra.s l272 ; ---> + + *** Speicher normal kopieren + +CopyMemFunc: movem.l d0-d1/a0-a1,-(SP) + moveq #12,d1 + cmp.l d1,d0 ; Länge < 12 ? + bcs.s l277 ; ja ---> byteweise kopieren + move.l a0,d1 ; Source + btst #0,d1 ; Gerade ? + beq.s l271 ; ja ---> + move.b (a0)+,(a1)+ ; Sonst 1 Byte kopieren + subq.l #1,d0 +l271: move.l a1,d1 ; Destination + btst #0,d1 ; Gerade ? + bne.s l277 ; nein ---> byteweise kopieren + move.l d0,d1 ; Länge + andi.w #3,d1 ; Byte-Rest von LONGs + +l272: move.w d1,-(SP) ; Rest retten für später + moveq #96,d1 ; 2* Länge von 12 Registern + cmp.l d1,d0 + bcs.s l274 ; movem lohnt sich nicht ---> + + movem.l d1-d7/a2-a6,-(SP) ; Alles retten +l273: movem.l (a0)+,d1-d7/a2-a6 + movem.l d1-d7/a2-a6,(a1) + moveq #48,d1 ; 12 LONG-Register + adda.l d1,a1 ; INC dest + sub.l d1,d0 ; DEC len + cmp.l d1,d0 ; nochmal ? + bcc.s l273 ; ja ---> + movem.l (SP)+,d1-d7/a2-a6 + +l274: lsr.l #2,d0 ; restliche Longwords + beq.s l276 ; keine ---> + subq.l #1,d0 ; für dbf + move.l d0,d1 + swap d0 +l275: move.l (a0)+,(a1)+ + dbf d1,l275 + dbf d0,l275 + +l276: move.w (SP)+,d1 ; Geretteter Byte-Rest + beq.s l27a ; 0 ---> + moveq #0,d0 + bra.s l279 ; byteweise kopieren + +l277: move.w d0,d1 + swap d0 + bra.s l279 +l278: move.b (a0)+,(a1)+ +l279: dbf d1,l278 + dbf d0,l278 +l27a: + movem.l (SP)+,d0-d1/a0-a1 + rts + +************************************************************************** + + *** Speicher löschen, A0 : Adresse, D0 : Länge in Bytes ( <=1MB! ) + +ClearMemFunc: movem.l d0-d2/a0,-(SP) + moveq.l #0,d2 ; Lösch-Register + move.l a0,d1 + btst #0,d1 ; Adresse gerade ? + beq.s 1$ ; ja ---> + subq.l #1,d0 ; DEC len + bmi.s 99$ ; Länge war 0 ---> + move.b d2,(a0)+ ; 1 Byte löschen +1$: + move.l d0,d1 ; Länge + lsr.l #4,d1 ; /16 weil 4 LONGs aufs mal + bra.s 3$ ; Für dbf +2$: move.l d2,(a0)+ + move.l d2,(a0)+ + move.l d2,(a0)+ + move.l d2,(a0)+ +3$: dbf d1,2$ + + andi.w #15,d0 ; restliche Bytes + bra.s 5$ ; Für dbf +4$: move.b d2,(a0)+ +5$: dbf d0,4$ +99$: + movem.l (SP)+,d0-d2/a0 + rts + +*************************************************************************** + + *** Anzahl freie Bytes CHIP-RAM nach D0 + +AvailMemFunc: move.l meb_ChipMRHeader+mh_Free(a6),d0 + rts + +*************************************************************************** + + *** Anzahl freie Bytes FAST-RAM nach D0 + +AvailFastMemFunc: + move.l meb_FastMRHeader+mh_Free(a6),d0 + rts + + +ActAmount: ds.l 1 + + END diff --git a/MyExec.i b/MyExec.i new file mode 100644 index 0000000..1802037 --- /dev/null +++ b/MyExec.i @@ -0,0 +1,431 @@ +************************************************************************** +** ** +** MYEXEC - Verschiedene Routinen die so manches Programm braucht ** +** ** +** by Christian A. Weber, Zurich/Switzwerland ** +** ** +************************************************************************** +** ** +** Version 4.4, 16-Apr-92 ** +** ** +************************************************************************** + + OPT O+,OW-,O5- + + INCLUDE "exec/types.i" + +STRUCTURES_I SET 1 ; Damit's kein Chaos gibt ;-) + +PP_SAVEMARGIN: EQU 32 ; Anzahl PowerPacker-Sicherheitsbytes + + +************************************************************************** +* Beispiel: SYSCALL AllocMem + +SYSCALL: MACRO + XREF _MyExecBase + MOVE.L A6,-(SP) + MOVEA.L _MyExecBase,A6 + JSR meb_\1(A6) + MOVEA.L (SP)+,A6 + ENDM + +************************************************************************** +* Beispiel: SYSJSR AllocMem (A6 muss auf _MyExecBase zeigen!) + +SYSJSR: MACRO + JSR meb_\1(A6) + ENDM + +************************************************************************** +* Beispiel: SYSGET.b CheatFlag,D0 + +SYSGET: MACRO + XREF _MyExecBase + MOVE.L A6,-(SP) + MOVEA.L _MyExecBase,A6 + MOVE.\0 meb_\1(A6),\2 + MOVEA.L (SP)+,A6 + ENDM + +************************************************************************** +* Beispiel: SYSPUT.l D0,UserData1 + +SYSPUT: MACRO + XREF _MyExecBase + MOVE.L A6,-(SP) + MOVEA.L _MyExecBase,A6 + MOVE.\0 \1,meb_\2(A6) + MOVEA.L (SP)+,A6 + ENDM + +************************************************************************** +* Beispiel: SYSLEA UserData1,A0 + +SYSLEA: MACRO + XREF _MyExecBase + MOVE.L A6,-(SP) + MOVEA.L _MyExecBase,A6 + LEA.L meb_\1(A6),\2 + MOVEA.L (SP)+,A6 + ENDM + +************************************************************************** +* Beispiel: SYSTST.l TripleScreen + +SYSTST: MACRO + XREF _MyExecBase + MOVE.L A6,-(SP) + MOVEA.L _MyExecBase,A6 + TST.\0 meb_\1(A6) + MOVEA.L (SP)+,A6 + ENDM + +************************************************************************** + +DISABLE MACRO + FAIL Use SYSCALL Disable + ENDM + +ENABLE MACRO + FAIL Use SYSCALL Enable + ENDM + + +clra MACRO + suba.l \1,\1 + ENDM + +************************************************************************** + +FUNCTION MACRO + IFNE SOFFSET&1 + FAIL FUNCTION at odd address + ENDC +meb_\1 EQU SOFFSET +SOFFSET SET SOFFSET+4 + ENDM + +************************************************************************** +* MSG "Text" ruft ROMCrack mit "Text" auf + +MSG MACRO + XREF _MyExecBase + bra.s .msg1\@ +.msg2\@: dc.b \1,0 + EVEN +.msg1\@: move.l a6,-(SP) + movea.l _MyExecBase,a6 + move.l #.msg2\@,meb_ROMCrackDebugText ; NICHT (a6)! + jsr meb_Debug(a6) + move.l (SP)+,a6 + ENDM + +************************************************************************** +* SMSG "Text" gibt "Text" auf serial port aus + +SMSG MACRO + XREF _MyExecBase + bra.s .smsg1\@ +.smsg2\@: dc.b \1,0 + EVEN +.smsg1\@: move.l a6,-(SP) + movea.l _MyExecBase,a6 + pea .smsg2\@(PC) + jsr meb_RawPrintf(a6) + addq.w #4,SP + move.l (SP)+,a6 + ENDM + +************************************************************************** +* BTSTW: Testet ein Bit in einem WORD + +BTSTW MACRO + + IFNE NARG-2 + FAIL BTSW: Format= BTSTW bitno,<ea> + ENDC + + IFGT \1-8 + btst.b #\1,\2 + ENDC + + IFLE \1-8 + btst.b #\1,1+\2 + ENDC + + ENDM + +************************************************************************** + + STRUCTURE Node,0 + + APTR ln_Succ + APTR ln_Pred + UBYTE ln_Type + BYTE ln_Pri + APTR ln_Name + LABEL ln_SIZEOF + +************************************************************************** + + STRUCTURE MinNode,0 + + APTR mln_Succ + APTR mln_Pred + LABEL mln_SIZEOF + +************************************************************************** + + STRUCTURE List,0 + + APTR lh_Head + APTR lh_Tail + APTR lh_TailPred + UBYTE lh_Type + UBYTE lh_pad + LABEL lh_SIZEOF + +************************************************************************** + + STRUCTURE BitMap,0 + + WORD bm_BytesPerRow + WORD bm_Rows + BYTE bm_Flags + BYTE bm_Depth + WORD bm_Pad + STRUCT bm_Planes,8*4 + LABEL bm_SIZEOF + +************************************************************************** + + STRUCTURE DiskPacket,mln_SIZEOF ; Struktur für SendPacket() + + LONG dp_FileName ; Filename von DiskMaker + APTR dp_Address ; Ladeadresse wenn nicht DPF_ALLOCMEM + LONG dp_FileSize ; Wird ausgefüllt von der Diskroutine + APTR dp_Reply ; Routine oder Flag-Adresse oder nix + LONG dp_UserData ; Frei benutzbar für den User + BYTE dp_Flags ; see DP-definitions below + BYTE dp_pad1 ; Strukturlänge auf WORD aufrunden + WORD dp_pad2 ; Strukturlänge auf LONG aufrunden :-) + LABEL dp_SIZEOF + + BITDEF DP,REPLYHANDLER,0 ; Reply ist Routine (jsr) + BITDEF DP,REPLYBYTE,1 ; Reply ist Byte-Flag, wird $ff + BITDEF DP,ALLOCMEM,4 ; CHIP wird automatisch reserviert + BITDEF DP,ALLOCFASTMEM,5 ; FAST wird automatisch reserviert + BITDEF DP,CRUNCHED,6 ; INTERNAL USE ONLY !!! + BITDEF DP,WRITE,7 ; Auf Disk schreiben statt lesen + +************************************************************************** + + STRUCTURE MemoryRegionHeader,0 ; EXEC-PRIVATE STRUKTUR ! + + APTR mh_Lower ; Zeiger auf Anfang der Region + APTR mh_Upper ; Zeiger auf Ende der Region + APTR mh_First ; Zeiger auf 1. freien Chunk + LONG mh_Free ; Anzahl freie Bytes der Region + LABEL mh_SIZEOF + +************************************************************************** + + STRUCTURE MemoryChunk,0 ; EXEC-PRIVATE STRUKTUR ! + + APTR mc_Next ; Zeiger auf nächsten freien Chunk + LONG mc_Bytes ; Anzahl Bytes dieses Chunks + LABEL mc_SIZEOF + +************************************************************************** + + *** AttentionFlag - Bits + + BITDEF AF,68010,0 ; also set for 68020+ + BITDEF AF,68020,1 ; also set for 68030+ + BITDEF AF,68030,2 ; also set for 68040+ + BITDEF AF,68040,3 + BITDEF AF,68881,4 ; also set for 68882 + BITDEF AF,68882,5 + + *** Flag - Bits, only for internal use :-) + + BITDEF EXEC,BUFENABLE,0 + BITDEF EXEC,RESETREQUEST,4 + +************************************************************************** + + STRUCTURE MyExecBaseStruct,$100 + + LONG meb_ROMCRACKMagic ; 'NCLR' oder 'DBUG' oder 0 + LONG meb_ROMCrackConfigMagic ; 'ICH!' + APTR meb_ROMCrackBSS + APTR meb_ROMCrackChipMem + APTR meb_ROMCrackDebugText ; ROMCrack's Debug-Text + + *** Private Einträge, SUBJECT TO CHANGE, NICHT BENUTZEN! + + STRUCT meb_ChipMRHeader,mh_SIZEOF + STRUCT meb_FastMRHeader,mh_SIZEOF + APTR meb_RAMDiskBase + LONG meb_RAMDiskSize + LONG meb_MainPrgName + LONG meb_LastRnd1 ; Beide müssen nacheinander stehen + LONG meb_LastRnd2 + STRUCT meb_DiskList,lh_SIZEOF ; Die Packet-Liste + STRUCT meb_FileList,lh_SIZEOF ; Die File-Cache-Liste + WORD meb_ProductCode + BYTE meb_IDNestCnt + BYTE meb_ExecFlags ; siehe EXECF_... + + *** Erlaubte Einträge + + APTR meb_SuperStackUpper ; SuperStack am Anfang (READ ONLY!) + WORD meb_AttnFlags ; Kopie von ExecBase->AttnFlags + WORD meb_SystemBplcon0 ; Kopie von gfxbase->system_bplcon0 + BYTE meb_VBlankFrequency ; Kopie von ExecBase->VBlankFrequency + BYTE meb_expad2 + + BYTE meb_ActualKey ; RawKeyCode + BYTE meb_ActualQualifiers ; Qualifier-Bits, (BitNr=KeyCode-$60) + BYTE meb_ActualASCIIKey ; ASCII-Code + BYTE meb_CheatFlag ; >0 falls Cheat mode on + + STRUCT meb_BobList,lh_SIZEOF ; für die Bobroutine + APTR meb_TripleScreen ; für die Bobroutine + WORD meb_SignalSet ; für die Bobroutine + + LONG meb_UserData1 ; Frei für den User, am Anfang 0 + LONG meb_UserData2 ; Frei für den User, am Anfang 0 + + STRUCT meb_exreserved,6 ; + pad auf LONG, NICHT benutzen! + + *** Level 3 Interrupt-Vektoren, zum Patchen oder 0 reinschreiben + + UWORD meb_VBLIntPad + UWORD meb_VBLIntJump + APTR meb_VBLIntVector + + UWORD meb_CopperIntPad + UWORD meb_CopperIntJump + APTR meb_CopperIntVector + + *** Cia-Interrupt-Vektoren, zum Patchen oder 0 reinschreiben + + APTR meb_CiaATimerAVector + APTR meb_CiaATimerBVector + APTR meb_CiaAAlarmVector + APTR meb_CiaASerialVector + APTR meb_CiaAFlagVector + + APTR meb_CiaBTimerAVector + APTR meb_CiaBTimerBVector + APTR meb_CiaBAlarmVector + APTR meb_CiaBSerialVector + APTR meb_CiaBFlagVector + + + *** System-Funktionen (use at your own risk!) + + ULONG meb_SecretMagic ; PRIVAT + FUNCTION InitExec ; (ExecEvent) (CRP) + FUNCTION ColdReboot ; () () + FUNCTION InitChipMem ; (Address,Size) (A0/D0) + FUNCTION InitFastMem ; (Address,Size) (A0/D0) + FUNCTION InitDisk ; (Product) (D0) + FUNCTION InitKey ; () () + FUNCTION SetCache ; (NewCacheBits) (D0) + + *** Debug-Funktionen + + FUNCTION Debug ; () () + + *** Speicherverwaltung + + FUNCTION AllocMem ; (Amount) (D0) + FUNCTION AllocClearMem ; (Amount) (D0) + FUNCTION AllocFastMem ; (Amount) (D0) + FUNCTION AllocFastClearMem ;(Amount) (D0) + FUNCTION FreeMem ; (Address) (A1) + FUNCTION AvailMem ; () () + FUNCTION AvailFastMem ; () () + FUNCTION CheckMem ; () () + FUNCTION CopyMem ; (Src,Dest,Len) (A0/A1/D0) + FUNCTION CopyMemQuick ; (Src,Dest,Len) (A0/A1/D0) + FUNCTION ClearMem ; (Address,Len) (A0/D0) + + *** Semaphoren + + FUNCTION Disable ; () () + FUNCTION Enable ; () () + FUNCTION OwnBlitter ; () () + FUNCTION DisownBlitter ; () () + + *** Listenverwaltung + + FUNCTION NewList ; (List) (A0) + FUNCTION Enqueue ; (List,Node) (A0/A1) + FUNCTION Remove ; (Node) (A1) + FUNCTION AddHead ; (List,Node) (A0/A1) + FUNCTION AddTail ; (List,Node) (A0/A1) + FUNCTION RemHead ; (List) (A0) + + *** Tastatur + + FUNCTION GetKey ; () () + FUNCTION WaitKey ; () () + FUNCTION FlushKeyBuf ; () () + FUNCTION SetMap ; (KeyMap oder 0) (A0) + FUNCTION SetResetHandler ; (Handler) (A0) + FUNCTION SetCheatText ; (RawKeyCodes) (A0) + + *** Ausgabe + + FUNCTION RawDoFmt ; (wie normal :-)) (...) + FUNCTION RawPrintf ; (Stack) (...) + FUNCTION PlayCDTrack ; (TrackNumber) (D0) + FUNCTION WaitCDTrack ; (nüt) () + + *** Zufall + + FUNCTION Randomize ; (Value1,Value2) (D0/D1) + FUNCTION Random ; (Limit) (D0) + + *** Disk-Routinen + + FUNCTION SetNoDiskHandler ;(Routine) (A0) + FUNCTION ReadFile ; (Name,Address) (D0/A0) + FUNCTION WriteFile ; (Name,Address) (D0/A0) + FUNCTION LoadFile ; (Name) (D0) + FUNCTION LoadFastFile ; (Name) (D0) + FUNCTION LoadSeg ; (Name) (D0) + FUNCTION UnLoadSeg ; (Segment) (A1) + FUNCTION BufReadFile ; (Name,Address (D0/A0) + FUNCTION BufLoadFile ; (Name) (D0) + FUNCTION DeleteFileNode ; (Name) (D0) + FUNCTION DeleteFileList ; () () + FUNCTION SendPacket ; (Packet) (A0) + + *** Bob-Routinen + + FUNCTION WaitBlit ; (Custom) (A5) + FUNCTION InitDrawBob ; (BitMap) (A0) + FUNCTION AddBob ; (NewBob) (A1) + FUNCTION RemBob ; (Bob) (A0) + FUNCTION RemAllBobs ; () () + FUNCTION RestoreBobList ; (BitMap) (A1) + FUNCTION DrawBobList ; (BitMap) (A1) + FUNCTION RestoreOneBob ; (Bob,BitMap) (A0/A1) + FUNCTION DrawOneBob ; (Bob,BitMap) (A0/A1) + FUNCTION AnimateOneBob ; (Bob) (A0) + FUNCTION MoveOneBob ; (Bob) (A0) + FUNCTION TestPoint ; (X,Y) (D0/D1) + FUNCTION SetMovePrg ; (Bob,MPrg,Speed,Step) (A0/A1/D0/D1) + FUNCTION SetAnimPrg ; (Bob,APrg,Speed) (A0/A1/D0) + FUNCTION SetGlobalClip ; (X,Y) (D0/D1) + FUNCTION HandleCollision ; () () + FUNCTION CollOneBob ; (Bob) (A0) + FUNCTION FlashBob ; (Bob,Time,Color) (A0/D0/D1) + FUNCTION GetBobData ; (Bob) (A0)->A2 + + LABEL __EXECBASESIZE diff --git a/PPDecrunch.S b/PPDecrunch.S new file mode 100644 index 0000000..f606593 --- /dev/null +++ b/PPDecrunch.S @@ -0,0 +1,151 @@ +***************************************************************************** +** ** +** PPDecrunch - Eine Datei PowerPacker-decrunchen auf sich selber ** +** ** +** Parameter : A0.L : Adresse ** +** D0.L : Länge der gecrunchten Daten ** +** ** +** Resultat : nix ** +** ** +***************************************************************************** + + IDNT PPDecrunch + SECTION text,CODE + + INCLUDE "MyExec.i" + + XDEF PPDecrunch + +PPDecrunch: movem.l d0-d7/a0-a5,-(SP) + lea Efficiency(PC),a5 ; A5: Pointer to efficiency + move.l a0,-(SP) ; Buffer für später + lea PP_SAVEMARGIN(a0),a3 ; A3: Destination + move.l a3,-(SP) ; Quelle für später + move.l (a0)+,-(SP) ; Decrunchte Grösse für später + + move.l (a0)+,(a5) ; Efficiency eintragen + lea -8(a0,d0.l),a0 ; A0: Source-Ende + + move.l a6,-(SP) + bsr.b Decrunch + movea.l (SP)+,a6 + + move.l (SP)+,d0 ; Decrunchte Grösse + movea.l (SP)+,a0 ; Quelle + movea.l (SP)+,a1 ; Ziel + jsr meb_CopyMem(a6) ; runterschieben + + movem.l (SP)+,d0-d7/a0-a5 + rts + +Efficiency: dc.l 0 + + +**************************************************************************** +* * +* PowerPacker Decrunch assembler subroutine V2.0 (reentrant !) * +* DESTROYS ALL REGISTERS! * +* * +* call as: * +* pp_DecrunchBuffer (endcrun, buffer, &efficiency, coloraddr); * +* with: * +* A0 endcrun : UBYTE * just after last byte of crunched file * +* A3 buffer : UBYTE * to memory block to decrunch in * +* A5 &efficiency: ptr to Longword defining efficiency of crunched file * +* * +* NOTE: * +* Decrunch a few bytes higher (safety margin) than the crunched file * +* to decrunch in the same memory space. (8 bytes suffice) * +* * +**************************************************************************** + +Decrunch: moveq #3,d6 + moveq #7,d7 + moveq #1,d5 + move.l a3,a2 ; remember start of file + move.l -(a0),d1 ; get file length and empty bits + tst.b d1 + beq.b NoEmptyBits + bsr.b ReadBit ; this will always get the next long (D5 = 1) + subq.b #1,d1 + lsr.l d1,d5 ; get rid of empty bits +NoEmptyBits: + lsr.l #8,d1 + add.l d1,a3 ; a3 = endfile +LoopCheckCrunch: + bsr.b ReadBit ; check if crunch or normal + bcs.b CrunchedBytes +NormalBytes: + moveq #0,d2 +Read2BitsRow: + moveq #1,d0 + bsr.b ReadD1 + add.w d1,d2 + cmp.w d6,d1 + beq.b Read2BitsRow +ReadNormalByte: + moveq #7,d0 + bsr.b ReadD1 + move.b d1,-(a3) + dbf d2,ReadNormalByte + cmp.l a3,a2 + bcs.b CrunchedBytes + rts +ReadBit: + lsr.l #1,d5 ; this will set X if d5 becomes zero + beq.b GetNextLong + rts +GetNextLong: + move.l -(a0),d5 + roxr.l #1,d5 ; X-bit set by lsr above + rts +ReadD1sub: + subq.w #1,d0 +ReadD1: + moveq #0,d1 +ReadBits: + lsr.l #1,d5 ; this will set X if d5 becomes zero + beq.b GetNext +RotX: + roxl.l #1,d1 + dbf d0,ReadBits + rts +GetNext: + move.l -(a0),d5 + roxr.l #1,d5 ; X-bit set by lsr above + bra.b RotX +CrunchedBytes: + moveq #1,d0 + bsr.b ReadD1 ; read code + moveq #0,d0 + move.b 0(a5,d1.w),d0 ; get number of bits of offset + move.w d1,d2 ; d2 = code = length-2 + cmp.w d6,d2 ; if d2 = 3 check offset bit and read length + bne.b ReadOffset + bsr.b ReadBit ; read offset bit (long/short) + bcs.b LongBlockOffset + moveq #7,d0 +LongBlockOffset: + bsr.b ReadD1sub + move.w d1,d3 ; d3 = offset +Read3BitsRow: + moveq #2,d0 + bsr.b ReadD1 + add.w d1,d2 ; d2 = length-1 + cmp.w d7,d1 ; cmp with #7 + beq.b Read3BitsRow + bra.b DecrunchBlock +ReadOffset: + bsr.b ReadD1sub ; read offset + move.w d1,d3 ; d3 = offset +DecrunchBlock: + addq.w #1,d2 +DecrunchBlockLoop: + move.b 0(a3,d3.w),-(a3) + dbf d2,DecrunchBlockLoop +EndOfLoop: + cmp.l a3,a2 + bcs LoopCheckCrunch + rts + + END diff --git a/RawDoFmt.S b/RawDoFmt.S new file mode 100644 index 0000000..3b2487c --- /dev/null +++ b/RawDoFmt.S @@ -0,0 +1,351 @@ +*************************************************************************** +** ** +** RawDoFmt - Die geniale Ausgabe-Routine, beherrscht neuerdings ** +** auch Binär-Zahlen (%b, %lb, %04b etc.) ** +** ** +*************************************************************************** +** ** +** Modification History ** +** -------------------- ** +** ** +** 01-May-89 CHW Created this file from CHH's HdExec.S ** +** 01-May-89 CHW Binary String Conversion added, code cleaned up ** +** 25-Nov-89 CHW Linksize changed from 34 to 64 (Paranoia?) ** +** ** +*************************************************************************** + + OPT O+,OW-,O5-,OW6+ + + SECTION text,CODE + + XDEF RawDoFmtFunc,_RawPrintfFunc + +RB_LEFTALIGNED: EQU 0 ; Flag-Definitionen +RB_ZEROFILL: EQU 1 +RB_LONGARG: EQU 2 + +LINKSIZE: EQU 64 ; Jaja, binär wird lang... + + +*************************************************************************** + + *** A0=Formatstring A1=Args A2=Routine A3=Ptr für Routine + +RawDoFmtFunc: movem.l d0-d6/a0-a5,-(a7) + link a6,#-LINKSIZE ; Puffer für Umwandlungen + move.l a1,-(SP) ; Argumente + move.l a0,a4 ; Formatstring + +MainLoop: move.b (a4)+,d0 ; Nächstes Zeichen + beq.s Ende ; fertig ---> + cmpi.b #'%',d0 + beq.s DoFormat +DirectOut: jsr (a2) ; Zeichen direkt ausgeben + bra.s MainLoop ; ---> + +Ende: jsr (a2) ; Endzeichen ausgeben + unlk a6 + movem.l (SP)+,d0-d6/a0-a5 + rts + + *** Format-Anweisung bearbeiten + +DoFormat: lea -LINKSIZE(a6),a5 ; Start des Puffers + clr.w d3 ; Flags löschen + cmpi.b #'-',(a4) ; Erstes Zeichen == '-' ? + bne.s 1$ ; nein ---> + bset #RB_LEFTALIGNED,d3 ; Linksbündig-Flag setzen + addq.l #1,a4 ; Formatzeiger vorrücken +1$: + cmpi.b #'0',(a4) ; Nächstes Zeichen == '0' ? + bne.s 2$ ; nein ---> + bset #RB_ZEROFILL,d3 ; Flag für mit Nullen füllen +2$: + bsr DecimalConvert + move.w d0,d6 ; D6 := minimale Feldbreite + clr.l d5 + cmpi.b #'.',(a4) ; Nächstes Zeichen == '.' ? + bne.s 3$ ; nein ---> + addq.w #1,a4 ; Formatzeiger vorrücken + bsr DecimalConvert + move.w d0,d5 ; D5 := maximale Feldbreite +3$: + cmpi.b #'l',(a4) ; Nächstes Zeichen == 'l' ? + bne.s 4$ ; nein ---> + bset #RB_LONGARG,d3 ; Flag für LONG-Argument + addq.w #1,a4 ; Formatzeiger vorrücken +4$: + move.b (a4)+,d0 ; Nächstes Zeichen + cmpi.b #'d',d0 ; 'd': Dezimaldarstellung ? + bne.s 5$ ; nein ---> + bsr.s GetData ; Daten nach D4 + bsr D4ToDez ; und in String verwandeln + bra.s AusgAbschl +5$: + cmpi.b #'x',d0 ; 'x': Hex-Darstellung ? + bne.s 6$ ; nein ---> + bsr.s GetData ; Daten nach D4 + bsr D4ToHex ; und in String verwandeln + bra.s AusgAbschl +6$: + cmpi.b #'b',d0 ; 'b': Binär-Darstellung ? + bne.s 7$ ; nein ---> + bsr.s GetData ; Daten nach D4 + bsr D4ToBin ; und in String verwandeln + bra.s AusgAbschl +7$: + cmpi.b #'s',d0 ; 's': String ? + bne.s 8$ ; nein ---> + move.l (a7),a1 ; A1: Ausgabedaten + move.l (a1)+,a5 ; A5: Zeiger auf String + move.l a1,(a7) ; Neues A1 zurückschreiben + bra.s AusgAbschl2 +8$: + cmpi.b #'c',d0 ; 'c': Einzelnes Zeichen ? + bne DirectOut ; nein ---> + bsr.s GetData ; Zeichencode nach D4 + move.b d4,(a5)+ ; und in Puffer schreiben + + +AusgAbschl: clr.b (a5) ; Puffer mit 0 abschliessen + lea -LINKSIZE(a6),a5 ; A5: Pufferanfang + +AusgAbschl2: move.l a5,a0 + bsr.s StrLenD2 + tst.w d5 ; Maximale Feldlänge ? + beq.s 1$ ; nein ---> + cmp.w d5,d2 ; String länger als max. ? + bhi.s 2$ ; ja ---> +1$: + move.w d2,d5 ; Feldlänge := Stringlänge +2$: + sub.w d5,d6 ; D6 := Feldlänge-Stringlänge + bpl.s 3$ ; Feldlänge grösser ---> + clr.w d6 +3$: + btst #RB_LEFTALIGNED,d3 ; Linksbündige Ausgabe ? + bne.s 5$ ; ja ---> + bsr Filler ; Mit 0 oder Space füllen + + bra.s 5$ ; für dbf +4$: move.b (a5)+,d0 ; Nächstes Zeichen + jsr (a2) ; ausgeben +5$: dbf d5,4$ + + btst #RB_LEFTALIGNED,d3 ; Linksbündig ? + beq MainLoop ; nein ---> + bsr Filler ; sonst auffüllen + bra MainLoop ; ---> + +************************************************************************** + + *** Ausgabedaten nach D4 holen + +GetData: move.l 4(a7),a1 ; Argument-Array + btst #RB_LONGARG,d3 ; LONG-Argument ? + bne.s 1$ ; ja ---> + move.w (a1)+,d4 ; Datenwort holen + move.l a1,4(a7) ; Neues A1 zurückschreiben + ext.l d4 ; Wort auf LONG erweitern + rts +1$: + move.l (a1)+,d4 ; Datenlangwort holen + move.l a1,4(a7) ; Neues A1 zurückschreiben + rts + +*************************************************************************** + + *** Stringlänge von (a0) nach D2 + +StrLenD2: moveq #-1,d2 +1$: tst.b (a0)+ + dbeq d2,1$ + neg.l d2 + subq.w #1,d2 + rts + +*************************************************************************** + + *** Dezimal-String (A4) in Zahl D0 umwandeln + +DecimalConvert: clr.l d0 + clr.l d2 +1$: move.b (a4)+,d2 ; Nächstes Zeichen + cmpi.b #'0',d2 + bcs.s 2$ + cmpi.b #'9',d2 + bhi.s 2$ + move.l d0,d1 + lsl.l #2,d0 ; Zahl *= 4 + add.l d1,d0 ; gibt * 5 + add.l d0,d0 ; gibt * 10 + subi.b #'0',d2 + add.l d2,d0 ; Zahl += nächste Ziffer + bra.s 1$ ; ---> Loop +2$: subq.l #1,a4 + rts + +*************************************************************************** + + *** Zahl D4 in Dezimal-String (A5)+ umwandeln + +D4ToDez: tst.l d4 ; Zahl testen + beq.s D4To_End ; == 0 ---> + bmi.s 1$ ; < 0 ---> + neg.l d4 ; Zahl negieren + bra.s 2$ ; ---> +1$: move.b #'-',(a5)+ ; Minuszeichen +2$: + lea ZehnerPotenzen(PC),a0 + st d1 ; Anfangsnullenflag setzen +3$: + move.l (a0)+,d2 ; D2 := nächster Tabellenwert + beq.s D4To_End ; Tabelle fertig ---> + + moveq #-1,d0 ; Zähler := 0 +4$: add.l d2,d4 ; So oft D2 zur Zahl addieren + dbgt d0,4$ ; bis sie positiv ist + sub.l d2,d4 ; dann einmal subtrahieren + addq.w #1,d0 ; Wurde nur 1* addiert ? + bne.s 5$ ; nein ---> + tst.b d1 ; Ist es eine führende 0 ? + bne.s 3$ ; ja ---> nicht ausgeben +5$: + sf d1 ; Anfangsnullenflag löschen + neg.b d0 ; Zahl der Additionen -1 + addi.b #'0',d0 ; ergibt Zifferncode + move.b d0,(a5)+ ; Ziffer in Puffer + bra.s 3$ ; ---> Loop +D4To_End: + neg.b d4 ; D4 := Letzte Ziffer + addi.b #'0',d4 ; ergibt Zifferncode + move.b d4,(a5)+ ; Ziffer in Puffer + rts + +ZehnerPotenzen: dc.l 1000000000 + dc.l 100000000 + dc.l 10000000 + dc.l 1000000 + dc.l 100000 + dc.l 10000 + dc.l 1000 + dc.l 100 + dc.l 10 + dc.l 0 ; Endmarke + dc.l $43485721 + +*************************************************************************** + + *** Zahl D4 in Hex-String (A5)+ umwandeln + +D4ToHex: tst.l d4 ; Zahl testen + beq D4To_End ; == 0 ---> + st d1 ; Anfangsnullenflag setzen + btst #RB_LONGARG,d3 ; LONG-Argument ? + bne.s 1$ ; ja ---> + moveq #3,d2 ; sonst 4 Stellen + swap d4 ; Zahlwert in oberes Wort + bra.s 2$ +1$: moveq #7,d2 ; 8 Stellen +2$: + rol.l #4,d4 ; Bits 0-3 := nächste Stelle + move.b d4,d0 + andi.b #15,d0 + bne.s 3$ ; Nicht 0 ---> + tst.b d1 ; Anfangsnull ? + bne.s 6$ ; ja ---> nicht ausgeben +3$: + sf d1 ; Anfangsnullenflag löschen + cmpi.b #9,d0 ; Ziffer > 9 ? + bhi.s 4$ ; ja ---> + addi.b #'0',d0 + bra.s 5$ +4$: addi.b #'A'-10,d0 +5$: move.b d0,(a5)+ ; Ziffer in Puffer +6$: dbf d2,2$ ; Loop ---> + rts + +*************************************************************************** + + *** Zahl D4 in Binär-String (A5)+ umwandeln + +D4ToBin: tst.l d4 ; Zahl testen + beq D4To_End ; == 0 ---> + st d1 ; Anfangsnullenflag setzen + btst #RB_LONGARG,d3 ; LONG-Argument ? + bne.s 1$ ; ja ---> + moveq #15,d2 ; sonst 16 Stellen + swap d4 ; Zahlwert in oberes Wort + bra.s 2$ +1$: moveq #31,d2 ; 32 Stellen +2$: roxl.l #1,d4 ; Nächste Stelle in Carry + bcs.s 3$ ; 1 ---> + tst.b d1 ; Anfangsnull ? + bne.s 5$ ; ja ---> nicht ausgeben + moveq #'0',d0 + bra.s 4$ ; ---> +3$: sf d1 ; Anfangsnullenflag löschen + moveq #'1',d0 +4$: move.b d0,(a5)+ ; Ziffer in Puffer +5$: dbf d2,2$ ; Loop ---> + rts + +*************************************************************************** + + *** Nullen oder Leerstellen ausgeben + +Filler: move.b #' ',d2 ; Füllcode: Space + btst #RB_ZEROFILL,d3 ; Füllen mit Nullen ? + beq.s 2$ ; nein ---> + move.b #'0',d2 ; Sonst Füllcode '0' + bra.s 2$ ; Für dbf +1$: move.b d2,d0 ; Füllcode + jsr (a2) ; ausgeben +2$: dbf d6,1$ + rts + + +************************************************************************* +* +* _RawPrintf.asm - Self-contained printf clone. Formatted strings +* are sent directly out the serial port. Xon/Xoff +* handshake is supported. +* This function may be called at any time, including +* interrupts. +* +* Bryce Nesbitt, 02-24-89 +* +************************************************************************* + + XDEF _RawPrintfFunc + +_RawPrintfFunc: movem.l a0/a1,-(SP) + move.l 4*3(SP),A0 ;grab format string + lea.l 4*4(SP),A1 ;grab stack address of parameters + movem.l A2/A3/D0/D1,-(SP) + lea.l PSCODE(pc),a2 + suba.l a3,a3 + bsr RawDoFmtFunc + movem.l (SP)+,D0/D1/A2/A3 + movem.l (SP)+,a0/a1 + rts + + +PSCODE: tst.b d0 + beq.s ignore +1$ move.w $DFF018,d1 ;_serdatr + btst #13,d1 ;TBE bit + beq.s 1$ + and.b #$7f,d1 + cmp.b #$18,d1 ;Check for CAN (^X) + beq.s ignore + cmp.b #$13,d1 ;Check for Xoff + beq.s 1$ + and.w #$ff,d0 + or.w #$100,d0 + move.w d0,$DFF030 ;_serdat +ignore: rts + +***************************************************************************** + + END @@ -0,0 +1,55 @@ + + SECTION text,CODE + + INCLUDE "MyExec.i" + + XDEF RandomizeFunc,RandomFunc + + + *** Random initialisieren, D0/D1 : Zufallswerte + +RandomizeFunc: movem.l d0-d3,-(SP) + add.l d0,d1 ; user seed in d0 (d1 too) + move.l d0,meb_LastRnd1(a6) ; save for next time through + move.l d1,meb_LastRnd2(a6) + bsr.s LongRnd + movem.l (SP)+,d0-d3 + rts + + + *** Zufallszahl [0..D0.W] berechnen + +RandomFunc: movem.l d1-d4,-(SP) + move.w d0,d4 ; save upper limit + beq.s 1$ ; range of 0 returns 0 always + bsr.s LongRnd ; get a longword random number + clr.w d0 ; use upper word (it's most random) + swap d0 + divu.w d4,d0 ; divide by range... + clr.w d0 ; ...and use remainder for the value + swap d0 ; result in D0.W +1$: movem.l (SP)+,d1-d4 + rts + + +LongRnd: movem.l meb_LastRnd1(a6),d0/d1 ; D0=LSB's, D1=MSB's of random number + andi.b #$0e,d0 ; ensure upper 59 bits are an... + ori.b #$20,d0 ; ...odd binary number + move.l d0,d2 + move.l d1,d3 + add.l d2,d2 ; accounts for 1 of 17 left shifts + addx.l d3,d3 ; [D2/D3] = RND*2 + add.l d2,d0 + addx.l d3,d1 ; [D0/D1] = RND*3 + swap d3 ; shift [D2/D3] additional 16 times + swap d2 + move.w d2,d3 + clr.w d2 + add.l d2,d0 ; add to [D0/D1] + addx.l d3,d1 + movem.l d0/d1,meb_LastRnd1(a6) ; save for next time through + move.l d1,d0 ; most random part to D0 + rts + + + END diff --git a/SCOPTIONS b/SCOPTIONS new file mode 100644 index 0000000..504d97c --- /dev/null +++ b/SCOPTIONS @@ -0,0 +1,24 @@ +MATH=FFP +PARAMETERS=REGISTERS +NOSTACKCHECK +STRINGMERGE +UNSIGNEDCHARS +STRUCTUREEQUIVALENCE +OPTIMIZE +MAP +MAPHUNK +MAPSYMBOLS +MAPLIB +MAPXREFERENCE +MAPOVERLAY +NOVERSION +NOICONS +MEMORYSIZE=HUGE +INCLUDEDIR=SC:Include +INCLUDEDIR=INCUSR: +DEFINE __USE_SYSBASE +CODENAME=text +DATANAME=data +BSSNAME=bss +MAPFILE=RAM:slink.map +MAXIMUMWARNINGS=50 @@ -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; +} + diff --git a/SysCDisk.S b/SysCDisk.S new file mode 100644 index 0000000..2d56e30 --- /dev/null +++ b/SysCDisk.S @@ -0,0 +1,303 @@ + + IDNT SysCDisk + SECTION text,CODE + + INCLUDE "MyExec.i" + INCLUDE "exec/macros.i" + INCLUDE "dos/dos.i" + + XREF _DOSBase,@CheckFile + +;CRUNCH + + XREF _RawPrintfFunc + IFD CRUNCH + XREF PPDecrunch + ENDC + + XDEF InitDiskFunc ; Disk-System initialisieren + XDEF SetNoDiskHandlerFunc + XDEF ReadFileFunc ; 'Datei' lesen + XDEF WriteFileFunc ; 'Datei' schreiben + XDEF LoadFileFunc ; Speicher reservieren & File lesen + XDEF LoadFastFileFunc ; FAST alloc & File lesen + XDEF SendPacketFunc ; Asynchronen Lese-Request schicken + + +*************************************************************************** +** ** +** I N I T D I S K - Disk-System init, Recalibrate, Timer alloc ... ** +** ** +** Parameter : nix ** +** ** +*************************************************************************** + +InitDiskFunc: movem.l d0/a0,-(SP) + + clr.l InsertDiskRoutine + + *** DiskRequest-Liste initialisieren + + lea meb_DiskList(a6),a0 + jsr meb_NewList(a6) + + movem.l (SP)+,d0/a0 + rts + + +*************************************************************************** +** ** +** S E T N O D I S K H A N D L E R - NoDisk-Handler setzen ** +** ** +** Parameter : A0.L: InsertDisk-Handler oder 0 ** +** ** +*************************************************************************** + +SetNoDiskHandlerFunc: + move.l a0,InsertDiskRoutine + rts + + +************************************************************************** +** ** +** R E A D F I L E - 'Datei' von Disk lesen & MFM-dekodieren ** +** ** +** Parameter : D0.L : DiskAdresse (Disk/Track/Offset) der Datei ** +** A0.L : Ladeadresse ** +** ** +** Resultat : D0.L : Fehlernummer, 0 if successful ** +** Z-Bit: gesetzt if OK, gelöscht wenn Fehler ** +** ** +************************************************************************** + +ReadFileFunc: movem.l a0-a1,-(SP) + lea -dp_SIZEOF-2(SP),SP ; DiskPacket erstellen + move.l d0,dp_FileName(SP) + move.l a0,dp_Address(SP) + movea.l SP,a0 ; A0 : Packet + lea dp_SIZEOF(SP),a1 ; A1 : End-Flag + clr.b (a1) ; löschen + move.l a1,dp_Reply(a0) + move.b #DPF_REPLYBYTE,dp_Flags(a0) + bsr.s SendPacketFunc +1$: tst.b (a1) ; Warten bis File geladen! + beq.s 1$ + lea dp_SIZEOF+2(SP),SP ; DiskPacket freigeben + moveq #0,d0 ; Success ** DEBUG ** + movem.l (SP)+,a0-a1 + rts + + +************************************************************************** +** ** +** L O A D F I L E - Speicher reservieren, Datei von Disk lesen ** +** ** +** Parameter : D0.L : DiskAdresse (Disk/Track/Offset) der Datei ** +** ** +** Resultat : D0.L : Adresse des Files, 0 if error ** +** Z-Bit: gelöscht wenn OK, gesetzt wenn Error ** +** ** +************************************************************************** + +LoadFileFunc: movem.l d1/a0-a1,-(SP) + moveq #DPF_REPLYBYTE|DPF_ALLOCMEM,d1 ; Packet Flags + bra.s DoLoadFile ; ---> + +LoadFastFileFunc: + movem.l d1/a0-a1,-(SP) + moveq #DPF_REPLYBYTE|DPF_ALLOCFASTMEM,d1 ; Packet Flags + ;; bra.s DoLoadFile ; ---> + +DoLoadFile: lea -dp_SIZEOF-2(SP),SP ; DiskPacket erstellen + movea.l SP,a0 ; A0 : Packet + lea dp_SIZEOF(SP),a1 ; A1 : End-Flag + move.l d0,dp_FileName(a0) + clr.b (a1) ; End-Flag löschen + move.l a1,dp_Reply(a0) + move.b d1,dp_Flags(a0) ; ReplyType & MemoryType + bsr.s SendPacketFunc +1$: tst.b (a1) ; Warten bis File geladen! + beq.s 1$ + move.l dp_Address(SP),d0 ; Resultat: Adresse + lea dp_SIZEOF+2(SP),SP ; Doesn't change CCR + movem.l (SP)+,d1/a0-a1 + rts + + +************************************************************************** +** ** +** S E N D P A C K E T - Asynchronen Read-Request aufgeben ** +** ** +** Parameter : A0.L : Zeiger auf struct DiskPacket ** +** ** +** Resultat : nix ** +** ** +************************************************************************** + +SendPacketFunc: movem.l d7/a0-a1/a4-a5,-(SP) + movea.l a0,a1 ; Packet + lea meb_DiskList(a6),a0 + jsr meb_AddTail(a6) ; Packet anhängen + bsr.s ProcessNextRequest ; System ankicken + movem.l (SP)+,d7/a0-a1/a4-a5 + rts + + +************************************************************************** + + *** Nächsten Request aus Diskliste verarbeiten + +ProcessNextRequest: + movem.l d0-d7/a0-a5,-(SP) + + lea meb_DiskList(a6),a0 + jsr meb_RemHead(a6) ; setzt CCR + beq .EndProcReq ; Kein Request pending ---> + movea.l d0,a2 ; A2 : Aktuelles Packet + + *** "Loading 'filename' (flags)" auf Debug-Konsole ausgeben + + moveq #0,d0 + move.b dp_Flags(a2),d0 + move.w d0,-(SP) + move.l dp_FileName(a2),-(SP) + pea LoadingFmt(PC) + bsr _RawPrintfFunc + lea 10(SP),SP + + *** Packet bearbeiten + + movea.l a6,a5 ; A5 : MyExecBase + + movea.l dp_FileName(a2),a0 + bsr @CheckFile + move.l d0,d2 ; D2 : File-Länge + move.l d2,-(SP) + bne 1$ ; OK --> + pea NotFoundText(PC) + bsr _RawPrintfFunc + addq.w #4,SP + bra .Error +1$ + btst.b #DPB_ALLOCMEM,dp_Flags(a2) ; CHIP-Alloc gewünscht ? + beq.s .NoChipAlloc ; nein ---> + move.l d2,d0 ; File-Länge + movea.l a5,a6 ; MyExecBase + jsr meb_AllocMem(a6) + bra.s .AllocCont ; ---> +.NoChipAlloc: + btst.b #DPB_ALLOCFASTMEM,dp_Flags(a2) ; FAST-Alloc gewünscht? + beq.s .NoFastAlloc ; nein ---> + move.l d2,d0 ; File-Länge + movea.l a5,a6 ; MyExecBase + jsr meb_AllocFastMem(a6) +.AllocCont: move.l d0,dp_Address(a2) ; Adresse ins Packet +.NoFastAlloc: + + move.l dp_FileName(a2),d1 + move.l #MODE_OLDFILE,d2 + movea.l _DOSBase,a6 + JSRLIB Open + move.l d0,d7 + bne.s 2$ + + movea.l dp_FileName(a2),a0 + lea df0buf,a1 +.copy: move.b (a0)+,(a1)+ + bne.s .copy + + move.l #buf,d1 + JSRLIB Open + move.l d0,d7 + beq.s .Error +2$ + move.l d7,d1 + move.l dp_Address(a2),d2 + move.l #10000000,d3 + JSRLIB Read + + move.l d0,-(SP) + pea BytesFmt(PC) + bsr _RawPrintfFunc + lea 8(SP),SP + + move.l d7,d1 + JSRLIB Close + + movea.l a2,a0 + movea.l a5,a6 ; MyExecBase + bsr.s ReplyPacket ; Packet (A0) beantworten + +.EndProcReq: movem.l (SP)+,d0-d7/a0-a5 + rts + +.Error: movea.l a5,a6 ; MyExecBase + jmp meb_ColdReboot(a6) ; Raus hier! + + +*************************************************************************** + + *** Packet (A0) beantworten + +ReplyPacket: movem.l a0-a2,-(SP) + movea.l a0,a2 ; A2 : Packet + movea.l dp_Reply(a2),a1 ; A1 : User's Reply-Adresse + + *** Text ausgeben + + move.l dp_Address(a2),-(SP) + pea LoadedFmt(PC) + bsr _RawPrintfFunc + lea 8(SP),SP + + IFD CRUNCH + bclr.b #DPB_CRUNCHED,dp_Flags(a2) + beq.s 1$ + movea.l dp_Address(a2),a0 ; A0 : Decrunch-Start + move.l dp_FileSize(a2),d0 ; D0 : File-Länge gecruncht + move.l (a0),dp_FileSize(a2) ; Echte Länge für User + bsr PPDecrunch +1$: + ENDC + btst.b #DPB_REPLYHANDLER,dp_Flags(a2) + beq.s 2$ + movea.l a2,a0 ; A0 : Packet für User + jsr (a1) ; ReplyHandler aufrufen + bra.s 99$ ; ---> +2$: + btst.b #DPB_REPLYBYTE,dp_Flags(a2) + beq.s 3$ + st.b (a1) ; ReplyByte setzen + ;; bra.s 99$ ; ---> +3$: +99$: movem.l (SP)+,a0-a2 + rts + +************************************************************************** +** ** +** W R I T E F I L E - Existierende 'Datei' auf Disk überschreiben ** +** ** +** Parameter : D0.L : FN_-Konstante (von DiskMaker erzeugt) ** +** A0.L : Adresse der Daten für das File ** +** ** +************************************************************************** + +WriteFileFunc: rts + + +************************************************************************** +* D A T E N (auch im CODE-Segment wegen PC-relativ) * +************************************************************************** + +InsertDiskRoutine: ds.l 1 ; User's InsertDisk handler + + +LoadingFmt: dc.b "Loading '%s' (flags=$%02x) ... ",0 +BytesFmt: dc.b "%ld bytes ",0 +LoadedFmt: dc.b "at $%08lx",10,13,0 +NotFoundText: dc.b "file not found",10,13,0 + +buf: dc.b "DF0:" +df0buf: ds.b 64 + + END diff --git a/SysStart.c b/SysStart.c new file mode 100644 index 0000000..808bc43 --- /dev/null +++ b/SysStart.c @@ -0,0 +1,220 @@ +/**************************************************************************** +** ** +** SysStart.c - Startet Exec MIT Betriebssystem ** +** ** +***************************************************************************** +** ** +** Modification History ** +** -------------------- ** +** ** +** 24-Feb-91 CHW Created this file from Start.S ** +** ** +****************************************************************************/ + +#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 <string.h> /* z.B. für __builtin_memcpy */ +#include <dos.h> + +#include <chlib.h> + + +char ident[] = "$VER: SysStart 5.0 by Christian A. Weber (" __DATE__ ")"; +char CLI_Template[] = "CS=CHIPSIZE/N,FS=FASTSIZE/N,MOD/K,PRI/N"; +char CLI_Help[] = "Usage: SysStart [CHIPSIZE kbytes] [FASTSIZE kbytes] [MOD name] [PRI pri]"; + +extern __regargs void Exit(LONG); +extern void RawPrintfFunc(char *, ...); + +extern struct ExecBase *SysBase; +extern struct GfxBase *GfxBase; + +extern BPTR StdErr; /* Standard Error output stream */ +extern struct Custom far volatile custom; + +extern void __asm __far InitExec( + 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 *); + + +struct +{ + LONG *ChipSizePtr; + LONG *FastSizePtr; + char *ModName; + LONG *PriPtr; +} argv; + + +UBYTE *chipbase; /* Startadresse des CHIP-RAMs für Exec */ +LONG chipsize; /* Grösse des CHIP-RAMs für Exec */ + +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; +BYTE oldtaskpri; + + +/***************************************************************************/ +/* Alles freigeben, back to DOS */ + +__saveds void ExitRoutine(void) +{ + int i; + custom.color[0] = 0x173; /* Grünlich */ + + RawPrintfFunc("SysStart: ExitRoutine()\r\n"); + printf("done.\n"); + + WaitBlit(); + DisownBlitter(); + + custom.cop1lc = (ULONG)GfxBase->copinit; /* Bild wieder einschalten */ + + custom.dmacon = 0x7FFF; + custom.dmacon = dmaconsave | DMAF_SETCLR; /* Original dmacon zurückholen */ + + custom.intena = 0x7FFF; + custom.intena = intenasave | INTF_SETCLR; /* Dito mit intena */ + + for(i=0; i<8; ++i) + custom.spr[i].dataa = custom.spr[i].datab = 0; + + RemakeDisplay(); + SetTaskPri(SysBase->ThisTask, oldtaskpri); + + if (fastbase) + { + FreeMem(fastbase, fastsize); + fastbase = NULL; + } + + if (chipbase) + { + FreeMem(chipbase, chipsize); + chipbase = NULL; + } + + CloseIntLib(); + CloseGfxLib(); + + Exit(RETURN_OK); +} + + +/***************************************************************************/ +/* Hauptprogramm */ + +LONG Main(LONG arglen, char *argline) +{ + char *module = "MainPrg"; + LONG taskpri=4; + + OpenGfxLib(); + OpenIntLib(); + + Puts(ident+6); + + AllocMem(0x40000000,0); /* Flushlibs */ + AllocMem(0x40000000,0); + + if (argv.ChipSizePtr) + { + chipsize = *argv.ChipSizePtr << 10; /* KBytes to Bytes */ + if(chipsize < 100000) + { + Puts("CHIP size must be > 100K, please try again!"); + return RETURN_ERROR; + } + } + else + { + chipsize = (AvailMem(MEMF_CHIP|MEMF_LARGEST) - 30000) & ~0xff; + if(chipsize > 1000000) + chipsize = (3*chipsize)/4; + } + + + if (argv.FastSizePtr) + { + fastsize = *argv.FastSizePtr << 10; + } + else + { + fastsize = (AvailMem(MEMF_FAST|MEMF_LARGEST) - 50000) & ~0xff; + if(fastsize > 1000000) + fastsize = (3*fastsize)/4; + } + + if (argv.ModName) + module = argv.ModName; + + if (argv.PriPtr) + taskpri = *argv.PriPtr; + + + if (chipbase = AllocMem(chipsize, MEMF_CHIP|MEMF_CLEAR)) + { + printf("Chip RAM: $%08lx (%ldK)\n", chipbase, chipsize >> 10); + + if (fastbase = AllocMem(fastsize, MEMF_FAST|MEMF_CLEAR)) + { + printf("Fast RAM: $%08lx (%ldK)\n", fastbase, fastsize >> 10); + } + else + { + fastsize = 0; + Puts("Not enough FAST RAM available"); + } + + OwnBlitter(); + WaitBlit(); + + oldtaskpri = SetTaskPri(SysBase->ThisTask,taskpri); + + /* 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; + + custom.color[0] = 0xF00; /* Bildschirm rot */ + + printf("Running %s ... ", module); + RawPrintfFunc("%s: Running %s ...\r\n", ident+6, module); + + InitExec( attnflags, /* D0 */ + sysbplcon0, /* D1 */ + vblankfreq, /* D2 */ + 0, /* D3 : Product-Code */ + (LONG)module, /* D4 : MainPrg-Name */ + chipbase, /* A0 : CHIP-Startadresse */ + chipbase+chipsize, /* A1 : CHIP-Grösse */ + fastbase, /* A2 : FAST-Startadresse */ + fastbase+fastsize /* A3 : FAST-Endadresse */ + ); + + ExitRoutine(); + /* not reached */ + + } + else printf("Can't get %ldK CHIP RAM!\n",chipsize/1024); + + return RETURN_WARN; + +} diff --git a/protcustom.i b/protcustom.i new file mode 100644 index 0000000..b720fe8 --- /dev/null +++ b/protcustom.i @@ -0,0 +1,125 @@ +************************************************************************** +** ** +** protcustom.i - Offsets der Amiga Custom-Chips, Base falsch! ** +** ** +************************************************************************** +** ** +** Modification History ** +** -------------------- ** +** ** +** 20-Jan-88 Created this file from relcustom.i ** +** 26-Apr-89 sprdatb corrected (was 8, should be 6) ** +** 29-Jun-89 Ist jetzt auch Genim2-kompatibel ** +** 16-Sep-90 CUSTOMOFFSET muss jetzt extern definiert werden ** +** ** +************************************************************************** + +custom: EQU $dff000-CUSTOMOFFSET ; Start der Custom-Chips + +bltddat: EQU $000+CUSTOMOFFSET +dmaconr: EQU $002+CUSTOMOFFSET +vposr: EQU $004+CUSTOMOFFSET +vhposr: EQU $006+CUSTOMOFFSET +dskdatr: EQU $008+CUSTOMOFFSET +joy0dat: EQU $00A+CUSTOMOFFSET +joy1dat: EQU $00C+CUSTOMOFFSET +clxdat: EQU $00E+CUSTOMOFFSET +adkconr: EQU $010+CUSTOMOFFSET +pot0dat: EQU $012+CUSTOMOFFSET +pot1dat: EQU $014+CUSTOMOFFSET +potinp: EQU $016+CUSTOMOFFSET +serdatr: EQU $018+CUSTOMOFFSET +dskbytr: EQU $01A+CUSTOMOFFSET +intenar: EQU $01C+CUSTOMOFFSET +intreqr: EQU $01E+CUSTOMOFFSET +dskpt: EQU $020+CUSTOMOFFSET +dsklen: EQU $024+CUSTOMOFFSET +dskdat: EQU $026+CUSTOMOFFSET +refptr: EQU $028+CUSTOMOFFSET +vposw: EQU $02A+CUSTOMOFFSET +vhposw: EQU $02C+CUSTOMOFFSET +copcon: EQU $02E+CUSTOMOFFSET +serdat: EQU $030+CUSTOMOFFSET +serper: EQU $032+CUSTOMOFFSET +potgo: EQU $034+CUSTOMOFFSET +joytest: EQU $036+CUSTOMOFFSET +strequ: EQU $038+CUSTOMOFFSET +strvbl: EQU $03A+CUSTOMOFFSET +strhor: EQU $03C+CUSTOMOFFSET +strlong: EQU $03E+CUSTOMOFFSET + +bltcon0: EQU $040+CUSTOMOFFSET +bltcon1: EQU $042+CUSTOMOFFSET +bltafwm: EQU $044+CUSTOMOFFSET +bltalwm: EQU $046+CUSTOMOFFSET +bltcpt: EQU $048+CUSTOMOFFSET +bltbpt: EQU $04C+CUSTOMOFFSET +bltapt: EQU $050+CUSTOMOFFSET +bltdpt: EQU $054+CUSTOMOFFSET +bltsize: EQU $058+CUSTOMOFFSET + +bltcmod: EQU $060+CUSTOMOFFSET +bltbmod: EQU $062+CUSTOMOFFSET +bltamod: EQU $064+CUSTOMOFFSET +bltdmod: EQU $066+CUSTOMOFFSET + +bltcdat: EQU $070+CUSTOMOFFSET +bltbdat: EQU $072+CUSTOMOFFSET +bltadat: EQU $074+CUSTOMOFFSET + +dsksync: EQU $07E+CUSTOMOFFSET + +cop1lc: EQU $080+CUSTOMOFFSET +cop2lc: EQU $084+CUSTOMOFFSET +copjmp1: EQU $088+CUSTOMOFFSET +copjmp2: EQU $08A+CUSTOMOFFSET +copins: EQU $08C+CUSTOMOFFSET +diwstrt: EQU $08E+CUSTOMOFFSET +diwstop: EQU $090+CUSTOMOFFSET +ddfstrt: EQU $092+CUSTOMOFFSET +ddfstop: EQU $094+CUSTOMOFFSET +dmacon: EQU $096+CUSTOMOFFSET +clxcon: EQU $098+CUSTOMOFFSET +intena: EQU $09A+CUSTOMOFFSET +intreq: EQU $09C+CUSTOMOFFSET +adkcon: EQU $09E+CUSTOMOFFSET + +aud: EQU $0A0+CUSTOMOFFSET +aud0: EQU $0A0+CUSTOMOFFSET ; Basis fuer Audio-Kanal 0 +aud1: EQU $0B0+CUSTOMOFFSET ; Basis fuer Audio-Kanal 1 +aud2: EQU $0C0+CUSTOMOFFSET ; Basis fuer Audio-Kanal 2 +aud3: EQU $0D0+CUSTOMOFFSET ; Basis fuer Audio-Kanal 3 + +audlc: EQU $00 +audlen: EQU $04 +audper: EQU $06 +audvol: EQU $08 +auddat: EQU $0A + +bplpt: EQU $0E0+CUSTOMOFFSET ; Basis fuer BitPlane Pointer +bpl1pt: EQU $0E0+CUSTOMOFFSET +bpl2pt: EQU $0E4+CUSTOMOFFSET +bpl3pt: EQU $0E8+CUSTOMOFFSET +bpl4pt: EQU $0EC+CUSTOMOFFSET +bpl5pt: EQU $0F0+CUSTOMOFFSET +bpl6pt: EQU $0F4+CUSTOMOFFSET + +bplcon0: EQU $100+CUSTOMOFFSET +bplcon1: EQU $102+CUSTOMOFFSET +bplcon2: EQU $104+CUSTOMOFFSET +bpl1mod: EQU $108+CUSTOMOFFSET +bpl2mod: EQU $10A+CUSTOMOFFSET +bpldat: EQU $110+CUSTOMOFFSET + +sprpt: EQU $120+CUSTOMOFFSET ; Basis fuer Sprite-Pointers +spr: EQU $140+CUSTOMOFFSET ; Basis fuer Sprites + +sprpos: EQU $00+CUSTOMOFFSET +sprctl: EQU $02+CUSTOMOFFSET +sprdataa: EQU $04+CUSTOMOFFSET +sprdatab: EQU $06+CUSTOMOFFSET + +color: EQU $180+CUSTOMOFFSET + +beamcon0: EQU $1DC+CUSTOMOFFSET ; Fatter Agnus only + diff --git a/relcustom.i b/relcustom.i new file mode 100644 index 0000000..f4a90ed --- /dev/null +++ b/relcustom.i @@ -0,0 +1,168 @@ +********************************************************************* +** ** +** relcustom.i - Alle Offsets der Amiga Custom-Chips ** +** ** +** Created: 27-Oct-87 CHW Last update: 16-Jan-88 CHW ** +** ** +********************************************************************* + +custom: EQU $dff000 ; Startadresse der Custom-Chips + +bltddat: EQU $000 +dmaconr: EQU $002 +vposr: EQU $004 +vhposr: EQU $006 +dskdatr: EQU $008 +joy0dat: EQU $00A +joy1dat: EQU $00C +clxdat: EQU $00E +adkconr: EQU $010 +pot0dat: EQU $012 +pot1dat: EQU $014 +potinp: EQU $016 +serdatr: EQU $018 +dskbytr: EQU $01A +intenar: EQU $01C +intreqr: EQU $01E +dskpt: EQU $020 +dsklen: EQU $024 +dskdat: EQU $026 +refptr: EQU $028 +vposw: EQU $02A +vhposw: EQU $02C +copcon: EQU $02E +serdat: EQU $030 +serper: EQU $032 +potgo: EQU $034 +joytest: EQU $036 +strequ: EQU $038 +strvbl: EQU $03A +strhor: EQU $03C +strlong: EQU $03E + +bltcon0: EQU $040 +bltcon1: EQU $042 +bltafwm: EQU $044 +bltalwm: EQU $046 +bltcpt: EQU $048 +bltbpt: EQU $04C +bltapt: EQU $050 +bltdpt: EQU $054 +bltsize: EQU $058 + +bltcmod: EQU $060 +bltbmod: EQU $062 +bltamod: EQU $064 +bltdmod: EQU $066 + +bltcdat: EQU $070 +bltbdat: EQU $072 +bltadat: EQU $074 + +dsksync: EQU $07E + +cop1lc: EQU $080 +cop2lc: EQU $084 +copjmp1: EQU $088 +copjmp2: EQU $08A +copins: EQU $08C +diwstrt: EQU $08E +diwstop: EQU $090 +ddfstrt: EQU $092 +ddfstop: EQU $094 +dmacon: EQU $096 +clxcon: EQU $098 +intena: EQU $09A +intreq: EQU $09C +adkcon: EQU $09E + +aud: EQU $0A0 +aud0: EQU $0A0 ; Basis fuer Audio-Kanal 0 +aud1: EQU $0B0 ; Basis fuer Audio-Kanal 1 +aud2: EQU $0C0 ; Basis fuer Audio-Kanal 2 +aud3: EQU $0D0 ; Basis fuer Audio-Kanal 3 + +audlc: EQU $00 +audlen: EQU $04 +audper: EQU $06 +audvol: EQU $08 +auddat: EQU $0A + +bplpt: EQU $0E0 ; Basis fuer BitPlane Pointer +bpl1pt: EQU $0E0 +bpl2pt: EQU $0E4 +bpl3pt: EQU $0E8 +bpl4pt: EQU $0EC +bpl5pt: EQU $0F0 +bpl6pt: EQU $0F4 + +bplcon0: EQU $100 +bplcon1: EQU $102 +bplcon2: EQU $104 +bpl1mod: EQU $108 +bpl2mod: EQU $10A +bpldat: EQU $110 + +sprpt: EQU $120 ; Basis fuer Sprite-Pointers +spr: EQU $140 ; Basis fuer Sprites + +sprpos: EQU $00 +sprctl: EQU $02 +sprdata: EQU $04 +sprdatb: EQU $08 + +color: EQU $180 + +htotal EQU $1c0 +hsstop EQU $1c2 +hbstrt EQU $1c4 +hbstop EQU $1c6 +vtotal EQU $1c8 +vsstop EQU $1ca +vbstrt EQU $1cc +vbstop EQU $1ce +sprhstrt EQU $1d0 +sprhstop EQU $1d2 +bplhstrt EQU $1d4 +bplhstop EQU $1d6 +hhposw EQU $1d8 +hhposr EQU $1da +beamcon0 EQU $1dc +hsstrt EQU $1de +vsstrt EQU $1e0 +hcenter EQU $1e2 +diwhigh EQU $1e4 + + +VARVBLANK EQU $1000 ; Variable vertical blank enable +LOLDIS EQU $0800 ; long line disable +CSCBLANKEN EQU $0400 ; redirect composite sync +VARVSYNC EQU $0200 ; Variable vertical sync enable +VARHSYNC EQU $0100 ; Variable horizontal sync enable +VARBEAM EQU $0080 ; variable beam counter enable +DISPLAYDUAL EQU $0040 ; use UHRES pointer and standard pointers +DISPLAYPAL EQU $0020 ; set decodes to generate PAL display +VARCSYNC EQU $0010 ; Variable composite sync enable +CSBLANK EQU $0008 ; Composite blank out to CSY* pin +CSYNCTRUE EQU $0004 ; composite sync true signal +VSYNCTRUE EQU $0002 ; vertical sync true +HSYNCTRUE EQU $0001 ; horizontal sync true + + ** new defines for bplcon0 +USE_BPLCON3 EQU 1 + ** new defines for bplcon2 + +BPLCON2_ZDCTEN EQU (1<<10) ; colormapped genlock bit +BPLCON2_ZDBPEN EQU (1<<11) ; use bitplane as genlock bits +BPLCON2_ZDBPSEL0 EQU (1<<12) ; three bits to select one +BPLCON2_ZDBPSEL1 EQU (1<<13) ; of 8 bitplanes in +BPLCON2_ZDBPSEL2 EQU (1<<14) ; ZDBPEN genlock mode + + ** defines for bplcon3 register + +BPLCON3_EXTBLNKEN EQU (1<<0) ; external blank enable +BPLCON3_EXTBLKZD EQU (1<<1) ; external blank ored into trnsprncy +BPLCON3_ZDCLKEN EQU (1<<2) ; zd pin outputs a 14mhz clock +BPLCON3_BRDNTRAN EQU (1<<4) ; border is opaque +BPLCON3_BRDNBLNK EQU (1<<5) ; border is opaque + diff --git a/zeropage.i b/zeropage.i new file mode 100644 index 0000000..b1f2436 --- /dev/null +++ b/zeropage.i @@ -0,0 +1,39 @@ +*************************************************************************** +** ** +** zeropage.i - Alle Interrupt- und Exception-Vektoren ** +** ** +** Modification History ** +** -------------------- ** +** ** +** 06-May-89 CHW Created this file! ** +** ** +*************************************************************************** + + STRUCTURE ZeroPage,0 + + APTR ResetSSP ; 0 + APTR ResetVector ; 1 + APTR BusErrorVector ; 2 + APTR AddrErrVector ; 3 + APTR IllegalVector ; 4 + APTR DivZeroVector ; 5 + APTR ChkVector ; 6 + APTR TrapVVector ; 7 + APTR PrivVector ; 8 + APTR TraceVector ; 9 + APTR LineAVector ; A + APTR LineFVector ; B + APTR Reserved0C ; C + APTR ProtocolVector ; D + APTR FormatVector ; E + APTR NotIntVector ; F + STRUCT Reserved10,8*4 ; 10-17 + APTR WrongIntVector ; 18 + APTR Level1Vector ; 19 + APTR Level2Vector ; 1A + APTR Level3Vector ; 1B + APTR Level4Vector ; 1C + APTR Level5Vector ; 1D + APTR Level6Vector ; 1E + APTR Level7Vector ; 1F + STRUCT TrapVectors,16*4 ; 20-2F |