tschak909 Posted October 21, 2019 Share Posted October 21, 2019 Hey guys, Am putting together an 8K sector copier cart (called tiny-copy) that can be plopped e.g. into an Ultimate 1MB BASIC slot. I have most of the code written, but am just curious: * Does anyone have code to detect RAM expansion options? * also does anyone have code to handle transitioning to high-speed I/O for drives that support it? @Mathy ??? I will be posting the result up to github soon. -Thom Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted October 21, 2019 Share Posted October 21, 2019 5 minutes ago, tschak909 said: also does anyone have code to handle transitioning to high-speed I/O for drives that support it? Yes: it's already in the U1MB SIO driver. You just need to call SIO. 2 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted October 21, 2019 Author Share Posted October 21, 2019 Yeah, ok, I guess I can side-step that. -Thom Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted October 22, 2019 Share Posted October 22, 2019 Yes: leave it to the OS, not least since the volume may not be hosted by a serial device (PBI hosted ATR, HDD partition, etc). Extended memory detection: http://atariki.krap.pl/index.php/Obsługa_standardowego_rozszerzenia_pamięci_RAM You might also want to check for SDX and branch to detection code which uses the SDX bank table if present in order not to nuke the DOS bank, RAMdisk, etc. See SDX programming manual. 2 Quote Link to comment Share on other sites More sharing options...
E474 Posted October 22, 2019 Share Posted October 22, 2019 Hi, I want to add sector copier functionality to ATR Maker Deluxe (it's an ABBUC software competition entry, so I can't publicly post the program, or sources yet), but if you are copying disks you could copy the sector data to a ramdisk file, rather than code for bank select management. Quote Link to comment Share on other sites More sharing options...
tschak909 Posted October 22, 2019 Author Share Posted October 22, 2019 (edited) 9 minutes ago, E474 said: Hi, I want to add sector copier functionality to ATR Maker Deluxe (it's an ABBUC software competition entry, so I can't publicly post the program, or sources yet), but if you are copying disks you could copy the sector data to a ramdisk file, rather than code for bank select management. Sigh. No, actually, I can't. This is intended to run from an 8K cart, entirely self contained without a DOS, so it uses SIOV wholly. So I have the whole machine to myself, ergo, I need to handle the bank switching myself. -Thom Edited October 22, 2019 by tschak909 Quote Link to comment Share on other sites More sharing options...
Alfred Posted October 22, 2019 Share Posted October 22, 2019 Look for the ACUSOL thread, I recall there was a discussion of bank detection routines and several routines were posted for Pab. Quote Link to comment Share on other sites More sharing options...
Mathy Posted October 22, 2019 Share Posted October 22, 2019 Hello Thom Matthias Reichl should have a high speed driver. Sincerely Mathy Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted October 23, 2019 Share Posted October 23, 2019 Yes: Hias' driver is built into the U1MB which is the target platform for the tool being developed. As I already suggested: keep serial drivers out of the application unless you want it to be useless with PBI hosted ATRs and hard disk partitions. The PBI BIOS has everything required, and even if the newer firmware with the driver is not present, the high-speed patched OS is. 3 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted October 25, 2019 Author Share Posted October 25, 2019 @flashjazzcat silly question, can 512 byte sectored "partitions" be read with SIOV if the DBYT length is 512? Or does that require special handling? -Thom Quote Link to comment Share on other sites More sharing options...
tschak909 Posted October 25, 2019 Author Share Posted October 25, 2019 As part of my process of understanding the output of the percom disk block, I wrote a little tool to dump and display it: /** * Read and dump percom block */ #include <stdio.h> #include <stdlib.h> #include <atari.h> #include <6502.h> struct _percom_block { unsigned char num_tracks; unsigned char step_rate; unsigned short sectors_per_track; unsigned char num_sides; unsigned char density; unsigned short sector_size; unsigned char drive_present; unsigned char reserved1; unsigned char reserved2; unsigned char reserved3; }; struct _percom_block percom_block; unsigned char buf[12]; void main(void) { struct regs r; OS.dcb.ddevic=0x31; OS.dcb.dunit=2; OS.dcb.dcomnd=0x4E; OS.dcb.dbuf=&buf; OS.dcb.dtimlo=0x0f; OS.dcb.dstats=0x40; OS.dcb.dbyt=12; r.pc=0xE459; _sys(&r); percom_block.num_tracks=buf[0]; percom_block.step_rate=buf[1]; percom_block.sectors_per_track=(buf[2]<<8)+buf[3]; percom_block.num_sides=buf[4]+1; percom_block.density=buf[5]; percom_block.sector_size=(buf[6]<<8)+buf[7]; percom_block.drive_present=buf[8]; printf("Percom Block Contents:\n"); printf("----------------------\n"); printf("num_tracks: %u\n",percom_block.num_tracks); printf("step_rate: %u\n",percom_block.step_rate); printf("sectors_per_track: %u\n",percom_block.sectors_per_track); printf("num_sides: %u\n",percom_block.num_sides); printf("density: %u\n",percom_block.density); printf("sector size: %u\n",percom_block.sector_size); printf("drive present? %u\n",percom_block.drive_present); } Example output of a DD 512 65535 sector disk: D1:PERCOM Percom Block Contents: ---------------------- num_tracks: 1 step_rate: 1 sectors_per_track: 65535 num_sides: 1 density: 0 sector size: 512 drive present? 255 Versus a 1050 formatted disk: D1:PERCOM Percom Block Contents: ---------------------- num_tracks: 40 step_rate: 1 sectors_per_track: 26 num_sides: 1 density: 4 sector size: 128 drive present? 255 You might ask, why I didn't just slam it right into the struct's buffer, the answer is that because Percom's controller was based on a 6809, the byte order is big endian, and therefore to use on a 6502, the bytes of the 16-bit values need to be swapped. -Thom 1 Quote Link to comment Share on other sites More sharing options...
Rybags Posted October 25, 2019 Share Posted October 25, 2019 Re sector length - the longer sectors can be handled by SIOV but not DSKINV so long as the buffer length is set correctly. Unsure but you might be able to get away using shorter buffer length in some cases, e.g. just read 128 bytes on a 256 byte sectored disk. Quote Link to comment Share on other sites More sharing options...
tschak909 Posted October 25, 2019 Author Share Posted October 25, 2019 Yup, i'll be doing it entirely with SIOV. Are there any other sector copiers out there that can handle the 512 byte sectors? If not, it'll be cool to be the first. Goal here is yeah, this is an 8K "cart", which can be slotted onto a U1MB, hopefully it will be useful. -Thom 1 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted October 25, 2019 Author Share Posted October 25, 2019 There we go, rough UI blocked out, program is at about 300 bytes (code+data) at the moment, but it will grow (haha) will receive splashes of color etc in a bit. Quote Link to comment Share on other sites More sharing options...
+Larry Posted October 25, 2019 Share Posted October 25, 2019 Neat little project. Just curious -- can Action! executables be put in cartridge format? I don't recall seeing one, but offhand, seems like it should be possible. Anyone know of one that already exists? Do you have a size goal -- 1 to 2K maybe? That would leave room for some other utilities. (?) -Larry Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted October 25, 2019 Share Posted October 25, 2019 10 hours ago, tschak909 said: @flashjazzcat silly question, can 512 byte sectored "partitions" be read with SIOV if the DBYT length is 512? Or does that require special handling? Yes they can. Commonly such 512 byte sectors will be hosted on some PBI device anyway, and most IDE host adapters will ignore the buffer length passed via the DCB and simply transfer the full sector regardless (loops are often unrolled, etc, and observing the buffer length would be fiddly and superfluous). Of course you should set the buffer size in the DCB anyway (since the tool need not care whether a volume is hosted on the serial or parallel bus), having obtained geometry information from the PERCOM block (which should provide the correct information regardless of where the volume is hosted, and if it does not, you can assume the disk is single-density). Quote Link to comment Share on other sites More sharing options...
Alfred Posted October 25, 2019 Share Posted October 25, 2019 2 hours ago, Larry said: Neat little project. Just curious -- can Action! executables be put in cartridge format? I don't recall seeing one, but offhand, seems like it should be possible. Anyone know of one that already exists? Do you have a size goal -- 1 to 2K maybe? That would leave room for some other utilities. (?) -Larry They can, if you’re careful as to the constructs you use. 1 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted October 25, 2019 Author Share Posted October 25, 2019 (for clarity, this is not in ACTION! but in C) -Thom Quote Link to comment Share on other sites More sharing options...
tschak909 Posted October 25, 2019 Author Share Posted October 25, 2019 (edited) @Larry basically, you have to be aware of your memory map. Cartridges are ROMmed code, and especially in ACTION! you have to carefully make sure that you specify RAM vs ROM addressing with your variables. In ROM programs, the address space is bifurcated, from the point of the linker, there are multiple segments of memory for things like CODE, DATA, RODATA, BSS, etc, and the parts that don't change get address offsets relative to the start of the ROM space, while parts that remain in RAM get address offsets relative to the requested start address (in my case $0600) With C, this is done by either explicitly setting segments, or, if you don't need specific address alignments (I don't, as I am not using a charset for example), then I can either specify a variable stay in ROM by doing: const unsigned char some_table[512]={ 0x00, 0x01, 0x02, 0x03 ... }; versus something that will start in ROM, but be copied to RAM by the runtime: unsigned char buf[512]={0x00, 0x01, 0x02 ...}; In C, this is put into the initialized data segment (commonly called DATA), and while it is stored on ROM, the contents are pushed over when the program starts, before being handed off to main(). Whereas if something is defined as: unsigned char some_state; This is what is known as uninitialized data, and in C this goes into what is called the BSS segment. The memory space is reserved relative to the starting address of your program. (and then there is heap that is allocated/freed over the course of the program, but only if malloc/free are used) As far as I know, ACTION! does not natively do dynamic memory allocation, but it can be implemented. (Honestly, on an 8-bit system, unless you are using something that stays resident in e.g. SpartaDOS X, using dynamic memory allocation is unneeded overhead IMHO) In my case, this cartridge does NOT use CIO, so it does not need an FMS, so it starts up almost immediately (it is not a diagnostic cart, so the OS initializes.), and because of that, the cartridge can literally use memory starting at about $0600 (actually probably as low as $0500), for program temporary variables, and use all of addressable ram for my purposes. Since I am hoping to detect and utilize XL/XE type expansions, this means that most disks will be done in one pass. If no ram expansion, no big deal, a 90K disk will take about 2 passes. It might seem silly as to why I am doing this, but I have two reasons: (1) I saw a hole that I thought needed to be filled, a sector copier that could fit on an 8K cart and therefore be loaded from a U1MB slot really quickly. (2) More examples in C of how to do Atari specific things, Nina's Diary, and Mr. Robot Formatter also fall into this. And ironically, if you include PLATOTERM in this, it serves as a spectrum between something ultra-portable, and something extremely machine specific being written in the same language. It is literally why C has been my lingua franca for almost three decades now, despite having about 40 other languages buried in my skull that I also use. Edited October 25, 2019 by tschak909 3 Quote Link to comment Share on other sites More sharing options...
+Larry Posted October 25, 2019 Share Posted October 25, 2019 Whew! Way more complicated than I thought! Quote Link to comment Share on other sites More sharing options...
sanny Posted October 25, 2019 Share Posted October 25, 2019 8 hours ago, flashjazzcat said: Yes they can. Commonly such 512 byte sectors will be hosted on some PBI device anyway, and most IDE host adapters will ignore the buffer length passed via the DCB and simply transfer the full sector regardless (loops are often unrolled, etc, and observing the buffer length would be fiddly and superfluous). This appears to me like a recipe for desaster. Give back more bytes than the program requested, overrunning buffers? Quote Link to comment Share on other sites More sharing options...
flashjazzcat Posted October 25, 2019 Share Posted October 25, 2019 16 minutes ago, sanny said: This appears to me like a recipe for desaster. Give back more bytes than the program requested, overrunning buffers? I think if an application requests a raw sector from a quad-density volume without allocating sufficient memory for the data (having established disk density using the proper methods), it deserves everything it gets. What would be your proposed alternative? 1 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted October 25, 2019 Author Share Posted October 25, 2019 So, with a bit of assembler massaging, was able to take the memory bank detection code above, and pull it in to be used by cc65. .include "atari.inc" .export _mem_detect, _banks, _bsav ;; Detect extended memory banks for XL/XE systems. ;; Borrowed from: http://atariki.krap.pl/index.php/Obs%C5%82uga_standardowego_rozszerzenia_pami%C4%99ci_RAM ext_b = $4000; anything in the range of $ 4000- $ 7FFF portb = $d301 ; procedure _mem_detect: lda portb pha lda #$ff sta portb lda ext_b pha ldx #$0f; remember bytes ext (from 16 blocks of 64k) _p0: jsr setpb lda ext_b sta _bsav, x dex bpl _p0 ldx #$0f; reset them (in a separate loop, because it is not known _p1: jsr setpb; which PORTB bit combinations choose the same banks) lda #$00 sta ext_b dex bpl _p1 stx portb; elimination of basic memory stx ext_b stx $00; necessary for some extensions up to 256k ldy #$00; loop counting blocks 64k ldx #$0f _p2: jsr setpb lda ext_b; if ext_b is nonzero, the 64k block is already counted bne _n2 dec ext_b; otherwise mark as counted lda ext_b; check if checked; if not -> something is wrong with the equipment bpl _n2 lda portb; enter PORTB into the array for bank 0 sta _banks, y eor #%00000100; complete the values for banks 1, 2, 3 sta _banks + 1, y eor #%00001100 sta _banks + 2, y eor #%00000100 sta _banks + 3, y iny iny iny iny _n2: dex bpl _p2 ldx #$0f; restore content ext _p3: jsr setpb lda _bsav, x sta ext_b dex bpl _p3 stx portb; X = $ FF pla sta ext_b pla sta portb tya ; so it can easily be picked up as return value rts ; subroutines setpb: txa ; bit order change:% 0000dcba ->% cba000d0 lsr ror ror ror adc #$01 ; setting bit 1 depending on the state of C ora #$01 ; setting the OS ROM control bit to the default value sta portb rts ; variables _banks: .res 64 _bsav: .res 16 added a tya before the rts so that the # of banks will be in the accumulator, and be passed as a return value back from mem_detect. Not sure I need bsav exported, I can probably hide that again. And an example of calling from C. /** * Mem detect harness */ #include <stdio.h> extern unsigned char mem_detect(void); extern unsigned char banks[64]; void main(void) { unsigned char num_banks = mem_detect(); unsigned char i; printf("\n\n"); printf("mem detect\n"); printf("----------\n\n"); printf("num_banks: %d\n",num_banks); for (i=0;i<num_banks;i++) { printf("bank[%d]=0x%02x\n",i,banks[i]); } printf("\n\n"); } banks[] contains an array of up to 64 entries containing the necessary complete PORTB values, making bank switching REALLY EASY. as can be seen from this testing harness, this output from being set to RAMBO 1088K: mem detect ---------- num_banks: 64 bank[0]=0xe3 bank[1]=0xe7 bank[2]=0xeb bank[3]=0xef bank[4]=0xc3 bank[5]=0xc7 bank[6]=0xcb bank[7]=0xcf bank[8]=0xa3 bank[9]=0xa7 bank[10]=0xab bank[11]=0xaf bank[12]=0x83 bank[13]=0x87 bank[14]=0x8b bank[15]=0x8f bank[16]=0x63 bank[17]=0x67 bank[18]=0x6b bank[19]=0x6f bank[20]=0x43 bank[21]=0x47 bank[22]=0x4b bank[23]=0x4f bank[24]=0x23 bank[25]=0x27 bank[26]=0x2b bank[27]=0x2f bank[28]=0x03 bank[29]=0x07 bank[30]=0x0b bank[31]=0x0f bank[32]=0xe1 bank[33]=0xe5 bank[34]=0xe9 bank[35]=0xed bank[36]=0xc1 bank[37]=0xc5 bank[38]=0xc9 bank[39]=0xcd bank[40]=0xa1 bank[41]=0xa5 bank[42]=0xa9 bank[43]=0xad bank[44]=0x81 bank[45]=0x85 bank[46]=0x89 bank[47]=0x8d bank[48]=0x61 bank[49]=0x65 bank[50]=0x69 bank[51]=0x6d bank[52]=0x41 bank[53]=0x45 bank[54]=0x49 bank[55]=0x4d bank[56]=0x21 bank[57]=0x25 bank[58]=0x29 bank[59]=0x2d bank[60]=0x01 bank[61]=0x05 bank[62]=0x09 bank[63]=0x0d -Thom Quote Link to comment Share on other sites More sharing options...
tschak909 Posted October 26, 2019 Author Share Posted October 26, 2019 What does a 512 byte sector look like? 3 Quote Link to comment Share on other sites More sharing options...
gozar Posted October 26, 2019 Share Posted October 26, 2019 This looks really cool, and something I could use. Question, can the copier detect the size of the sector of the disk automatically? I'm probably doing something wrong, but the last time I tried to back up some of my personal disks I ran into issues not know which disks are SD, DD, or ED so I missed data. I have a mix of SpartaDOS, DOS 3, DOS 2.5, and MyDOS disks. I'm sure there are others in there... Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.