From 2d04cacc5322951f187bb17e017c12920ac8ebe2 Mon Sep 17 00:00:00 2001 From: Mark Zbikowski Date: Thu, 25 Apr 2024 21:24:10 +0100 Subject: MZ is back! --- v4.0/src/INC/MSHALO.ASM | 247 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 v4.0/src/INC/MSHALO.ASM (limited to 'v4.0/src/INC/MSHALO.ASM') diff --git a/v4.0/src/INC/MSHALO.ASM b/v4.0/src/INC/MSHALO.ASM new file mode 100644 index 0000000..65b46d5 --- /dev/null +++ b/v4.0/src/INC/MSHALO.ASM @@ -0,0 +1,247 @@ +; SCCSID = @(#)ibmhalo.asm 1.1 85/04/10 +; On 2K (800h) boundaries beginning at address C0000h and ending at EF800h +; there is a header that describes a block of rom program. This header +; contains information needed to initialize a module and to provide PCDOS +; with a set of reserved names for execution. +; +; This header has the following format: +; +; rom_header STRUC +; Signature1 DB 55h +; Signature2 DB AAh +; rom_length DB ? ; number of 512 byte pieces +; init_jmp DB 3 dup (?) +; name_list name_struc <> +; rom_header ENDS +; +; name_struc STRUC +; name_len DB ? +; name_text DB ? DUP (?) +; name_jmp DB 3 DUP (?) +; name_struc ENDS +; +; The name list is a list of names that are reserved by a particular section +; of a module. This list of names is terminated by a null name (length +; is zero). +; +; Consider now, the PCDOS action when a user enters a command: +; +; COMMAND.COM has control. +; o If location FFFFEh has FDh then +; o Start scanning at C0000h, every 800h for a byte 55h followed +; by AAh, stop scan if we get above or = F0000H +; o When we've found one, compare the name entered by the user +; with the one found in the rom. If we have a match, then +; set up the environment for execution and do a long jump +; to the near jump after the found name. +; o If no more names in the list, then continue scanning the module +; for more 55h followed by AAh. +; o We get to this point only if there is no matching name in the +; rom. We now look on disk for the command. +; +; This gives us the flexibility to execute any rom cartridge without having +; to 'hard-code' the name of the cartridge into PCDOS. Rom modules that +; want to be invisible to the DOS should not have any names in their lists +; (i.e. they have a single null name). +; +; Consider a new release of BASIC, say, that patches bugs in the ROM version. +; Clearly this version will be available on disk. How does a user actually +; invoke this new BASIC?? He cannot call it BASIC on the disk because the +; EXEC loader will execute the ROM before it even looks at the disk! Only +; solution: +; +; o Keep things consistent and force the user to have his software named +; differently from the ROM names (BASIC1, BASIC2, etc). + +rom_header STRUC + Signature1 DB ? + Signature2 DB ? + rom_length DB ? + init_jmp DB 3 dup (?) + name_list DB ? +rom_header ENDS + +name_struc STRUC + name_len DB ? + name_text DB 1 DUP (?) + name_jmp DB 3 DUP (?) +name_struc ENDS + +ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING + +; +; Check for IBM PC Jr rom cartrides. DS:DX is a pointer to name +; +ROM_SCAN: + PUSH ES + PUSH SI + PUSH DI + PUSH CX + PUSH AX + PUSH BX +; +; check for PC Jr signature in rom +; + MOV AX,0F000h + MOV ES,AX + CMP BYTE PTR ES:[0FFFEh],0FDh + JZ SCAN_IT +NO_ROM: + CLC +ROM_RET: + POP BX + POP AX + POP CX + POP DI + POP SI + POP ES + RET +SCAN_IT: +; +; start scanning at C000 +; + MOV AX,0C000h +SCAN_ONE: + MOV ES,AX + XOR DI,DI +SCAN_MODULE: +; +; check for a valid header +; + CMP WORD PTR ES:[DI],0AA55h + JZ SCAN_LIST + ADD AX,080h +SCAN_END: + CMP AX,0F000h + JB SCAN_ONE + JMP NO_ROM +; +; trundle down list of names +; +SCAN_LIST: + MOV BL,ES:[DI].rom_length ; number of 512-byte jobbers + XOR BH,BH ; nothing in the high byte + SHL BX,1 + SHL BX,1 ; number of paragraphs + ADD BX,7Fh + AND BX,0FF80h ; round to 2k + + MOV DI,name_list +SCAN_NAME: + MOV CL,ES:[DI] ; length of name + INC DI ; point to name + XOR CH,CH + OR CX,CX ; zero length name + JNZ SCAN_TEST ; nope... compare + ADD AX,BX ; yep, skip to next block + JMP SCAN_END +; +; compare a single name +; +SCAN_TEST: + MOV SI,DX + INC SI + REPE CMPSB ; compare name + JZ SCAN_FOUND ; success! +SCAN_NEXT: + ADD DI,CX ; failure, next name piece + ADD DI,3 + JMP SCAN_NAME +; +; found a name. save entry location +; +SCAN_FOUND: + CMP BYTE PTR DS:[SI],'?' + JZ SCAN_SAVE + CMP BYTE PTR DS:[SI],' ' + JNZ SCAN_NEXT +SCAN_SAVE: + MOV [rom_cs],ES + MOV [ROM_ip],DI + STC + JMP ROM_RET + +; +; execute a rom-placed body of code. allocate largest block +; +ROM_EXEC: + MOV BX,0FFFFh + MOV AH,ALLOC + INT int_command + MOV AH,ALLOC + INT int_command + PUSH BX + PUSH AX +; +; set terminate addresses +; + MOV AX,(set_interrupt_vector SHL 8) + int_terminate + PUSH DS + MOV DS,[RESSEG] + ASSUME DS:RESGROUP + MOV DX,OFFSET RESGROUP:EXEC_WAIT + INT int_command + MOV DX,DS + MOV ES,DX + ASSUME ES:RESGROUP + POP DS + ASSUME DS:NOTHING +; +; and create program header and dup all jfn's +; + POP DX + MOV AH,DUP_PDB + INT int_command +; +; set up dma address +; + MOV DS,DX + MOV DX,080h + MOV AH,SET_DMA + INT int_command +; +; copy in environment info +; + MOV AX,[ENVIRSEG] + MOV DS:[PDB_environ],AX +; +; set up correct size of block +; + POP BX ; BX has size, DS has segment + MOV DX,DS + ADD DX,BX + MOV DS:[PDB_block_len],DX +; +; change ownership of block +; + MOV DX,DS + DEC DX + MOV DS,DX + INC DX + MOV DS:[arena_owner],DX + MOV DS,DX +; +; set up correct stack +; + CMP BX,1000h + JB GOT_STACK + XOR BX,BX +GOT_STACK: + MOV CL,4 + SHL BX,CL + MOV DX,DS + MOV SS,DX + MOV SP,BX + XOR AX,AX + PUSH AX +; +; set up initial registers and go to the guy +; + NOT AX + PUSH [ROM_CS] + PUSH [ROM_IP] + MOV ES,DX +ASSUME ES:NOTHING +FOOBAR PROC FAR + RET +FOOBAR ENDP -- cgit v1.2.3