Jump to content

ivop

Members
  • Posts

    3,337
  • Joined

  • Last visited

  • Days Won

    3

Posts posted by ivop

  1. On 4/21/2024 at 6:17 AM, ivop said:

    It's indeed used to find the BDOS entry for applications to call, but it's also used to determine MEMTOP (MSB used only), and sometimes to calculate the beginning of CCP. I have seen code doing a hardcoded BDOS vector - 00806H = start of CCP. For example The Amsterdam Compiler Kit (ACK) does that.

    [snip]

    Also found the code in boot.s in ACK:

      Reveal hidden contents

        ! Now the 'heap'.

        lhld 0x0006              ! BDOS entry point
        lxi d, -0x806            ! offset to start of CCP
        dad d
        shld _cpm_ramtop
     

     

    Found another one. This time in the official DRI's XSUB (eXtended SUBmit):

        lda bdos+1
        cpi 06h
        jnz loaderr

     

    Quote

    Ok.  I've got one of these coming:  https://www.ebay.com/itm/175793498479

     

    It may be here by April 30th.  Another week long delay to see if I really got this thing working.   <sigh>

    Hopefully that one works okay!

     

  2. 5 minutes ago, reifsnyderb said:

    Ok.  I just tried 3 other atr files.  I know these work fine with Altirra.  I am having similar problems with respeqt and the USB cable.  I don't know if it's respeqt, the cable, or something else.

    That's disappointing. I just found this:

     

     

    Perhaps reading works well enough (with retries?) to make a copy to a real floppy? It needs extended memory, but I assume that's not a problem with your 1090 memory expansion :)

     

  3. 13 minutes ago, reifsnyderb said:

    There is no consistent place it's been failing as it varies.  The only thing consistent is that it the system gets farther along when the SIO speed is fast.

    Could you make a sector copy to a real floppy and try that?

     

    Edit: if you have only one real drive, you could boot from that, swap disks, and then press CTRL-C, assuming your CONIN routines passes along <32 characters.

     

  4. 23 minutes ago, reifsnyderb said:

    I could have done JSR SIOV.  But, I figured I'd use the resident disk handler as it's basically the same thing and requires fewer inputs.

    I see. I'd forgotten about that as I always use SIO directly. I just noticed a bug in my CP/M-65 code. DDEVIC always needs to be set to $31, and SIO adds DUNIT to it. Well, they don't support multiple drives yet, so it never failed ;)

     

    Back to your code. I assume write.com fails? After which command does it fail? (make_file, write_sequential, or close?)

     

  5. 1 hour ago, reifsnyderb said:

    All of the disk I/O is going through Atari's Resident Disk Handler.  What is odd is that I've been able to confirm that some of the writes are working.....but not all are working.

     

    Here's the read/write code:

     

    	JSR	DSKINV
    

     

    Shouldn't that be JSR SIOV ? ($E459). You also need to set DBYTLO/HI to 128, and DSTATS data direction.

     

    You could basically copy most of my code from CP/M-65:

    Spoiler

    zproc bios_READ
        lda #$40        ; data direction receive
        sta DSTATS
        lda #SIO_READ_SECTOR
        bne do_SIO
    zendproc

    zproc bios_WRITE
        lda #$80        ; data direction send
        sta DSTATS
        lda #SIO_WRITE_SECTOR

    do_SIO:
        sta DCOMND
        lda #$31
        clc
        adc drive_number
        sta DDEVIC
        and #$0f
        sta DUNIT

        lda dma
        sta DBUFLO
        lda dma+1
        sta DBUFHI

        lda #128
        sta DBYTLO
        lda #0
        sta DBYTHI

        lda sector_num      ; Atari starts counting at sector 1
        clc
        adc #1
        sta DAUX1
        lda sector_num+1
        adc #0
        sta DAUX2

    #ifdef ATARI_XL
        jsr SIOV_wrapper
    #else
        jsr SIOV
    #endif

        lda DSTATS
        cmp #1
        beq status_ok

        sec
        rts

    status_ok:
        clc
        rts
    zendproc
     

     

    • Like 1
  6. Here's a disk image that might help you debugging this problem

     

    Source:

    Spoiler

    #include <stdio.h>
    #include <string.h>
    #include <cpm.h>

    unsigned char buffer[128];

    int main(int argc, char **argv) {
        int i;

        cpm_fcb.ex = cpm_fcb.s1 = cpm_fcb.s2 = cpm_fcb.rc = 0;
        memcpy(&cpm_fcb.f, "FOO     BAR", 11);

        printf("Opening file\n");
        if (cpm_make_file(&cpm_fcb)) {
            printf("Error opening file, file exists?\n");
            return 1;
        }

        printf("Setting DMA\n");
        cpm_set_dma(&buffer);

        printf("Filling buffer\n");
        for (i=0; i<128; i++)
            buffer[i] = i;

        printf("Writing buffer\n");
        if (cpm_write_sequential(&cpm_fcb)) {
            printf("Error writing to disk\n");
            return 1;
        }

        printf("Closing file\n");
        if (cpm_close_file(&cpm_fcb)) {
            printf("Error closing file\n");
            return 1;
        }

        printf("Done.\n");
        return 0;
     

     

    Expected output:

    Spoiler

    64k CP/M vers 2.2

    A>dir foo.bar
    NO FILE
    A>write
    Opening file
    Setting DMA
    Filling buffer
    Writing buffer
    Closing file
    Done.

    A>dir foo.bar
    A: FOO      BAR
    A>dump foo.bar

    0000 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
    0010 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
    0020 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
    0030 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
    0040 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
    0050 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
    0060 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
    0070 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F

     

    Edit: BTW are you sure the disk is writable? I don't know what RespeQt's defaults are. Might be R/O.

     

    writetest.atr

    • Thanks 1
  7. 14 minutes ago, reifsnyderb said:

    Got it.  I just tried the ccp.sys and bdos.sys on my boot disk image and it works.  I can tell it's changed because if I try to get an empty directory the response is no all in caps.   🙂

     

    Great! Just for fun, you could mount my sample bootdisk.atr as drive B: and do DIR there. Then try DUMP DUMP.COM :) And STAT DSK:

     

    Edit: and test writing to disk with PIP FOO.COM=DUMP.COM   and then FOO FOO.COM

     

  8. 1 hour ago, reifsnyderb said:

    Track 3, Sector 1 should be Sector 79 on an Atari disk.  So, that being said, and if my math is correct, sector 79 would start at offset 10112.  The directory should have the user byte and filename first.  So, I am thinking that the directory entries, and possibly files (?) all need shifted by 16 bytes.

    The 16 bytes are the ATR header.

    Also, the 79th sector starts after 3*26=78 sectors, which is 78*128=9984 bytes ($2700). With the ATR header, that's file offset 10000 (0x2710).

     

    From the bootdisk.atr that was made with mkfs.cpm and the diskdefs following your spec (boottrk 3):

    Spoiler

    ....

    000026D0   E5 E5 E5 E5  E5 E5 E5 E5  E5 E5 E5 E5  E5 E5 E5 E5  ................
    000026E0   E5 E5 E5 E5  E5 E5 E5 E5  E5 E5 E5 E5  E5 E5 E5 E5  ................
    000026F0   E5 E5 E5 E5  E5 E5 E5 E5  E5 E5 E5 E5  E5 E5 E5 E5  ................
    00002700   E5 E5 E5 E5  E5 E5 E5 E5  E5 E5 E5 E5  E5 E5 E5 E5  ................
    00002710   00 44 55 4D  50 20 20 20  20 43 4F 4D  00 00 00 04  .DUMP    COM....
    00002720   02 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
    00002730   00 53 54 41  54 20 20 20  20 43 4F 4D  00 01 00 29  .STAT    COM...)
    00002740   03 04 05 06  07 08 00 00  00 00 00 00  00 00 00 00  ................
    00002750   00 50 49 50  20 20 20 20  20 43 4F 4D  00 00 00 3A  .PIP     COM...:
    00002760   09 0A 0B 0C  0D 0E 0F 10  00 00 00 00  00 00 00 00  ................
    00002770   E5 E5 E5 E5  E5 E5 E5 E5  E5 E5 E5 E5  E5 E5 E5 E5  ................
    00002780   E5 E5 E5 E5  E5 E5 E5 E5  E5 E5 E5 E5  E5 E5 E5 E5  ................
    00002790   E5 E5 E5 E5  E5 E5 E5 E5  E5 E5 E5 E5  E5 E5 E5 E5  ................

    ....
     

     

  9. 1 hour ago, reifsnyderb said:

     

    I just started to take a look at this.  I removed the serial number code from CCP.  Did you mean to keep the serial number code in CCP as it's not in BDOS? 

     

    The beginning of BDOS is at $EC00.  Should BDOS really start at $EC06?  The BIOS would have to change the zero page vector to $EC06, of course.

     

    I thought the purpose of having the zero page vector was so that applications could find BDOS.....

    You are not using the original DRI source code. BDOS starts with a six byte serial, and jmp BDOSE (the entry point) is after that. In a lot of versions it's just six zeroes, sometimes the second byte is 16H to indicate it's version 2.2 of CP/M. It's indeed used to find the BDOS entry for applications to call, but it's also used to determine MEMTOP (MSB used only), and sometimes to calculate the beginning of CCP. I have seen code doing a hardcoded BDOS vector - 00806H = start of CCP. For example The Amsterdam Compiler Kit (ACK) does that.

     

    Original code from January 1980:

     

    Spoiler

    ; serial number (not documented in original DRI source file)
        db  0   ; OEM number, low byte
        db  0   ; CP/M version, 16h = 2.2
        db  0   ; OEM number, high byte
        db  0,0,0   ; serial number, big-endian

    ;   enter here from the user's program with function number in c,
    ;   and information address in d,e
        jmp bdose   ;past parameter block

    ;   ************************************************
    ;   *** relative locations 0009 - 000e           ***
    ;   ************************************************
    pererr: dw  persub  ;permanent error subroutine
    selerr: dw  selsub  ;select error subroutine
    roderr: dw  rodsub  ;ro disk error subroutine
    roferr: dw  rofsub  ;ro file error subroutine


    bdose:              ;arrive here from user programs
        xchg            ;info=DE, DE=info
        shld    info
        xchg
        mov a,e     ;linfo = low(info) - don't equ

     

     

    The original CCP source code has support for conditional assembly of it serial number:

    Spoiler

        ifndef  noserial
    serialize:
        ;check serialization
        lxi d,serial    ;check six bytes
        lxi h,bdosl
        mvi b,6
    ser0:   ldax    d
        cmp m
        jnz badserial
        inx d
        inx h
        dcr b
        jnz ser0
        ret         ;serial number is ok
        endif
     

     

    I used the vanilla sources to build CP/M for my 8080 emulator, and they are the same .SYS files I included in the cpm1090.zip file I posted here for you earlier. My builds are in the cpm22 directory in the atari8080 github repo. The original is here: https://github.com/brouhaha/cpm22/ . The only thing they did is convert it from the ancient 8080 ASM.COM format to something more modern. The assembler you need is linked to in the description.

     

    Edit: fixed to -00806H ;)

     

    Also found the code in boot.s in ACK:

    Spoiler

        ! Now the 'heap'.

        lhld 0x0006              ! BDOS entry point
        lxi d, -0x806            ! offset to start of CCP
        dad d
        shld _cpm_ramtop
     

     

    • Like 1
  10. 1 hour ago, reifsnyderb said:

    I suppose the 3 character buffer could be handled either in the CP/M BIOS or in the Atari I/O.  I think it would be much faster to do this in the CP/M BIOS.

    VT52 is easiest implemented as a state machine on the Atari side. No need to buffer characters. If you would do it in CONOUT at the Z80 side, you would need to devise a method to signal all the different VT52 "instructions" to the Atari, defeating the purpose. It's the Atari side that needs to manipulate the display.

  11. 35 minutes ago, reifsnyderb said:

    If only the ESC Y col row is needed, why not just intercept the command and tell the Atari OS to just re-position the cursor?  The same could be done for any other VT52 cases.

    Yes, that's possible. But he Atari would still behave funny with the three line buffer and all. And the E: handler is very slow.

    35 minutes ago, reifsnyderb said:

    Here's the current code to send the console output....

    This is what my first CP/M-65 BIOS did, too. But when I compared DUMP DUMP.COM between the Atari and the BBC, I quickly decided to ditch the E: handler and write a dumb terminal. If you look just at conout (the TTY driver, ignore the screen driver), it's really very simple. I reused the row and column addresses the Atari OS uses.

    42 minutes ago, reifsnyderb said:

    I didn't see that mouser is selling any DIP 64 Z-180 chips.

    I see. Googling around it seems they are harder to get than Z80s. So that's not a useful replacement either.

  12. 22 minutes ago, reifsnyderb said:

    This may be the easiest way to have files put on an ATR image by "injecting" the files to the correct location, in the image, and adding a directory entry.  Does anyone have an opinion as to if this is the way to go with this or if the Atari should be involved?  My personal opinion is that this is the easiest way to do this.

    At first I would stick to using mkfs.cpm and cpmcp to copy files to it, and then prepend the ATR header. If there are enough users really wanting to copy files directly from a DOS 2.5 disk to a cpmfs disk, it might be worth the trouble to write a specific utility for that. Probably a DOS utility, as CP/M cannot read the boot sectors via its BIOS. I hardly think it's worth the trouble.

     

    12 minutes ago, kheller2 said:

    I think there was a large effort involved in getting the proper DD disks created for Indus and ATR.  It might be better to stay in the DD format, but that wasn’t Atari’s direction with the 1090 or sweetpea.  

    How many reserved tracks does the Indus CP/M use? I think being able to boot with stock hardware (800XL, 1050, 1090) has its merits.

    • Like 1
  13. 1 hour ago, reifsnyderb said:

     

    I don't know what the supply will be.  I really don't like relying on cannibalized hardware, either.  Western Design sells the W65C02....so when I made the Happy Board there's a couple solder jumpers so all new hardware could be used.

    No need to cannibalize hardware IMHO. Looking at Aliexpress/eBay there are tons of refurbished Z80s available for as low as $1 each. Don't know how the "fake" situation is with Z80s though. I recall 6502s are sometimes mislabeled, like a 6502B actually being an A.

     

    1 hour ago, reifsnyderb said:

    Yeah, I was rather elated to get the CCP prompt up.  It responds as well.  So, if I try the "dir" command, for example, it reads the directory region of the disk. 

    Yeah, I remember the first time I got the A> prompt with my emulator. That's an exiting moment :)

    1 hour ago, reifsnyderb said:

    Since respeQt shows what sectors are being read, I also discovered that CP/M was initially reading one sector before the first sector.  After some troubleshooting, to verify my track/sector to sector translation code was working correctly, I discovered that CP/M was passing a sector 0.  So, there was an off-by-one error.  I had to increment the sector number, to "fix" the off-by-one issue and get the correct sectors to be read.  The documentation wasn't clear as to whether CP/M started with sector 0 or 1.

    Good you found it. I prototyped my 8080 emulator in C and noticed that sectors start at 0, so I was prepared when I did the 6502 code.

     

    1 hour ago, reifsnyderb said:

    Well, I was elated yesterday, at around 2:00pm, to get the prompt, have issues such as the CR/LF translation working, get keyboard input working, etc.  Only hours later, I find out I am closing in on getting a CPU/Memory board for a soon to be discontinued CPU. 

     

    Oh, yeah, the 80 column card appears to work with the CP/M card as well.  Maybe it will run WordStar as-is?

    No, that won't work. The Atari E: handler does all sorts of things with high ASCII characters (clear screen, bell at the end of line 3, clear up to 3 lines etc.) which might interfere with CP/M working properly. It's best to have a true dumb terminal that bypasses the E: handler. To get WordStar 3.3 working, you can manually configure that to do VT52, which is very easy. WS only needs position cursor (ESC Y col row). The rest is optional. Don't know about later WS, because 3.3 was the last 8080 version. But VT52 should be enough and has a very limited command set (http://gunkies.org/wiki/VT52 , CP/M-65 implementation: https://github.com/davidgiven/cpm65/blob/master/apps/vt52drv.asm , Atari dumb terminal is in its bios https://github.com/davidgiven/cpm65/blob/master/src/arch/atari800/atari800.S , 80 columns software driver is at https://github.com/davidgiven/cpm65/blob/master/src/arch/atari800/utils/tty80drv.S).

     

    Edit: forgot to mention. Regarding the Z80 situation, looking at the notification (https://www.mouser.com/PCN/Littelfuse_PCN_Z84C00.pdf ) it's only the Z80 that's discontinued. Not sure how much effort it takes, but you could upgrade to the DIP-64 Z180. The added DMA would be useless, and the new instructions won't be used, but while you're at it, you might want to break out the build-in UART to a connector.

     

    Edit2: https://www.zilog.com/docs/z180/ps0140.pdf

     

  14. Hi,

     

    It's a pity the DIP and PLCC versions are discontinued, but I suppose they won't be hard to get anytime soon. Even NMOS 6502 are plenty available as NOS and refurbished.

     

    I see you used a RE'd Z80 source for BDOS and CCP. In theory that's fine, but I would not remove the 6 bytes serial at the beginning of BDOS and move BDOSE to $xx00. Some applications rely on it being $xx06 and the zero page vector ending with $06. IIRC ACK compiled applications have that dependency. If I were you, I'd just stick to DRI vanilla source code. You won't gain a full page of memory savings anyway, and it's advised to have each component page aligned.

     

    The cross-platform utilities are here: http://www.cpm.z80.de/download/cpm2-plm.zip . Most include source, too.

     

    I don't think you wasted three weeks on this. It's great to see you got to the CCP prompt! Most of the work seems done. Now you "only" need some form of proper terminal emulation and you can run WordStar :)

     

  15. 15 hours ago, _The Doctor__ said:

    was there never a fix to autolog or just have a relog before disk operations. I might have recently forgot that step and killed a disk, face palm palm face.

    Relog disks before operations is not as trivial as it may seem and can be slow, if possible at all. Opening and closing files is expensive, hence a lot of applications keep their files open until program termination. Also note that BDOS does not know if there are any files open. That info is all in user space (File Control Blocks).

     

    I recently read an anecdote from somebody that was working at a company where at least once a week an employee came at his desk with a ruined floppy. To avoid to have to manually retrieve (some of) the data each time, he modified the BIOS of all their workstations to run a timer interrupt that checked the floppy drive's open/close sensor every 100ms. If somebody opened the drive after boot, a big warning would be displayed urging the user to put back the SAME disk again, and would not continue until the drive was closed again, hopefully with the same disk inside. After that, the reports of ruined floppies dropped to zero.

     

    • Like 4
  16. There is no CP/M RAM disk standard. There's not a standard to how banked memory was done. CP/M 3 supported banked memory, but their implementations varied wildly, ranging from 4kB to 32kB of bankable RAM. Similar to how there is not one disk format. Each system had their own disk format, and if they supported a RAM disk, it was in their custom BIOS implementation. I have seen drive M: (for "memory" I suppose) or drive P: (last one available). But since your goal is four drives (A:-D:) you could just as easily use E:.

     

    As all disk access goes through the Atari OS SIO routines, it's much easier to mount several ATR disk images with SIDE or another PBI IDE implementation and have your SSED disk images on a CF or SD card. Just as fast, and non-volatile. You can even boot from them. RAM disks are obsolete IMO. Well except for initramfs during Linux boot I suppose ;)

     

    CP/M is also not capable of mixing floppy formats, as the disk layout is fixed in memory. And swapping disks is also a thing. Never swap a disk in the middle of an application or it will ruin your filesystem. The only way to swap disks is when CCP is running and after a swap press control-C to restart CCP so it logs in the new disk. If you forget the last step, it might ruin the newly inserted disk.

    • Like 1
    • Thanks 1
  17. 1 hour ago, reifsnyderb said:

    I started a response then realized I was thinking in CP/M terms of tracks and sectors.  Meanwhile the Atari is only working with sectors.  So, Yeah, it now makes more sense to just load it all into the Atari's RAM.  I'll re-figure it.

    Here's a skeletal with build system. It now generates a zero-filled file for bios.sys. You have to supply your own bios.asm and build rule in the Makefile.

    Typing 'make' builds the bootblock, creates the CP/M FS with that bootblock, copies some files to it, and creates an ATR image from CP/M disk image.

    Bootblock.s contains several instances of ; XXX your code here, as you are more knowledgeable about how to switch off/on the Z80.

     

    Spoiler

    $ make
    dd if=/dev/zero of=bios.sys bs=256 count=6
    6+0 records in
    6+0 records out
    1536 bytes (1,5 kB, 1,5 KiB) copied, 0,000375971 s, 4,1 MB/s
    mads -o:bootblock.bin bootblock.s
    Start bootblock: $0700
    End code:        $0802
    Start data:      $0900
    End bootblock:   $2580
    Writing object file...
    220 lines of source assembled in 3 pass
    7808 bytes written to the object file
    dd if=/dev/zero of=cpmfs.img bs=128 count=1040
    1040+0 records in
    1040+0 records out
    133120 bytes (133 kB, 130 KiB) copied, 0,00365784 s, 36,4 MB/s
    mkfs.cpm -b bootblock.bin -f atari1090ed cpmfs.img
    cpmcp -f atari1090ed cpmfs.img cpm22/DUMP.COM cpm22/STAT.COM cpm22/PIP.COM \
        0:
    cpmls -f atari1090ed cpmfs.img
    0:
    dump.com
    pip.com
    stat.com
    cat atrheader.dat cpmfs.img > bootdisk.atr
    ls -l bootdisk.atr
    -rw-rw-r-- 1 ivo ivo 133136 Apr  9 20:02 bootdisk.atr

     

     

    Hope this helps :)

     

    Edit: for inspiration: https://github.com/ivop/atari8080/blob/main/8080.s starting at line 2234 (absolute sector calculation, handling bank overflow, e.g. you read 128 bytes to $7ff0 in bank 2).

    and https://github.com/davidgiven/cpm65/blob/master/src/arch/atari800/atari800.S starting at line 941 for sector read/write code. TTY code uses K: for keyboard in. For CONOUT you can use E: as a start. Once you get the A> prompt and can run DUMP DUMP.COM, you can look into a proper 'dumb' CP/M terminal and finally an ADM-3a or VT52 terminal emulation.

     

    Edit2: the bank overflow trick uses up to 127 bytes after the bank ends. On read, I just read into memory past $8000, detect overflow, select next bank, and copy the number of overflown bytes to $4000. On write, I check overflow, select next bank, copy X number of bytes from $4000 to $8000, select previous bank, write 128 bytes from e.g. $7ff0.

    cpm1090.zip

  18. 13 hours ago, reifsnyderb said:

    Ok, I figure I'll lay out the disk like this:

     

    ;	Disk layout:
    ;	Track 0		Sector 	1			Atari boot sector (Atari @ $0700) -- Note:  Sectors 1-14 are loaded with the boot sector.
    ;	Track 0		Sectors	1-2			CP/M BIOS Loader (Atari @ $0714 - $07FF) -- Loads CP/M BIOS into Z-80 RAM bank 3, $7A00
    ;	Track 0		Sectors 3-10		Atari CP/M I/O (Atari @ $0800 - $0BFF) -- 1k allocated, probably less is needed
    ;	Track 0		Sectors	11-14		CP/M BIOS (Atari @ $0C00 $0DFF) -- 512 bytes allocated
    ;	Track 1		Sectors	1-16		CCP - 2048 bytes starting at  E400 (Z-80 RAM bank 3, $6400)
    ;	Track 1		Sectors 17-26		BDOS - 1152 bytes starting at EC00 (Z-80 RAM bank 3, $6C00)
    ;	Track 2		Sectors	1-19		BDOS - 2432 bytes
    ;	Track 3		Sectors	1-16		Directory - 2048 bytes
    ;	Track 3		Sectors 17-26		Data - 1152 bytes
    ;	Track 4+	Data																	

     

    (I still can't get the stupid indents to display right.   😞   )

     

    I'll leverage the OS to load the Atari boot sector and include the CP/M BIOS loader, the Atari CP/M I/O code that handles the I/O between CP/M and the Atari OS, and the CP/M BIOS.

    The CP/M BIOS loader code will set the Z-80 cold boot jump at $0000 (Z-80 RAM bank 0, $4000) and copy the already loaded CP/M BIOS (from $0C00 to $0DFF) to the Z-80 BIOS location at $FA00 (Z-80 RAM bank 3, 7A00).

    Control will then be transferred to the Atari CP/M I/O code that will start the Z-80 and manage the I/O between the Z-80 and the Atari OS.

    The CP/M BIOS will then load CCP and BDOS.

     

    It's quite possible the Atari CP/M I/O code will take less than 1k.  I'll reduce it's size if necessary. 

     

    I just need to add the CCP and BDOS loading code to the CP/M BIOS.  Right now, the CP/M BIOS sits at 378 bytes.   🙂

     

    Why? If you followed my example there is no need for special Z80 code to load BDOS and CCP. Everything is loaded in one go by the Atari OS during boot, then copy BDOS+BIOS to Z80 RAM, set 0000H vector, and run. The only thing the Z80 BIOS has to do is signal LoadCCP during WBOOT, similar to how you signal ConsoleStatues, and ReadSector, etc.. You also do not have to keep track of at which sector something is located, everything is handled automatically by mads. The bootblock is just sector 1-78 (maximum, can be smaller) that contains "everything everywhere all at once" ;) If you want, I can create a larger example that you only have to fill in with the I/O code.

     

     

    • Like 1
  19. 2 hours ago, snicklin said:

    It is also a lot slower, so I wouldn't really be gaining anything there.

    Python is mostly used as a wrapper around C++ machine learning libraries. With PyTorch, CuPy, Theano, PyCuda, TensorFlow, etc. and a proper GPU you get thousands of threads instead of just a few with a CPU. Things like evaluating the proposed images can be done in parallel per pixel, i.e. thousands of pixels are evaluated simultaneously. We are speaking of at least a 100x increase in speed compared to evaluating pixel by pixel as it is now. And switching between different optimizers is easy.

     

     

    • Like 2
  20. 30 minutes ago, reifsnyderb said:

    Truthfully, I don't know how the directory track should be counted.  I guess it can store data if there is space.

    Strictly speaking, the directory sectors count for the disk capacity, the reserved tracks do not:

     

    sectors = (number_of_tracks - reserved_tracks) * sectors_per_track
    blocks_on_disk = sectors * 128 / block_size
    30 minutes ago, reifsnyderb said:

    Loading BDOS, during cold boot, and CCP, curing warm boot, is a good option as well.  I am figuring that it doesn't take too long to load BDOS and the BIOS either way.  One of my thoughts is to minimize the Atari code as much as possible.  I was looking at the structure of the Atari boot sector and thinking that, if possible, the Atari code and BIOS code could all be loaded at the same time.  This way, Atari's OS would load both and it would save some code on my end.    

    Yes, this is exactly what I tried to explain earlier with the mads example 'ins'-ing the .SYS files :) The Atari OS boot code can load up to 255 sectors to consecutive memory. No need for padding between the Atari code and CCP+BDOS+BIOS.SYS. Aligning to page boundaries is slightly faster though, as lda abs,x is 25% longer (5 cycles instead of 4) if you cross a page boundary.

     

    CCP = $e400
    CCP_BANKEDRAM = $4000 + (CCP & $3fff) ; in BANK3
    
    copy_ccp:
    	lda #BANK3
    	sta BANKREG
    	ldx #0
    
    copy_loop:
    	.rept 6
    		lda CCP_LOWRAM+#*256,x
    		sta CCP_BANKEDRAM+#*256,x
    	.endr
    	inx
    	bne copy_loop
    
    ; ... more code
    
    	.align $0100
    
    CCP_LOWRAM:
        ins 'CCP.SYS'

     

     

    30 minutes ago, reifsnyderb said:

    The 512 byte estimate doesn't include the buffers.  I put the buffers in the last 512 bytes of free memory.  Since there isn't any sign they have to be initialized with anything, their content doesn't matter.  Worst case, I suppose I could clear the memory during cold boot.

    Agreed. I don't think that's even necessary.

  21. 11 hours ago, GravityWorm said:

    @drpeter


    New version crashes 20% the time. Some memory fault. Something like segmentation fault or memory access violation

    You could try my Linux fork at https://github.com/ivop/RastaConverter

    Started 12 years ago, and has a lot of fixes (compiler warnings fixed, deprecated code replaced). Never got around to create a proper patch to send upstream though. I recently merged the new Sheddy code.

     

    It has Link Time Optimization enabled (faster), and it also supports Profile Guided Optimization. For the latter, type make pg first, run rastaconv-pg for a few minutes with real world data to collect profile data, then run make pu to build the final binary rastaconv-pu.

     

    • Thanks 3
  22. 1 hour ago, reifsnyderb said:

    The extra 1152 bytes is the space in the directory track that isn't used by the directory.

     

    I was counting the 40 tracks as track numbers 0 to 39.  So, with 3 tracks used by the OS there are 36 tracks left.

    Ah, I see. We had a different definition of disk capacity. I also counted block 0 where the directory lives.

     

    1 hour ago, reifsnyderb said:

    I've been considering options on this one.  Since a warm boot requires that the BIOS copy CCP back, why not have the BIOS copy both CCP and BDOS back in place?  Since only the BIOS is involved in the warm boot, it wouldn't matter.  So, I've been thinking that if the Atari installs the BIOS and sets the BIOS jump in the Z-80 memory at $0000, then the cold boot function would be ran first.  The cold boot would then run part (most) of the warm boot code and install both CCP and BDOS.

    That would do a full re-initialization of BDOS each warm boot. Back in the day, BOOT (cold) fell through to the WBOOT code and was something like this:

     

    BOOT:

        ; do cold boot stuff

        ; load BDOS

        ; fallthrough

    WBOOT:

        ; do warm boot stuff

        ; load CCP

        ; run CCP

     

    If you let the Atari copy BDOS+BIOS and set 0000H before starting the Z80, the load BDOS step can be omitted. But in the end it does not really matter. When I was debugging my 8080 emulator prototype in C I had BOOT and WBOOT copy both BDOS and CCP each time, and that works as well. But it would be over three times slower to copy BDOS, too.

     

    1 hour ago, reifsnyderb said:

    Yeah, my mistake.  I found it after posting.  Realistically, not all 1536 bytes would be loaded as the buffers would be at the end.  I am currently guessing that the BIOS will be under 512 bytes.

    Nice! That's including buffers and DPH/DPB I suppose?

     

    Edit: premature post... sigh.

  23. 12 hours ago, reifsnyderb said:

    Ok.  I re-did my calculations as how to fit everything into the normal CP/M boot area.  Keep in mind I am planning to use the 1050's density and a half format.  Boot track layout is at the bottom.

     

    ; 	Calculations:
    ;
    ;  	Size of CCP = $EC00 - $E400 = $800 = 2048 bytes (16 sectors)
    ;	Size of  BDOS = $FA00 - $EC00 = $E00 = 3584 bytes (28 sectors)
    ;	Size of BIOS = $FFFF - $FA00 = $5FF = 1535 bytes (12 sectors)
    ;	Total size of CCP + BDOS + BIOS =  $1BFF = 7167 bytes
    ;	Bytes per Track: = 128 bytes * 26 sectors = 3328 bytes
    ;	128 byte sectors needed for CCP + BDOS + BIOS  =  56 sectors
    ;	Bytes per directory entry :  32
    ;	Directory entries per sector:  4
    ;
    ;	Directory entries are 32 bytes.  4 entries per 128 byte sector.
    ;
    ;	Drive storage capacity 	= Tracks 4 to 40 + 1152 bytes 
    ;							= 36 * 3328 + 1152 = 119808 + 1152 = 120960
    ;							= 120960 / 1024 bytes per block = 118 = $76
    ;
    ;	Boot track layout:
    ;	Track 0		Sectors 	1-12		Atari boot sector, BIOS loader, and CP/M I/O - 1536 bytes max
    ;	Track 0		Sectors 	13-26		BIOS - 1535 bytes max starting at FA00
    ;	Track 1		Sectors		1-16		CCP - 2048 bytes starting at  E400
    ;	Track 1		Sectors 	17-26		BDOS - 1152 bytes starting at EC00
    ;	Track 2		Sectors		1-19		BDOS - 2432 bytes
    
    

     

    If you reserve 3 tracks (0-2), you have 37 tracks for the filesystem, not 36. So 37*26*128 /1024 = 120 blocks. Where did the 1152 come from in your drive storage capacity?

     

    Also, I would make the order CCP, BDOS, BIOS. That way you can copy BDOS and BIOS to shared memory in a single copy loop. They do not have to be sector aligned, although being page aligned could speed up your copy loop.

     

    Note that the size of the BIOS is $ffff-$fa00+1 = 1536 bytes. But that doesn't matter for the rest of the calculations.

     

    Edit:

     

    diskdef for your format:

     

    diskdef atari1090ed
        seclen 128
        tracks 40
        sectrk 26
        blocksize 1024
        maxdir 64
        boottrk 3
        os 2.2
    end

     

    Edit2:

     

    Disk Parameter Block calculations:

     

    ; atari1090ed
    number_of_tracks = 40
    reserved_tracks = 3
    sectors_per_track = 26
    block_size = 1024
    dirents = 128
    
        if block_size = 1024
    block_shift = 3
        elseif block_size = 2048
    block_shift = 4
        elseif block_size = 4096
    block_shift = 5
        elseif block_size = 8192
    block_shift = 6
        elseif block_size = 16384
    block_shift = 7
        endif
    
    block_mask = (1 << block_shift) - 1
    
    checksum_buffer_size = (dirents + 3) / 4
    sectors = (number_of_tracks - reserved_tracks) * sectors_per_track
    blocks_on_disk = sectors * 128 / block_size
    allocation_vector_size = (blocks_on_disk + 7) / 8
    directory_blocks = (dirents * 32) / block_size
    allocation_bitmap = (0ffffh << (16 - directory_blocks)) & 0ffffh
    
        if directory_blocks = 0
            error "Directory must be at least one block in size!"
        endif
        if (dirents * 32) # block_size != 0
            error "Directory is not an even number of blocks in size!"
        endif
    
        if blocks_on_disk < 256
            if block_size = 1024
    extent_mask = 000h              ; %00000000
            elseif block_size = 2048
    extent_mask = 001h              ; %00000001
            elseif block_size = 4096
    extent_mask = 003h              ; %00000011
            elseif block_size = 8192
    extent_mask = 007h              ; %00000111
            elseif block_size = 16384
    extent_mask = 00fh              ; %00001111
            endif
        else
            if block_size = 1024
                error "Cannot use a block size of 1024 on a large disk!"
            elseif block_size = 2048
    extent_mask = 000h              ; %00000000
            elseif block_size = 4096
    extent_mask = 001h              ; %00000001
            elseif block_size = 8192
    extent_mask = 003h              ; %00000011
            elseif block_size = 16384
    extent_mask = 007h              ; %00000111
            endif
        endif
    
    dpblk:
        dw sectors_per_track
        db block_shift
        db block_mask
        db extent_mask
        dw blocks_on_disk - 1
        dw dirents - 1
        db (allocation_bitmap & 0ff00h)>>8
        db (allocation_bitmap & 000ffh)
        dw checksum_buffer_size
        dw reserved_tracks
    
    dirbf:
        ds 128      ; can be the same for multiple disks
    chk00:
        ds checksum_buffer_size
    all00:
        ds allocation_vector_size

     

    • Like 2
  24. Perhaps you can get one of these?

     

    https://www.amazon.com/JANSANE-PL2303TA-Serial-Console-Raspberry/dp/B07D9R5JFK/ref=sr_1_9?crid=288FWF02G11QF&dib=eyJ2IjoiMSJ9.mmFSFgBLhSyBOomkkUq4yGiGWlh3AaGYTCkOhDC2QZduSly4-Yzhl7JdHD-4CC81nIkrAl-ofLD96FOelis17PeCkBgfwUyNj9ZLgnkbq_EQczRxgiPwHyjuUM0_Bw7XgI-CWE8h6yANbhuw0D76JcVjP0mPFiDhxfOSjJXQHOYfv39TE2FoFuo_n_vK6g4Q2moOMGeTJvVCS0BEAVnT77NzsfdN4CVbS6fQ7Xm0N84.GkiLOa55xzFbxdRgzi-yOANRtstWuqF82ZkybvnwkLk&dib_tag=se&keywords=usb+ttl+serial&qid=1712539626&sprefix=usb+ttl+serial%2Caps%2C195&sr=8-9

     

    Wired to the SIO port you should be able to run RespeQt. Otherwise you are making it a lot more difficult for yourself than necessary, writing a CP/M writer in Basic and all that. Create the raw disk image by concatenating the 54 sectors boot block with (720-54)*128 zeroes and use mkfs.cpm and cpmcp to put other files there, like PIP.COM, STAT.COM, etc... Prepend ATR header for 720 sectors of 128 bytes. Boot from that or sector copy to a blank disk.

     

    If you leverage the Atari OS boot mechanism, it'll load the first three tracks (54 sectors) automatically somewhere in memory. Most of the time $0700, but that is not a requirement. Also 3 boot sectors is not fixed, you can set that to 54. After that you can fast memcopy the Z80 code in place (BIOS and BDOS), and let WBOOT trigger a LoadCCP command to the Atari, which memcopies the CCP in place. This is not far off from what Atari did with their implementation. In mads that would be something like:

     

        opt h-
    
        org $0700
    
        .byte 0
        .byte 54
        .word $0700
        .word main
    
    main:
        ; code here
        ; copy $1400 bytes from BDOS to shared memory at $ec00
        ; start Z80
    loop:
        ; wait for IO request, dispatch with jump table or several cmp's
        ...
        ; in LoadCCP call, copy $0800 bytes from CCP to $e400 in shared memory
        ....
        jmp loop
    
    CCP:
        ins 'ccp.sys'    ; $0800 bytes, at $e400 in shared memory
    
    BDOS:
        ins 'bdos.sys'   ; $0e00 bytes, at $ec00 in shared memory
    
    BIOS:
        ins 'bios.sys'   ; $0600 bytes, at $fa00 in shared memory

     

    If you don't want to or are unable to get a SIO2PC capable cable and want to use your 1090 ROM method, you can also, depending on the amount of ROM available, create the CP/M disk as described earlier, not turn it into an ATR, but just copy as much from the beginning of the disk image file to the ROM and write the ROM contents to a blank formatted disk with (Turbo) Basic. You can check if all the files you copied to the CP/M disk fit by first creating the FS on a non-zero padded file (just specify a non-existent disk.img file) and see how large it becomes after cpmcp. cpmcp does not expand the image file to the actual FS size. BTW with mkfs.cpm -f yourformatindiskdefs -b bootblock.bin disk.img you can automatically include the boot block created with mads. Hope this'll save you some time ;)

    • Like 3
  25. Looks good! Doing a little more on the Z80 side then I would have done, but it makes sense to not delegate some of the BIOS functions to the Atari (SELDISK and friends for example). Regarding loading BDOS from disk, I would make BDOS part of the initialization process. After that it never has to be loaded again. Lots of the original CP/Ms did that too. It's not supposed to be overwritten, ever. You also have a chicken and egg problem, because if there's no BDOS, you cannot read BDOS.SYS from the filesystem because there is no filesystem handler, which is BDOS. Regarding loading CCP.SYS, you can keep a copy in 6502 RAM and have WBOOT copy that over to the shared RAM. That's a lot faster.

     

    To summarize, the Atari bootcode loads BDOS and BIOS into the shared RAM, and CCP in its own RAM, and starts running its mainloop. BIOS will request CCP to be copied during WBOOT.

     

    Edit: I noticed you reserve only one byte for IOTrack, but that should be two bytes.

     

    Edit2: changed observation on what to do at the Z80 side and what to delegate :)

    • Like 2
×
×
  • Create New...