home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / RCPM / LUXI80.LBR / MAKELUX.AZM / MAKELUX.ASM
Assembly Source File  |  2000-06-30  |  9KB  |  446 lines

  1.     ORG    00100H
  2. WBOOT    EQU    00000H
  3. BDOS    EQU    00005H
  4. DEFFCB    EQU    00080H
  5. ;
  6. CR    EQU    00DH
  7. LF    EQU    00AH
  8. ;
  9. CHROUT    EQU    002H
  10. OPNFIL    EQU    00FH
  11. CLSFIL    EQU    010H
  12. FNDFIL    EQU    011H
  13. DELFIL    EQU    013H
  14. RDREC    EQU    014H
  15. WRTREC    EQU    015H
  16. MAKFIL    EQU    016H
  17. SETDMA    EQU    01AH
  18. ;
  19. START:    LXI    H,0
  20.     DAD    SP
  21.     SHLD    TMPSTK        ;Save STACK for later (self-modifying code)
  22.     LXI    SP,LOADER+080H
  23. ;
  24.     LXI    D,DEFFCB
  25.     MVI    C,SETDMA    ;Use default FCB for DIR searches
  26.     CALL    BDOS
  27. ;
  28.     LXI    D,CO0FCB
  29.     MVI    C,FNDFIL
  30.     CALL    BDOS        ;Go search for LUX.CO0
  31.     INR    A        ;Is it there?
  32.     JNZ    FNDCO1        ;Yes
  33.     CALL    ILPRT
  34.     DB    'Can''t find LUX.CO0 - Aborting',CR,LF,0
  35.     JMP    EXIT        ;Nope - display error and return
  36. ;
  37. FNDCO1:    LXI    D,CO1FCB
  38.     MVI    C,FNDFIL
  39.     CALL    BDOS        ;Go search for LUX.CO1
  40.     INR    A        ;Is it there?
  41.     JNZ    OPNCO0        ;Yes
  42.     CALL    ILPRT
  43.     DB    'Can''t find LUX.CO1 - Aborting',CR,LF,0
  44.     JMP    EXIT        ;Nope - display error and return
  45. ;
  46. OPNCO0:    LXI    D,CO0FCB
  47.     MVI    C,OPNFIL
  48.     CALL    BDOS        ;Open LUX.CO0 for input
  49.     CPI    0FFH        ;Open OK?
  50.     JNZ    GETCO0        ;Yes - go read it then
  51.     CALL    ILPRT
  52.     DB    'LUX.CO0 open error',CR,LF,0
  53.     JMP    EXIT        ;Nope - display error and return
  54. ;
  55. GETCO0:    LXI    H,RDSPC
  56.     LXI    D,080H
  57. GETC0A:    DAD    D        ;Calc next sector address
  58.     XCHG
  59.     PUSH    D
  60.     PUSH    H
  61.     MVI    C,SETDMA
  62.     CALL    BDOS        ;Tell BDOS where to put LUX.CO0 sector
  63.     LXI    D,CO0FCB
  64.     MVI    C,RDREC
  65.     CALL    BDOS        ;Read a record of LUX.CO0
  66.     POP    H
  67.     POP    D
  68.     XCHG
  69.     ORA    A        ;All of file in yet?
  70.     JZ    GETC0A        ;Nope - go read another sector
  71.     SHLD    CO0END        ;Yes. Save "end of LUX.CO0" pointer
  72. ;
  73.     LXI    D,CO1FCB
  74.     XRA    A
  75.     STA    CO1EXT
  76.     STA    CO1REC        ;Init current extent and record to read
  77.     MVI    C,OPNFIL
  78.     CALL    BDOS        ;Open LUX.CO1
  79.     CPI    0FFH        ;Open OK?
  80.     JNZ    GETCO1        ;Yes
  81.     CALL    ILPRT
  82.     DB    'LUX.CO1 open error',CR,LF,0
  83.     JMP    EXIT        ;Nope - display error and return
  84. ;
  85. GETCO1:    LXI    H,CO0DAT    ;<HL> points to LUX.CO0 data
  86.     LXI    D,LNKMAP    ;<DE> points to our link map
  87. ;
  88. GETC1A:    XRA    A        ;Clear <A>
  89.     STAX    D        ;Zero out a byte of the link map
  90.     MVI    B,008H        ;Prepare to process 8 bytes of LUX.CO0
  91. ;
  92. GETC1B:    CALL    GETBYT        ;Fetch a byte of LUX.CO1
  93.     JC    MAKLEN        ;Jump if end of file on LUX.CO1
  94.     CMP    M        ;Is this byte of LUX.CO1 same as LUX.CO0?
  95.     JZ    GETC1C        ;Yes - so it's absolute
  96.     STC            ;No - it's relative
  97. ;
  98. GETC1C:    LDAX    D
  99.     RAL
  100.     STAX    D        ;Tag the bit corresponding to this byte
  101.     INX    H        ;Next byte of LUX.CO0...
  102.     DCR    B
  103.     JNZ    GETC1B        ;Process all 8 bits of this link map entry
  104.     INX    D        ;Point to next byte of link map
  105.     JMP    GETC1A        ; and do it all over again
  106. ;
  107. MAKLEN:    LHLD    CO0END
  108.     LXI    D,CO0DAT
  109.     MOV    A,L
  110.     SUB    E
  111.     MOV    L,A
  112.     MOV    A,H
  113.     SBB    D
  114.     MOV    H,A        ;Calc length of LUX.CO0 (in <HL>)
  115.     MOV    A,L
  116.     ORA    A        ;Is length of form 0XX00h?
  117.     JZ    MKLEN1        ;Yup
  118.     MVI    L,0
  119.     INR    H        ;Nope, so force it that way (add 128 bytes)
  120. MKLEN1:    SHLD    CO0LEN        ; and save that length away
  121.     LXI    D,LODLEN
  122.     DAD    D        ;Add the length of the loader to LUX.CO0 length
  123.     MOV    A,L
  124.     ORA    A        ;Is length in the form 0XX00h?
  125.     JZ    MKLEN2        ;Yup
  126.     CPI    080H        ;Well then, is it in the form 0XX80?
  127.     JZ    MKLEN2        ;Yup
  128.     MVI    L,0
  129.     INR    H        ;Nope, so force it to be a multiple of sector
  130. ;
  131. MKLEN2:    MVI    B,7
  132. MKLEN3:    MOV    A,H
  133.     RRC
  134.     MOV    H,A
  135.     MOV    A,L
  136.     RAR
  137.     MOV    L,A
  138.     DCR    B
  139.     JNZ    MKLEN3        ;Divide this length by the sector size (080h)
  140. ;    MOV    A,L
  141.     STA    LODKNT        ;Save the sector count
  142. ;
  143.     LXI    D,COMFCB
  144.     MVI    C,DELFIL
  145.     CALL    BDOS        ;Delete any old LUX.COM file
  146.     LXI    D,COMFCB
  147.     MVI    C,MAKFIL
  148.     CALL    BDOS        ;Create a new LUX.COM file
  149.     CPI    0FFH        ;Could we create the file?
  150.     JNZ    WRTCOM        ;Yes - go write it then
  151.     CALL    ILPRT
  152.     DB    'No directory space',CR,LF,0
  153.     JMP    EXIT        ;Nope - display error and return
  154. ;
  155. WRTCOM:    LXI    H,LOADER
  156.     LXI    D,080H
  157.     LDA    LODKNT
  158.     MOV    B,A        ;Sector count to <B>
  159. ;
  160. WTCOM1:    DAD    D        ;Calc next sector address
  161.     XCHG
  162.     PUSH    B
  163.     PUSH    D
  164.     PUSH    H        ;We use all regs, so save em
  165.     MVI    C,SETDMA
  166.     CALL    BDOS        ;Tell BDOS where to get the data
  167.     LXI    D,COMFCB
  168.     MVI    C,WRTREC
  169.     CALL    BDOS        ;Write a record of LUX.COM
  170.     POP    H
  171.     POP    D
  172.     POP    B        ;Get all our regs back
  173. ;
  174.     XCHG
  175.     ORA    A        ;Did we get an error on that last write?
  176.     JNZ    WTCOM2        ;Yes - disk must be full then
  177.     DCR    B
  178.     JNZ    WTCOM1        ;Nope - go write another record then
  179. ;
  180.     LXI    D,COMFCB
  181.     MVI    C,CLSFIL
  182.     CALL    BDOS        ;Go close the file now
  183.     CPI    0FFH        ;Sucessful close?
  184.     JNZ    EXIT        ;Yes - all done. LUX.COM is ready!!!
  185. ;
  186. WTCOM2:    CALL    ILPRT
  187.     DB    'Disk full - aborting',CR,LF,0
  188.  ;
  189.     LXI    D,COMFCB
  190.     MVI    C,CLSFIL
  191.     CALL    BDOS        ;Try to close the file again
  192.     LXI    D,COMFCB
  193.     MVI    C,DELFIL
  194.     CALL    BDOS        ;Delete the bad file
  195. EXIT:    LXI    SP,$-$
  196. TMPSTK    EQU    $-2
  197.     RET            ;We now return you to the system
  198. ;
  199. GETBYT:    PUSH    B
  200.     PUSH    D
  201.     PUSH    H
  202. GTBYT1:    LDA    BYTKNT
  203.     INR    A
  204.     STA    BYTKNT
  205.     CPI    081H
  206.     JZ    GETREC
  207.     LHLD    LODADR
  208.     MOV    A,M
  209.     INX    H
  210.     SHLD    LODADR
  211.     POP    H
  212.     POP    D
  213.     POP    B
  214.     ORA    A
  215.     RET
  216. ;
  217. GETREC:    XRA    A
  218.     STA    BYTKNT
  219.     LXI    H,DEFFCB
  220.     SHLD    LODADR        ;Reset data address
  221.     XCHG            ;<DE> gets default FCB address
  222.     MVI    C,SETDMA
  223.     CALL    BDOS
  224.     LXI    D,CO1FCB
  225.     MVI    C,RDREC
  226.     CALL    BDOS
  227.     ORA    A
  228.     JZ    GTBYT1
  229.     POP    H
  230.     POP    D
  231.     POP    B
  232.     STC
  233.     RET
  234. ;
  235. ILPRT:    XTHL
  236. ILPRT1:    MOV    A,M
  237.     ORA    A
  238.     JZ    ILPRT2
  239.     CALL    CTYPE
  240.     INX    H
  241.     JMP    ILPRT1
  242. ;
  243. ILPRT2:    XTHL
  244.     RET
  245. ;
  246. CTYPE:    PUSH    PSW
  247.     PUSH    B
  248.     PUSH    D
  249.     PUSH    H
  250.     ANI    07FH
  251.     MOV    E,A
  252.     MVI    C,CHROUT
  253.     CALL    BDOS
  254.     POP    H
  255.     POP    D
  256.     POP    B
  257.     POP    PSW
  258.     RET
  259. ;
  260. LODADR:    DW    0
  261. BYTKNT:    DB    128
  262. LODKNT:    DB    0
  263. CO0END:    DW    0
  264. CO0FCB:    DB    0        ;Current drive
  265.     DB    'LUX     CO0'    ;File name
  266.     DB    0,0,0,0,0,0,0,0    ;Rest of FCB
  267.     DB    0,0,0,0,0,0,0,0
  268.     DB    0,0,0,0,0,0,0,0
  269. CO1FCB:    DB    0        ;Current drive
  270.     DB    'LUX     CO1'    ;File name
  271. CO1EXT:    DB    0,0,0,0,0,0,0,0
  272.     DB    0,0,0,0,0,0,0,0
  273.     DB    0,0,0,0
  274. CO1REC:    DB    0,0,0,0
  275. COMFCB:    DB    0               ;Current drive
  276.     DB    'LUX     COM'    ;File name
  277.     DB    0,0,0,0,0,0,0,0    ;Rest of FCB
  278.     DB    0,0,0,0,0,0,0,0
  279.     DB    0,0,0,0,0,0,0,0
  280. ;
  281. ;    Start the loader at 0XX00h just to make it look nice
  282. ;
  283.     ORG    ($+0FFH) AND 0FF00h
  284. ;
  285. ;    The following loader is placed in the beginning of LUX.COM,
  286. ;    followed by the LINK MAP and finally, LUX.CO0.  The loader
  287. ;    examines top of memory, allows enough space for LUX to
  288. ;    reside in, and relocates LUX.CO0 (the 0 absolute version)
  289. ;    to this area, changing all relative bytes to absolute by
  290. ;    adding in the offset of where LUX.CO0 is being moved.  The
  291. ;    loader accomplishes this by using the LINK MAP created above.
  292. ;
  293. OFFSET    EQU    $-100H
  294. LOADER    EQU    $-080H
  295. ;
  296. LODBEG    EQU    $
  297.     CALL    LOCATE        ;Locate a place for LUX and link it there
  298. ;
  299.     LHLD    C0LENR
  300.     MOV    B,H
  301.     MOV    C,L
  302.     LHLD    LDADDR
  303.     XCHG
  304.     LXI    H,C0DATR
  305. ;
  306. TMP010    EQU    $-OFFSET
  307.     MOV    A,M
  308.     INX    H
  309.     XCHG
  310.     MOV    M,A
  311.     INX    H
  312.     XCHG
  313.     DCR    C
  314.     JNZ    TMP010
  315.     DCR    B
  316.     JNZ    TMP010        ;Move LUX to our new-found area
  317. ;
  318.     LHLD    LDADDR
  319.     PCHL            ; and go run it!!!
  320. ;
  321. LOCATE    EQU    $-OFFSET
  322.     LDA    BDOS+1
  323.     CPI    006H        ;Has LUX modified BIOS vectors already?
  324.     JNZ    LINK        ;Yes - just link it then
  325. ;
  326.     LHLD    WBOOT+1
  327.     MVI    B,004H        ;Prepare to find a place for LUX to reside
  328. ;
  329. LOCAT1:    EQU    $-OFFSET
  330.     INX    H        ;Skip the JMP opcode byte
  331.     MOV    E,M
  332.     INX    H
  333.     MOV    D,M        ;<DE> has address of a BIOS routine
  334.     INX    H        ;<HL> points to next BIOS jump vector
  335. ;    PUSH    H        ; so save it
  336. ;
  337.     MOV    A,L
  338.     SUB    E
  339.     MOV    A,H
  340.     SBB    D        ;Is this BIOS routine below its jump vector?
  341. ;    POP    H
  342.     JNC    LINK        ;Yes - use it then for top of memory
  343.     DCR    B
  344.     JNZ    LOCAT1        ;No - better find another then
  345. ;
  346. ;    None of the vectors reference routine below their vectors, so
  347. ;    we can assume all of memory below the Warm Start vector is free
  348. ;    for use.
  349. ;
  350.     LHLD    WBOOT+1        ;Get address of Warm Boot vector
  351.     LXI    D,0F203H
  352.     DAD    D        ;Point back to where BDOS vectors should be
  353. ;
  354.     XCHG
  355.     LHLD    BDOS+1        ;Get BDOS vector address
  356.     XCHG            ; into <DE>
  357.     MOV    A,E
  358.     CMP    L        ;Are the two the same?
  359.     JNZ    LINK        ;Nope. Better use BDOS address then
  360.     MOV    A,D
  361.     CMP    H        ;Are they *really* the same?
  362.     JNZ    LINK        ;Nope. Better use BDOS address then
  363.     JMP    LINK1        ;Yes, so we know BDOS is safe to use
  364. ;
  365. LINK    EQU    $-OFFSET
  366.     LHLD    BDOS+1
  367.     DCR    H        ;Use BDOS address - 256 for safety
  368.     JMP    LINK2
  369. ;
  370. LINK1    EQU    $-OFFSET
  371.     LHLD    BDOS+1        ;Safe to use BDOS address directly
  372. LINK2    EQU    $-OFFSET
  373.     MVI    L,0        ;Start at an even boundary
  374. ;
  375.     XCHG
  376.     LHLD    C0LENR        ;Get LUX length
  377.     XCHG            ; into <DE>
  378.     MOV    A,L
  379.     SUB    E
  380.     MOV    L,A
  381.     MOV    A,H
  382.     SBB    D
  383.     MOV    H,A        ;Subtract LUX length from our address
  384.     SHLD    LDADDR        ; which becomes the load point
  385. ;
  386.     MOV    C,H        ;<C> has LOAD offset for linking
  387.     LHLD    C0LENR
  388.     XCHG            ;<DE> has LUX length
  389.     LXI    H,LKMAPR
  390.     SHLD    IXPTR        ;<IXPTR> has LINK MAP address
  391.     LXI    H,C0DATR    ;<HL> has LUX address
  392. ;
  393. LINK3    EQU    $-OFFSET
  394.     MVI    B,8        ;Prepare for 8 bytes of processing
  395. LINK4    EQU    $-OFFSET
  396.     PUSH    H
  397.     LHLD    IXPTR        ;Get <IXPTR>
  398.     MOV    A,M
  399.     RAL            ;Is this byte absolute or relative
  400.     MOV    M,A
  401.     POP    H
  402.     JNC    LINK5        ;Absolute - don't offset it then
  403.     MOV    A,M
  404.     ADD    C
  405.     MOV    M,A        ;Relative - offset it by the load address
  406. LINK5    EQU    $-OFFSET
  407.     INX    H        ;Next byte of raw LUX code
  408.     DCX    D
  409.     MOV    A,E
  410.     ORA    D        ;Done all of LUX yet?
  411.     RZ            ;Yes - linking is complete
  412.     DCR    B
  413.     JNZ    LINK4        ;No - go do another byte of LUX
  414. ;
  415.     PUSH    H
  416.     LHLD    IXPTR
  417.     INX    H        ;Point to next byte of LINK MAP
  418.     SHLD    IXPTR
  419.     POP    H
  420.     JMP    LINK3        ; and go process 8 more bytes of LUX
  421. ;
  422. C0LENR    EQU    $-OFFSET
  423. CO0LEN:    DW    0
  424. LDADDR    EQU    $-OFFSET
  425.     DW    0
  426. IXPTR    EQU    $-OFFSET
  427.     DW    0
  428. ;
  429. ;    ADDRESS = 00480h
  430. ;
  431. LKMAPR    EQU    $-OFFSET
  432. LNKMAP:    DS    128
  433.     DS    128
  434.     DS    128
  435.     DS    128
  436.     DS    128
  437.     DS    128
  438. ;
  439. ;    LUX.CO0 follows this program and goes below:
  440. ;
  441. C0DATR    EQU    $-OFFSET
  442. CO0DAT    EQU    $
  443. RDSPC    EQU    CO0DAT-080H
  444. LODLEN    EQU    CO0DAT-LODBEG
  445.     END
  446.