title testrsx.asm (c) 1988 Bridger Mitchell ; name RSX240 ;"RSX" required .xlist ; This rsx just prints an identifying message when called: ; ; ld c,240 ;0F0h ; call 5 ; OURCODE equ 240 ;0F0h ; ; ; *---------- Plu*Perfect Systems RSX Extended Header----------------* ;/ \ ; ; The rsx code goes in the CSEG (code segment). ; CSEG ; rsx: jp rsxstart ; 00 jp rsxwb ; +03 jp rsxremove ; +06 rsxwba: dw $-$ ; +09 rsxprot:dw rsx ; +0B dw rsxname ; +0D rsxnext:jp $-$ ; -> next wb or ccp entry ; +0F ; next: jp $-$ ; -> next rsx or bdos ; +12 nextwb: dw $-$ ; +15 ;\ / ; *-----------------------------------------------------------------* ; rsxname: db 'TESTRSX',0 ; nul-terminated name of rsx. ; ; ; The BDOS intercept ; rsxstart: ld a,c cp OURCODE ; if not our function jr nz,next ; .. pass on to next rsx or bdos ld de,ourmsg ; do our thing. ld c,9 call next ; by calling the bdos via the rsx chain ret ; custom_remove: ret ; ; Just to illustrate the use of the data segment, ; let's put the message string there. It will be loaded ; immediately above the code segment. ; DSEG ; ourmsg: db 0dh,0ah,'TESTRSX is active.$' ; CSEG ; ; ; *---------------- Standard RSX Code -----------------------------* ;/ \ ; ; The warm-boot intercept. ; rsxwb: .new call fix0001 ; ensure correct page 0 ld hl,(bios+4) ; does bios wb addr ld de,rsx+3 ; point at us? or a sbc hl,de jr nz,1$ ; no, we're not the bottom rsx ld hl,(rsxprot) ; we are, set our protect address ld (0006),hl 1$: ld bc,(0004h) ; get c = logged du for ccp jp rsxnext ; in case we're top rsx ; ; ; The removal routine. ; rsxremove: call custom_remove ; do extra restoration for this rsx ; ld hl,(nextwb) ; get saved original warmboot addr ld (bios+4),hl ; and restore it to bios jmp vector ; ; When the caller terminates to a warmboot, ; the next module (or bios, if none), will correct 0006. ; ; Set CY flag to inform removal tool that this routine ; has taken action. (Some RSX's are not self-removing). ; fix0001:ld hl,(rsxwba) ; restore (0001) in case an errant ld (0001h),hl ; application has tampered with it scf ; set CY to signal success ret ; ; ; Before loading an RSX, JetLDR will first check for protected memory. ; If it detects memory protected by a non-RSX header (e.g. a debugger) ; it will cancel the load. Otherwise, JetLDR will call any ; code in the _INIT_ named common, after the rsx module has been ; loaded and relocated. This code will be located in non-protected ; memory, and takes no space in the RSX. ; ; Return parameter: A = 0 indicates a good installation ; A = ABORT = 0FFh = not installed ; common /_INIT_/ ; ; Install the rsx. This code is standard for all rsx's, ; except for: ; custom_init ; custom_twin ; init: ld hl,(0006) ; hl = possible rsx, or bdos ld c,0 ; initialize count of rsx's ; initlp: push hl ; stack (possible) rsx base address ld de,09 ; if candidate is an rsx add hl,de ; ..the wbaddr will be here ld e,(hl) ; get address inc hl ld d,(hl) ld hl,(0001) ; and compare or a sbc hl,de pop hl jr nz,inittop ; warmboot addr not there, stop looking ; ; we have an rsx in memory, is it our twin? ; inc c ; count an rsx found push hl call ckname pop hl jr z,twin ; ld de,0Fh+1 ; that rsx was't a twin, check for more add hl,de ; get addr of next rsx's wboot jmp ld a,(hl) inc hl ld h,(hl) ld l,a dec hl ; back up to head of that next rsx dec hl dec hl jr initlp ; now check that rsx ; ; we're at the top of the (possibly empty) rsx chain ; inittop: inc c ; any rsx's found? dec c ld hl,ccp+3 ; prepare to use ccp entry address jr z,setnext ; ..no ; ld hl,(0006) ; yes, use bottom rsx's address ; setnext: ld (rsxnext+1),hl ; save the next addr ; in the rsx chain to bdos/ccp ; ; install the rsx into the running system ; ld hl,(bios+4) ; save the bios's wb addr ld (nextwb),hl ; in the header ld hl,rsx+3 ; point the bios wb jump ld (bios+4),hl ; at the rsx wb vector ld hl,bios+3 ; store wb addr ld (rsx+09),hl ; in rsx header word ld hl,(0006) ; get addr of next rsx or bdos ld (next+1),hl ; and install it ld hl,rsx ; finally, protect the rsx ld (0006),hl ; call custom_init ; take care of extras ret ; ckname: ld de,0dh ; offset to candidate rsx name pointer add hl,de ld a,(hl) ; get address inc hl ld h,(hl) ld l,a ld de,rsxname ; compare to our name ckname1:ld a,(de) cp (hl) ret nz inc (hl) ; candidate must be nul-terminated dec (hl) jr nz,ckname2 or a ; ..at our same byte ret ckname2:inc hl inc de jr ckname1 ; ; Handle the case of a previously-loaded copy of this RSX. ; twin: call custom_twin ret ;\ / ; *-----------------------------------------------------------------* ; ; Custom initialization code goes here. ; ; ; Do the particular patches for this RSX. ; Note: this code is in the _INIT_ segment. custom_init: custom_twin: ret ; Include identification info in the REL image. ; JetLDR will display the bytes up to the first NUL byte ; when the RSX is loaded. ; ; common /_ID_/ ; db 'Very simple test RSX:' db 13,10,'Print message on bdos function 240' db 0 ; Include whatever other named-commons are needed for this RSX. ; JetLDR will resolve these labels for us. ; common /_BIOS_/ bios equ $ common /_CCP_/ ccp equ $ end ;testrsx.asm