Jump to content

ivop

Members
  • Posts

    3,323
  • Joined

  • Last visited

  • Days Won

    3

ivop last won the day on April 9 2017

ivop had the most liked content!

2 Followers

Contact / Social Media

Profile Information

  • Gender
    Male
  • Location
    The Netherlands

Recent Profile Visitors

22,715 profile views

ivop's Achievements

River Patroller

River Patroller (8/9)

4k

Reputation

  1. 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.
  2. 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.
  3. 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. 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
  4. 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.
  5. 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.
  6. 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 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' Agreed. I don't think that's even necessary.
  7. 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.
  8. Ah, I see. We had a different definition of disk capacity. I also counted block 0 where the directory lives. 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. Nice! That's including buffers and DPH/DPB I suppose? Edit: premature post... sigh.
  9. 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
  10. 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
  11. 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
  12. I understand what you mean. Thanks for your concern. The hexdump files did have missing line feeds, but the contents of the .Byte data statements are all there. See for example CPM1/CPMFILES1.MAC.3. The CPMFILES*.MAC files contain a dump of the CP/M filesystem, starting at track 3 (skipping the reserved tracks 0-2). If you were to convert the first 128 hex bytes to ASCII you would see the directory there.
  13. Me neither. I guess they were just lazy and let the Z80 copy it to the right place. Sector skewing is not used. The table is a dummy. On a real 8080/Z80 it is used to to translate sector numbers for the drive controller, but that's not used here. I wouldn't remove the track/secnum distinction. Multiply by 18 on the 6502 is cheap (*16+*2, just shifts and one addition). CP/M-65 internally doesn't use track numbers, and sector numbers range from 0-719 on a SSSD disk. In my 8080 emulator I translate track/sec to just sec for CP/M-65. If you are going to rewrite the BIOS anyway and not use Atari's stuff, IMHO it can be done much simpler. Jump table has every entry vector to almost the same Z80 subroutine. That subroutine does: * call subroutine, saves Z80 registers at $ff01 and further (AF, BC, DE, HL) * set $ff00 to BIOS call number (this is the only thing that is different for each vector) * call Atari * call subroutine, restores Z80 registers from $ff01 and further * RET Now you can just implement everything at the Atari side. You could leverage much of the i8080 emulator. You could either run it on top of CP/M-65 or copy the BIOS translation code and the relevant parts of atari800.S BIOS and run it independently.
  14. Binary files don't have line feeds. They look to be extracted from the binary blob hexdumps in CPMFILES*.MAC, which was actually on my todo-list Not sure if he used the CPM1 or CPM2 directory version. Files from May 30 1984 (sizes 117148, and last one 49948) are identical though, so I that doesn't matter. The atbios.com file is not a real CP/M COM file (which would load at 00100H) but a memory dump from 00000H-0F4FFH. The BIOS is re-assembled at F200. A bit low, but at least there's plenty of room for the command frame ($fbf0) and data transfer area ($fc00). The rest is padded with zeroes. I compared it with the 20K version at 04A00H and it seems it not just a re-assembled file. I'll run the disassembler on it to see what's changed. Edit: 20K version at $4a00 Edit2: it actually is identical to the 20K version, just reassembled to $f200 with CCPSTART at $dc00 and BDOS at $e400 (BDOSE = $e406). I don't see CCP.SYS and BDOS.SYS at these locations anywhere, but they are easy to re-assemble from the Digital Research Inc. source code.
  15. Note that when the machine is powered on, 00000H reads JP BOOT, but the BOOT code changes that to JP WBOOT. It's used by programs that overwrite CCP during operation because they need more RAM. The general approach to detect the amount of RAM is to check location 7 (the high byte of BDOSE, BDOS Entry point) and use that as the top of the RAM. Normally a program exits with RET to CCP, but if it knows it has overwritten CCP or modified important disk structures on disk, it does JP 00000H, which does a warm start, which reads CCP from disk, and initializes itself again.
×
×
  • Create New...