|
|
1.1.1.4 root 1: ; Cartridge assembler code.
1.1.1.3 root 2: ; 68000 code that is used for starting programs from the emulated GEMDOS harddisk
1.1.1.4 root 3: ; and for using bigger VDI resolutions
1.1.1.3 root 4:
1.1.1.4 root 5: ; Hatari's "illegal" (free) opcodes:
6: GEMDOS_OPCODE equ 8
7: SYSINIT_OPCODE equ 10
8: VDI_OPCODE equ 12
1.1.1.3 root 9:
1.1.1.4 root 10: ; System variables:
11: _longframe equ $059E
1.1 root 12:
13:
1.1.1.4 root 14: org $fa0000
1.1.1.3 root 15:
1.1 root 16:
1.1.1.4 root 17: ; This is the cartridge header:
18: dc.l $ABCDEF42 ; C-FLAG (magic value)
19: dc.l $00000000 ; C-NEXT
20: dc.l sys_init+$08000000 ; C-INIT - flag has bit 3 set = before disk boot, but after GEMDOS init
21: dc.l infoprgstart ; C-RUN
22: dc.w %0101100000000000 ; C-TIME
23: dc.w %0011001000101001 ; C-DATE
24: dc.l infoprgend-infoprgstart ; C-BSIZ, offset: $14
25: dc.b 'HATARI.TOS',0,0 ; C-NAME
26:
27: .even
28:
29:
30: old_gemdos: ds.l 1 ; has to match the CART_OLDGEMDOS define!
31: vdi_opcode: dc.w VDI_OPCODE ; Address to call after Trap #2 (VDI), causes illegal instruction
32:
33: ; New GemDOS vector (0x84) - for intercepting Pexec
1.1.1.3 root 34: new_gemdos:
1.1 root 35: dc.w GEMDOS_OPCODE ; Returns NEG as run old vector, ZERO to return or OVERFLOW to run pexec
1.1.1.3 root 36: bvs.s pexec
37: bne.s go_oldgemdos
1.1 root 38: rte
39:
1.1.1.4 root 40: ; Branch to old GemDOS
1.1.1.3 root 41: go_oldgemdos:
1.1.1.4 root 42: move.l old_gemdos(pc),-(sp) ; Set PC to 'old_gemdos' and continue execution, WITHOUT corrupting registers!
1.1.1.3 root 43: rts
1.1 root 44:
1.1.1.4 root 45: ; Progam Execute
1.1.1.3 root 46: pexec:
1.1.1.4 root 47: move usp,a0 ; Parameters on user stack pointer?
48: btst #5,(sp) ; Check if program was in user or supervisor mode
49: beq.s p_ok
50: lea 6(sp),a0 ; Parameters are on SSP
51: tst.w _longframe.w ; Do we use a CPU > 68000?
52: beq.s p_ok ; No: A0 is OK
53: addq #2,a0 ; Skip 2 additional stack frame bytes on CPUs >= 68010
54: p_ok:
55: addq #2,a0 ; Skip GEMDOS function number
1.1.1.3 root 56: tst (a0) ; Test pexec mode
1.1 root 57: bne.s no_0
1.1.1.3 root 58:
59: ; Simulate pexec mode 0
1.1 root 60: move.l a6,-(sp)
61: move.l a0,a6
1.1.1.3 root 62: bsr.s find_prog
1.1.1.7 root 63: bsr load_n_reloc
1.1 root 64: clr.l 2(a6)
65: clr.l 10(a6)
66: move.l d0,6(a6)
1.1.1.3 root 67:
68: move.w #48,-(sp) ; Sversion: get GEMDOS version
1.1.1.7 root 69: trap #1 ; call GEMDOS
1.1.1.3 root 70: addq #2,sp
71: ror.w #8,d0 ; Major version to high, minor version to low byte
72: cmp.w #$0015,d0
73: bge.s use_gemdos_015
74: move.w #4,(a6) ; pexec mode 4 for exec. prepared program
75: bra.s mode0_ok
76: use_gemdos_015:
77: move.w #6,(a6) ; On GEMDOS 0.15 and higher, we can use mode 6
78: mode0_ok:
79:
1.1 root 80: move.l (sp)+,a6
1.1.1.3 root 81: bra.s go_oldgemdos
82:
1.1 root 83: no_0:
84: cmp #3,(a0)
85: bne.s go_oldgemdos
1.1.1.3 root 86:
87: ; Simulate pexec mode 3
1.1 root 88: move.l a6,-(sp)
89: move.l a0,a6
1.1.1.3 root 90: bsr.s find_prog
1.1.1.7 root 91: bsr.s load_n_reloc
1.1 root 92: gohome:
93: move.l (sp)+,a6
94: rte
1.1.1.3 root 95:
1.1 root 96: find_prog:
1.1.1.3 root 97: move #$2f,-(sp) ; Fgetdta
1.1.1.2 root 98: trap #1 ; Gemdos
1.1 root 99: addq #2,sp
100: move.l d0,a0
101: move.l (a0)+,-(sp)
102: move.l (a0)+,-(sp)
103: move.l (a0)+,-(sp)
104: move.l (a0)+,-(sp)
105: move.l (a0)+,-(sp)
106: move.l (a0)+,-(sp)
107: move.l (a0)+,-(sp)
108: move.l (a0)+,-(sp)
109: move.l (a0)+,-(sp)
110: move.l (a0)+,-(sp)
111: move.l (a0)+,-(sp)
112: move.l a0,-(sp)
113: move #$17,-(sp)
114: move.l 2(a6),-(sp)
1.1.1.3 root 115: move #$4e,-(sp) ; Fsfirst
1.1.1.2 root 116: trap #1 ; Gemdos
1.1 root 117: addq #8,sp
118: move.l (sp)+,a0
119: move.l (sp)+,-(a0)
120: move.l (sp)+,-(a0)
121: move.l (sp)+,-(a0)
122: move.l (sp)+,-(a0)
123: move.l (sp)+,-(a0)
124: move.l (sp)+,-(a0)
125: move.l (sp)+,-(a0)
126: move.l (sp)+,-(a0)
127: move.l (sp)+,-(a0)
128: move.l (sp)+,-(a0)
129: move.l (sp)+,-(a0)
130: tst.l d0
131: beq.s findprog_ok
132: addq #4,sp
133: bra.s gohome
134: findprog_ok:
135: rts
1.1.1.3 root 136:
1.1.1.7 root 137:
138: load_n_reloc:
1.1.1.8 ! root 139: movem.l a3-a5/d6,-(sp)
! 140:
! 141: clr.w -(sp)
1.1 root 142: move.l 2(a6),-(sp)
1.1.1.8 ! root 143: move.w #$3d,-(sp) ; Fopen
1.1.1.2 root 144: trap #1 ; Gemdos
1.1 root 145: addq #8,sp
1.1.1.7 root 146: move.l d0,d6 ; Keep file handle in d6
1.1.1.8 ! root 147: tst.l d0
! 148: bmi lr_err_out
1.1.1.6 root 149:
1.1.1.8 ! root 150: clr.w -(sp) ; Temporary space for prg header magic
! 151: move.l sp,-(sp)
! 152: move.l #2,-(sp)
1.1 root 153: move d6,-(sp)
1.1.1.3 root 154: move #$3f,-(sp) ; Fread
1.1.1.8 ! root 155: trap #1 ; Gemdos: Read header magic
! 156: lea 12(sp),sp
! 157: move.w (sp)+,d1
! 158: cmp.l #2,d0
! 159: bne load_reloc_error
! 160:
! 161: cmp.w #$601a,d1 ; Check program header magic
! 162: beq.s hdr_magic_ok
! 163: move.l #-66,d0 ; Error code: Invalid PRG format
! 164: bra load_reloc_error
! 165: hdr_magic_ok:
! 166: clr.w -(sp)
! 167: move.w d6,-(sp)
! 168: move.l #22,-(sp) ; offset of the program flags
! 169: move.w #66,-(sp) ; Fseek
! 170: trap #1 ; Gemdos: Seek to program flags
! 171: lea 10(sp),sp
! 172: cmp.l #22,d0
! 173: bne load_reloc_error
! 174:
! 175: clr.l -(sp) ; Temporary space for program flags
! 176: move.l sp,-(sp)
! 177: move.l #4,-(sp)
! 178: move d6,-(sp)
! 179: move #$3f,-(sp) ; Fread
! 180: trap #1 ; Gemdos: Read program flags
1.1.1.6 root 181: lea 12(sp),sp
1.1.1.8 ! root 182: move.l (sp)+,a3 ; Program flags now in a3
! 183: cmp.l #4,d0
! 184: bne load_reloc_error
1.1.1.6 root 185:
1.1.1.8 ! root 186: ; Let's call Pexec now to create the basepage, first try
! 187: ; Pexec(7) and if that does not work fall back to mode 5
! 188: move.l 10(a6),-(sp)
! 189: move.l 6(a6),-(sp)
! 190: move.l a3,-(sp) ; program flags in program header
! 191: move.w #7,-(sp) ; Create basepage wrt program flags
! 192: move.w #$4b,-(sp) ; Pexec (mode 7)
! 193: trap #1 ; Gemdos
! 194: lea 16(sp),sp
! 195: tst.l d0
! 196: bpl.s pexec_ok
! 197:
! 198: move.l 10(a6),-(sp)
! 199: move.l 6(a6),-(sp)
! 200: clr.l -(sp)
! 201: move.w #5,-(sp) ; Create basepage
! 202: move.w #$4b,-(sp) ; Pexec (mode 5)
! 203: trap #1 ; Gemdos
! 204: lea 16(sp),sp
! 205: tst.l d0
! 206: bmi load_reloc_error
! 207:
! 208: pexec_ok:
! 209: move.l d0,a5 ; Basepage in a5
! 210:
! 211: clr.w -(sp)
! 212: move.w d6,-(sp)
! 213: clr.l -(sp) ; Back to the start of the file
! 214: move.w #66,-(sp) ; Fseek
! 215: trap #1 ; Gemdos: Seek to start of the file
! 216: lea 10(sp),sp
! 217: tst.l d0
! 218: bne lr_err_free
1.1.1.7 root 219:
220: lea 256(a5),a3 ; a3 points now to the program header
1.1.1.8 ! root 221: move.l a3,-(sp)
! 222: move.l #$1c,-(sp)
! 223: move d6,-(sp)
! 224: move #$3f,-(sp) ; Fread
! 225: trap #1 ; Gemdos: Read full program header
! 226: lea 12(sp),sp
! 227: cmp.l #$1c,d0
! 228: bne lr_err_free
1.1.1.7 root 229:
230: lea 8(a5),a4
231: move.l a5,d0
232: add.l #$100,d0
233: move.l d0,(a4)+ ; text start
234: move.l 2(a3),d0
235: move.l d0,(a4)+ ; text length
236: add.l 8(a5),d0
237: move.l d0,(a4)+ ; data start
238: move.l 6(a3),(a4)+ ; data length
239: add.l 6(a3),d0
240: move.l d0,(a4)+ ; bss start
241: move.l 10(a3),(a4)+ ; bss length
242:
243: add.l 10(a3),d0
244: cmp.l 4(a5),d0 ; is the TPA big enough?
1.1.1.8 ! root 245: bhi tpa_not_ok
1.1.1.7 root 246:
247: move.l a5,d0
248: add.l #$80,d0
249: move.l d0,32(a5) ; default DTA always points to cmd line space!
250:
251: move.l 24(a5),a4
252: add.l 14(a3),a4 ; add symtab length => a4 points to reloc table
1.1.1.8 ! root 253: move.w 26(a3),a3 ; a3 is now the absflag (0 means reloc)
1.1.1.7 root 254:
255: pea 256(a5)
256: pea $7fffffff
1.1 root 257: move d6,-(sp)
1.1.1.3 root 258: move #$3f,-(sp) ; Fread
1.1.1.2 root 259: trap #1 ; Gemdos
1.1.1.7 root 260: lea 12(sp),sp
261:
1.1 root 262: move d6,-(sp)
1.1.1.3 root 263: move #$3e,-(sp) ; Fclose
1.1.1.2 root 264: trap #1 ; Gemdos
1.1 root 265: addq #4,sp
1.1.1.7 root 266:
1.1.1.8 ! root 267: move.w a3,d1
! 268: tst.w d1 ; check absflag
! 269: bne.s relocdone
! 270:
1.1 root 271: move.l 8(a5),a3
272: move.l a3,d0
1.1.1.2 root 273:
1.1.1.3 root 274: ; Get first offset of the relocation table. Since A4 seems sometimes not
275: ; to be word aligned (if symbol table length is uneven), we have to read
276: ; byte by byte...
1.1.1.8 ! root 277: move.b (a4),d1
1.1.1.3 root 278: clr.b (a4)+
1.1.1.8 ! root 279: lsl.w #8,d1
! 280: move.b (a4),d1
1.1.1.3 root 281: clr.b (a4)+
1.1.1.8 ! root 282: swap d1
! 283: move.b (a4),d1
1.1.1.3 root 284: clr.b (a4)+
1.1.1.8 ! root 285: lsl.w #8,d1
! 286: move.b (a4),d1
1.1.1.3 root 287: clr.b (a4)+
288:
1.1.1.8 ! root 289: tst.l d1
1.1 root 290: beq.s relocdone
1.1.1.8 ! root 291: adda.l d1,a3
! 292: moveq #0,d1
1.1.1.3 root 293: relloop0:
294: add.l d0,(a3)
295: relloop:
1.1.1.8 ! root 296: move.b (a4),d1
1.1.1.7 root 297: clr.b (a4)+ ; Some programs like GFA-Basic expect a clear memory
1.1.1.8 ! root 298: tst.b d1
1.1.1.3 root 299: beq.s relocdone
1.1.1.8 ! root 300: cmp.b #1,d1
1.1.1.3 root 301: bne.s no254
302: lea 254(a3),a3
303: bra.s relloop
304: no254:
1.1.1.8 ! root 305: adda.w d1,a3
1.1.1.3 root 306: bra.s relloop0
1.1.1.2 root 307:
1.1 root 308: relocdone:
309: move.l 28(a5),d0
310: beq.s cleardone
311: move.l 24(a5),a0
312: clear:
313: clr.b (a0)+
314: subq.l #1,d0
315: bne.s clear
316: cleardone:
317: move.l a5,d0
1.1.1.8 ! root 318: movem.l (sp)+,a3-a5/d6
1.1 root 319: rts
1.1.1.4 root 320:
1.1.1.8 ! root 321: tpa_not_ok:
! 322: move.l #-39,d0 ; Error code: Not enough memory
! 323: lr_err_free:
! 324: move.l d0,-(sp)
1.1.1.7 root 325: move.l a5,-(sp)
326: move.w #$49,-(sp) ; Mfree
327: trap #1 ; Release "pexeced" memory
328: addq.l #6,sp
1.1.1.8 ! root 329: move.l (sp)+,d0
! 330: load_reloc_error:
! 331: move.w d6,-(sp)
! 332: move.l d0,d6 ; Save error code
! 333: move.w #$3e,-(sp) ; Fclose
! 334: trap #1 ; Gemdos
! 335: addq #4,sp
! 336: move.l d6,d0 ; Restore error code
! 337: lr_err_out:
! 338: movem.l (sp)+,a3-a5/d6
! 339: addq #4,sp ; Drop return address
! 340: bra gohome ; Abort
1.1.1.7 root 341:
1.1.1.4 root 342:
343:
344: ; This code is called during TOS' boot sequence.
345: ; It gets a pointer to the Line-A variables and uses an illegal opcode
346: ; to run our system initialization code in OpCode_SysInit().
347: sys_init:
348: dc.w $A000 ; Line-A init (needed for VDI resolutions)
349: dc.w SYSINIT_OPCODE ; Illegal opcode to call OpCode_SysInit()
350: rts
351:
352:
353:
354: ; This code is run when the user starts the HATARI.PRG
355: ; in the cartridge. It simply displays some information text.
356: infoprgstart:
357: pea hatarix32(pc)
358: move.w #32,-(sp)
359: trap #14 ; Dosound - play some music :-)
360: addq.l #6,sp
361:
362: pea infotext(pc)
363: move.w #9,-(sp)
364: trap #1 ; Cconws - display the information text
365: addq.l #6,sp
366:
367: move.w #7,-(sp)
368: trap #1 ; Crawcin - wait for a key
369: addq.l #2,sp
370:
371: clr.w -(sp)
372: trap #1 ; Pterm0
373:
374:
375: infotext:
376: dc.b 27,'E',13,10
377: dc.b ' =========================',13,10
378: dc.b ' Hatari keyboard shortcuts',13,10
379: dc.b ' =========================',13,10
380: dc.b 13,10
381: dc.b ' F11 : toggle fullscreen/windowed mode',13,10
382: dc.b ' F12 : activate the setup GUI of Hatari',13,10
383: dc.b 13,10
384: dc.b 'All other shortcuts are activated by',13,10
385: dc.b 'pressing AltGr or Right-Alt or Meta key',13,10
386: dc.b 'together with one of the following keys:',13,10
387: dc.b 13,10
388: dc.b ' a : Record animation',13,10
389: dc.b ' g : Grab a screenshot',13,10
390: dc.b ' i : Leave full screen & iconify window',13,10
391: dc.b ' j : joystick via key joystick on/off',13,10
392: dc.b ' m : mouse grab',13,10
393: dc.b ' r : warm reset of the ST',13,10
394: dc.b ' c : cold reset of the ST',13,10
395: dc.b ' s : enable/disable sound',13,10
396: dc.b ' q : quit the emulator',13,10
397: dc.b ' x : toggle normal/max speed',13,10
398: dc.b ' y : enable/disable sound recording',13,10
399: dc.b 0
400:
401:
402: hatarix32:
1.1.1.5 root 403: ibytes 'cart_mus.x32'
1.1.1.4 root 404:
405:
406: infoprgend:
407:
408: END
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.