; Cartridge assembler code. ; 68000 code that is used for starting programs from the emulated GEMDOS harddisk ; and for using bigger VDI resolutions ; Hatari's "illegal" (free) opcodes: GEMDOS_OPCODE equ 8 SYSINIT_OPCODE equ 10 VDI_OPCODE equ 12 ; System variables: _longframe equ $059E org $fa0000 ; This is the cartridge header: dc.l $ABCDEF42 ; C-FLAG (magic value) dc.l $00000000 ; C-NEXT dc.l sys_init+$08000000 ; C-INIT - flag has bit 3 set = before disk boot, but after GEMDOS init dc.l infoprgstart ; C-RUN dc.w %0101100000000000 ; C-TIME dc.w %0011001000101001 ; C-DATE dc.l infoprgend-infoprgstart ; C-BSIZ, offset: $14 dc.b 'HATARI.TOS',0,0 ; C-NAME .even old_gemdos: ds.l 1 ; has to match the CART_OLDGEMDOS define! vdi_opcode: dc.w VDI_OPCODE ; Address to call after Trap #2 (VDI), causes illegal instruction ; New GemDOS vector (0x84) - for intercepting Pexec new_gemdos: dc.w GEMDOS_OPCODE ; Returns NEG as run old vector, ZERO to return or OVERFLOW to run pexec bvs.s pexec bne.s go_oldgemdos rte ; Branch to old GemDOS go_oldgemdos: move.l old_gemdos(pc),-(sp) ; Set PC to 'old_gemdos' and continue execution, WITHOUT corrupting registers! rts ; Progam Execute pexec: move usp,a0 ; Parameters on user stack pointer? btst #5,(sp) ; Check if program was in user or supervisor mode beq.s p_ok lea 6(sp),a0 ; Parameters are on SSP tst.w _longframe.w ; Do we use a CPU > 68000? beq.s p_ok ; No: A0 is OK addq #2,a0 ; Skip 2 additional stack frame bytes on CPUs >= 68010 p_ok: addq #2,a0 ; Skip GEMDOS function number tst (a0) ; Test pexec mode bne.s no_0 ; Simulate pexec mode 0 move.l a6,-(sp) move.l a0,a6 move.l a6,-(sp) ;new bsr.s find_prog move.l (sp)+,a6 ;new bsr pexec5 bsr reloc clr.l 2(a6) clr.l 10(a6) move.l d0,6(a6) move.w #48,-(sp) ; Sversion: get GEMDOS version trap #1 ; call GEMDOS addq #2,sp ror.w #8,d0 ; Major version to high, minor version to low byte cmp.w #$0015,d0 bge.s use_gemdos_015 move.w #4,(a6) ; pexec mode 4 for exec. prepared program bra.s mode0_ok use_gemdos_015: move.w #6,(a6) ; On GEMDOS 0.15 and higher, we can use mode 6 mode0_ok: move.l (sp)+,a6 bra.s go_oldgemdos no_0: cmp #3,(a0) bne.s go_oldgemdos ; Simulate pexec mode 3 move.l a6,-(sp) move.l a0,a6 bsr.s find_prog bsr.s pexec5 bsr.s reloc gohome: move.l (sp)+,a6 rte find_prog: move #$2f,-(sp) ; Fgetdta trap #1 ; Gemdos addq #2,sp move.l d0,a0 move.l (a0)+,-(sp) move.l (a0)+,-(sp) move.l (a0)+,-(sp) move.l (a0)+,-(sp) move.l (a0)+,-(sp) move.l (a0)+,-(sp) move.l (a0)+,-(sp) move.l (a0)+,-(sp) move.l (a0)+,-(sp) move.l (a0)+,-(sp) move.l (a0)+,-(sp) move.l a0,-(sp) move #$17,-(sp) move.l 2(a6),-(sp) move #$4e,-(sp) ; Fsfirst trap #1 ; Gemdos addq #8,sp move.l (sp)+,a0 move.l (sp)+,-(a0) move.l (sp)+,-(a0) move.l (sp)+,-(a0) move.l (sp)+,-(a0) move.l (sp)+,-(a0) move.l (sp)+,-(a0) move.l (sp)+,-(a0) move.l (sp)+,-(a0) move.l (sp)+,-(a0) move.l (sp)+,-(a0) move.l (sp)+,-(a0) tst.l d0 beq.s findprog_ok addq #4,sp bra.s gohome findprog_ok: rts pexec5: move.l 10(a6),-(sp) move.l 6(a6),-(sp) clr.l -(sp) move #5,-(sp) move #$4b,-(sp) ; Pexec trap #1 ; Gemdos lea 16(sp),sp tst.l d0 bmi.s pexecerr rts pexecerr: addq #4,sp bra.s gohome reloc: movem.l a3-a5/d6-d7,-(sp) move.l d0,a5 clr -(sp) move.l 2(a6),-(sp) move #$3d,-(sp) ; Fopen trap #1 ; Gemdos addq #8,sp move.l d0,d6 move.l a5,-(sp) add.l #228,(sp) pea $1c.w move d6,-(sp) move #$3f,-(sp) ; Fread trap #1 ; Gemdos lea 12(sp),sp ; check size!! move.l a5,-(sp) add.l #256,(sp) pea $7fffffff move d6,-(sp) move #$3f,-(sp) ; Fread trap #1 ; Gemdos lea 12(sp),sp move d6,-(sp) move #$3e,-(sp) ; Fclose trap #1 ; Gemdos addq #4,sp lea 8(a5),a4 move.l a5,d0 add.l #$100,d0 move.l d0,(a4)+ ; text start move.l 230(a5),d0 move.l d0,(a4)+ ; text length add.l 8(a5),d0 ; data start move.l d0,(a4)+ move.l 234(a5),(a4)+ ; data length add.l 234(a5),d0 move.l d0,(a4)+ ; bss start move.l 238(a5),(a4)+ ; bss length move.l a5,d0 add.l #$80,d0 move.l d0,32(a5) move.l 24(a5),a4 add.l 242(a5),a4 ; symbol table length move.l 8(a5),a3 move.l a3,d0 tst.w 254(a5) bne.s relocdone ; Get first offset of the relocation table. Since A4 seems sometimes not ; to be word aligned (if symbol table length is uneven), we have to read ; byte by byte... move.b (a4),d7 clr.b (a4)+ lsl.w #8,d7 move.b (a4),d7 clr.b (a4)+ swap d7 move.b (a4),d7 clr.b (a4)+ lsl.w #8,d7 move.b (a4),d7 clr.b (a4)+ tst.l d7 beq.s relocdone adda.l d7,a3 moveq #0,d7 relloop0: add.l d0,(a3) relloop: move.b (a4),d7 move.b #$00,(a4)+ ; Some programs like GFA-Basic expect a clear memory tst.b d7 beq.s relocdone cmp.b #1,d7 bne.s no254 lea 254(a3),a3 bra.s relloop no254: adda.w d7,a3 bra.s relloop0 relocdone: move.l 28(a5),d0 beq.s cleardone move.l 24(a5),a0 clear: clr.b (a0)+ subq.l #1,d0 bne.s clear cleardone: move.l a5,d0 movem.l (sp)+,a3-a5/d6-d7 rts ; This code is called during TOS' boot sequence. ; It gets a pointer to the Line-A variables and uses an illegal opcode ; to run our system initialization code in OpCode_SysInit(). sys_init: dc.w $A000 ; Line-A init (needed for VDI resolutions) dc.w SYSINIT_OPCODE ; Illegal opcode to call OpCode_SysInit() rts ; This code is run when the user starts the HATARI.PRG ; in the cartridge. It simply displays some information text. infoprgstart: pea hatarix32(pc) move.w #32,-(sp) trap #14 ; Dosound - play some music :-) addq.l #6,sp pea infotext(pc) move.w #9,-(sp) trap #1 ; Cconws - display the information text addq.l #6,sp move.w #7,-(sp) trap #1 ; Crawcin - wait for a key addq.l #2,sp clr.w -(sp) trap #1 ; Pterm0 infotext: dc.b 27,'E',13,10 dc.b ' =========================',13,10 dc.b ' Hatari keyboard shortcuts',13,10 dc.b ' =========================',13,10 dc.b 13,10 dc.b ' F11 : toggle fullscreen/windowed mode',13,10 dc.b ' F12 : activate the setup GUI of Hatari',13,10 dc.b 13,10 dc.b 'All other shortcuts are activated by',13,10 dc.b 'pressing AltGr or Right-Alt or Meta key',13,10 dc.b 'together with one of the following keys:',13,10 dc.b 13,10 dc.b ' a : Record animation',13,10 dc.b ' g : Grab a screenshot',13,10 dc.b ' i : Leave full screen & iconify window',13,10 dc.b ' j : joystick via key joystick on/off',13,10 dc.b ' m : mouse grab',13,10 dc.b ' r : warm reset of the ST',13,10 dc.b ' c : cold reset of the ST',13,10 dc.b ' s : enable/disable sound',13,10 dc.b ' q : quit the emulator',13,10 dc.b ' x : toggle normal/max speed',13,10 dc.b ' y : enable/disable sound recording',13,10 dc.b 0 hatarix32: ibytes 'cart_mus.x32' infoprgend: END