HatariWii/src/cart_asm.s

409 lines
9.2 KiB
ArmAsm

; 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
bsr.s find_prog
bsr load_n_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 load_n_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
load_n_reloc:
movem.l a3-a5/d6,-(sp)
clr.w -(sp)
move.l 2(a6),-(sp)
move.w #$3d,-(sp) ; Fopen
trap #1 ; Gemdos
addq #8,sp
move.l d0,d6 ; Keep file handle in d6
tst.l d0
bmi lr_err_out
clr.w -(sp) ; Temporary space for prg header magic
move.l sp,-(sp)
move.l #2,-(sp)
move d6,-(sp)
move #$3f,-(sp) ; Fread
trap #1 ; Gemdos: Read header magic
lea 12(sp),sp
move.w (sp)+,d1
cmp.l #2,d0
bne load_reloc_error
cmp.w #$601a,d1 ; Check program header magic
beq.s hdr_magic_ok
move.l #-66,d0 ; Error code: Invalid PRG format
bra load_reloc_error
hdr_magic_ok:
clr.w -(sp)
move.w d6,-(sp)
move.l #22,-(sp) ; offset of the program flags
move.w #66,-(sp) ; Fseek
trap #1 ; Gemdos: Seek to program flags
lea 10(sp),sp
cmp.l #22,d0
bne load_reloc_error
clr.l -(sp) ; Temporary space for program flags
move.l sp,-(sp)
move.l #4,-(sp)
move d6,-(sp)
move #$3f,-(sp) ; Fread
trap #1 ; Gemdos: Read program flags
lea 12(sp),sp
move.l (sp)+,a3 ; Program flags now in a3
cmp.l #4,d0
bne load_reloc_error
; Let's call Pexec now to create the basepage, first try
; Pexec(7) and if that does not work fall back to mode 5
move.l 10(a6),-(sp)
move.l 6(a6),-(sp)
move.l a3,-(sp) ; program flags in program header
move.w #7,-(sp) ; Create basepage wrt program flags
move.w #$4b,-(sp) ; Pexec (mode 7)
trap #1 ; Gemdos
lea 16(sp),sp
tst.l d0
bpl.s pexec_ok
move.l 10(a6),-(sp)
move.l 6(a6),-(sp)
clr.l -(sp)
move.w #5,-(sp) ; Create basepage
move.w #$4b,-(sp) ; Pexec (mode 5)
trap #1 ; Gemdos
lea 16(sp),sp
tst.l d0
bmi load_reloc_error
pexec_ok:
move.l d0,a5 ; Basepage in a5
clr.w -(sp)
move.w d6,-(sp)
clr.l -(sp) ; Back to the start of the file
move.w #66,-(sp) ; Fseek
trap #1 ; Gemdos: Seek to start of the file
lea 10(sp),sp
tst.l d0
bne lr_err_free
lea 256(a5),a3 ; a3 points now to the program header
move.l a3,-(sp)
move.l #$1c,-(sp)
move d6,-(sp)
move #$3f,-(sp) ; Fread
trap #1 ; Gemdos: Read full program header
lea 12(sp),sp
cmp.l #$1c,d0
bne lr_err_free
lea 8(a5),a4
move.l a5,d0
add.l #$100,d0
move.l d0,(a4)+ ; text start
move.l 2(a3),d0
move.l d0,(a4)+ ; text length
add.l 8(a5),d0
move.l d0,(a4)+ ; data start
move.l 6(a3),(a4)+ ; data length
add.l 6(a3),d0
move.l d0,(a4)+ ; bss start
move.l 10(a3),(a4)+ ; bss length
add.l 10(a3),d0
cmp.l 4(a5),d0 ; is the TPA big enough?
bhi tpa_not_ok
move.l a5,d0
add.l #$80,d0
move.l d0,32(a5) ; default DTA always points to cmd line space!
move.l 24(a5),a4
add.l 14(a3),a4 ; add symtab length => a4 points to reloc table
move.w 26(a3),a3 ; a3 is now the absflag (0 means reloc)
pea 256(a5)
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
move.w a3,d1
tst.w d1 ; check absflag
bne.s relocdone
move.l 8(a5),a3
move.l a3,d0
; 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),d1
clr.b (a4)+
lsl.w #8,d1
move.b (a4),d1
clr.b (a4)+
swap d1
move.b (a4),d1
clr.b (a4)+
lsl.w #8,d1
move.b (a4),d1
clr.b (a4)+
tst.l d1
beq.s relocdone
adda.l d1,a3
moveq #0,d1
relloop0:
add.l d0,(a3)
relloop:
move.b (a4),d1
clr.b (a4)+ ; Some programs like GFA-Basic expect a clear memory
tst.b d1
beq.s relocdone
cmp.b #1,d1
bne.s no254
lea 254(a3),a3
bra.s relloop
no254:
adda.w d1,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
rts
tpa_not_ok:
move.l #-39,d0 ; Error code: Not enough memory
lr_err_free:
move.l d0,-(sp)
move.l a5,-(sp)
move.w #$49,-(sp) ; Mfree
trap #1 ; Release "pexeced" memory
addq.l #6,sp
move.l (sp)+,d0
load_reloc_error:
move.w d6,-(sp)
move.l d0,d6 ; Save error code
move.w #$3e,-(sp) ; Fclose
trap #1 ; Gemdos
addq #4,sp
move.l d6,d0 ; Restore error code
lr_err_out:
movem.l (sp)+,a3-a5/d6
addq #4,sp ; Drop return address
bra gohome ; Abort
; 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