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