    ;; This program will dump the CPC+ System cartridge.
    ;;
    ;; This program will save 8 files.
    ;; CARTROM1.BIN, CARTROM2.BIN, CARTROM3.BIN, CARTROM4.BIN,
    ;; CARTROM5.BIN, CARTROM6.BIN, CARTROM7.BIN and CARTROM8.BIN
    ;;
    ;; Each file will be 16K. The total data will be 128K.
    ;;
    ;; The files should be joined together into a single binary file to
    ;; create the complete ROM image. Join the files in numeric order:
    ;; e.g. CARTROM1.BIN+CARTROM2.BIN+CARTROM3.BIN+...+CARTROM8.BIN
    ;;
    ;; This final binary file can be converted to a .CPR cartridge file for use
    ;; with emulators using the BUILDCPR utility.
    ;;
    ;; Kev Thacker, 1997-2002
    ;;
    ;; This source is released under the GNU public license.

    ;; firmware function to enable upper rom (rom will be readable in range &c000-&ffff)
    .kl_u_rom_enable	equ &b900
    ;; firmware function to disable upper rom (rom data can't be read)
    .kl_u_rom_disable equ &b903

    ;; firmware function to open a file for output
    .cas_out_open	equ &bc8c
    ;; firmware function to write a block of data to a file
    .cas_out_direct	equ &bc98
    ;; firmware function to close a file opened for output
    .cas_out_close	equ &bc8f

    ;; NOTE: ROM Data from &4000-&7FFF. Program code starts at &8000.
    ;; Upper ROM can be read in range &c000-&ffff (when activated).
    ;; Firmware area between &A600 (approximatly; depends on ROMs connected) to &bfff.
    ;; Lower firmware area between &0000-&0040.

    org &8000
    nolist

    .save_cart
    ;; There are 8 x 16K blocks in the system cartridge.
    ld b,8

    ;; ROM's with ID's of 128-255 will select a 16K block in the cartridge ROM
    ;; if a cartridge is less than 512K, then more than one ID will select the same
    ;; 16K block of the cartridge ROM. e.g. if the cartridge is 128K, then selections
    ;; 128 and 136 will select the same 16K block.

    ld e,&80

    .save_loop
    push bc

    ;;----------------------------------------------------------------
    ;; disable interrupts - will stop firmware from enabling any roms
    di

    ;;----------------------------------------------------------------
    ;; STAGE 1: Select the rom
    ld c,e
    ld b,&df
    out (c),c

    ;;----------------------------------------------------------------
    ;; STAGE 2: enable rom (rom data now readable in range &c000-&ffff

    ;; enable upper rom
    call kl_u_rom_enable

    ;;----------------------------------------------------------------
    ;; STAGE 3: copy rom data to ram

    ;; copy rom data to ram
    ;; (the firmware will enable the DOS rom in the range &c000-&ffff to write
    ;; the file; therefore we can't keep the rom enabled while reading/writing to
    ;; disc)
    ld hl,&c000
    ld de,&4000
    ld bc,&4000
    ldir

    ;; disable upper rom
    call kl_u_rom_disable

    ;; save rom data
    call save_file

    inc de
    pop bc
    djnz save_loop
    ret

    ;;----------------------------------------------------------

    .save_file
    push hl
    push de

    ld hl,end_filename-1		;; update digit in filename
    inc (hl)

    ld b,end_filename-filename	;; B = length of filename
    ld hl,filename			;; HL = address of filename
    ld de,two_k_buffer		;; DE = address of 2k buffer (not used
    					;; with cas_out_direct)

    call cas_out_open			;; firmware function: open output file
    pop de
    pop hl
    					;; HL = start address
    					;; DE = length
    					;; BC = execution address
    ld bc,0
    ld a,2				;; binary file
    call cas_out_direct		;; firmware function: write a entire block

    call cas_out_close		;; firmware function: close output file
    ret

    ;; the initial filename, this is updated for
    ;; each file saved
    .filename
    defb "CARTROM0"
    .end_filename

    .two_k_buffer equ $+1