JamesD Posted February 7, 2012 Share Posted February 7, 2012 (edited) Compute magazine publish source to GET and PUT functions in assembly language. The article was in issue 91, December 1987 The original source hid part of the assembly as just bytes, but I hand disassembled that part of the code and included it. It's bound to have errors in the disassembly and the branches need labels, but I thought I'd pass on what I had in case someone has a use for it or wants to finish what I started. See the article for full details. FYI, some instructions start in one BYTE statement and finish in the next. Tabs may have gotten eaten by the look of the code. ;Compute Issue 91 Dec 87 XLSB = 214 XMSB = 215 YLSB = 216 YMSB = 218 LENGTH = 219 BYTESLSB = 220 BYTESMSB = 221 IMAGELSB = 222 IMAGEMSB = 223 CMD = 224 *= $FFFF ;Place your program's beginning assembling address here JMP BEGIN GET LDA #0 JMP GP PUT LDA #1 GP STA 227 .BYTE 169,0,133,212,133,213,1 LDA #0 STA 212 STA 213 .BYTE 214,133,225,165,89,101,215,133,226,162 OR (XLSB,X) STA 225 LDA #89 ADC XMSB STA 226 LDX #0 .BYTE 0,228,216,240,32,165,225,24,101,220 CPX YLSB BEQ #32 LDA 225 CLC ADC BYTESLSB .BYTE 133,225,165,226,101,221,133,226,165,215 STA 225 LDA 226 ADC BYTESMSB STA 226 LDA XMSB .BYTE 56,233,1,133,216,165,217,233,0,133 SEC SBC #1 STA YLSB LDA 217 SBC #0 .BYTE 217,169,0,201,0,240,220,228,217,240 STA 217 LDA #0 CMP #0 BEQ #220 CPX 217 .BYTE 6,169,0,201,0,240,214,162,1,160 BEQ #6 LDA #0 CMP #0 BEQ #214 LDX #1 .BYTE 0,196,218,240,81,165,227,201,1,208 LDY #0 CPY YMSB BEQ #81 LDA 227 CMP #1 .BYTE 55,165,224,201,1,208,22,177,222,201 BNE #55 LDA CMD CMP #1 BNE #22 LDA (IMAGELSB),Y .BYTE 0,240,10,177,225,201,0,240,4,169 CMP #0 BEQ #10 LDA (225),Y CMP #0 BEQ #4 .BYTE 1,133,212,177,222,201,0,240,20,165 LDA #1 STA 212 LDA (IMAGELSB),Y CMP #0 BEQ #20 .BYTE 224,201,1,240,10,177,225,201,0,240 LDA CMD CMP #1 BEQ #10 LDA (225),Y CMP #0 .BYTE 4,169,1,133,212,177,222,145,225,200 BEQ #4 LDA #1 STA 212 LDA IMAGELSB STA (225),Y INY .BYTE 169,0,201,0,240,191,177,225,201,0 LDA #0 CMP #0 BEQ #191 LDA 225 .BYTE 240,6,169,1,133,212,177,225,145,222 BEQ #6 LDA #1 STA 212 LDA 225 STA (222),Y .BYTE 169,0,201,0,240,229,228,219,240,35 LDA #0 CMP #0 BEQ #229 CPX 219 BEQ #35 .BYTE 160,0,165,222,24,101,218,133,222,165 LDY #0 LDA IMAGELSB CLC ADC YMSB STA IMAGELSB LDA IMAGEMSB .BYTE 223,105,0,133,223,165,225,24,101,220 ADC #0 ;add the carry bit STA IMAGEMSB LDA 225 CLC ADC BYTESLSB .BYTE 133,225,165,226,101,221,133,226,232,169 STA 225 LDA 226 ADC BYTESMSB STA 226 INX LDA #0 .BYTE 0,201,0,240,191,96 CMP #0 BEQ #191 RTS ;Begin your assembly language program at line 1400 ; To use the routine, just store your values into the appropriate variables and do a 'JSR GET' or 'JSR PUT' BEGIN Edited March 9, 2012 by JamesD Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted February 7, 2012 Share Posted February 7, 2012 No offense, but it's useless without doing positioning as well (i.e. to work with individual bytes in random-access files). To read or write files in their entirety, it's speedier to use the SIO routine. After opening the file, flow value ($07 for read, $0B for write) is placed in $352, start address goes in $354/5, length in $358/9. Load A and X with $10, then JMP $E456. Quote Link to comment Share on other sites More sharing options...
Rybags Posted February 7, 2012 Share Posted February 7, 2012 GET/PUT in CIO can be byte or record oriented. If the buffer length = 0 then it's a byte per call through the A register. You'd be better off just consulting the OS manual. CIO calls are pretty easy. X register = IOCB index (0, $10, $20 etc) Then just set the command byte, buffer address, buffer length, aux1, aux2 when necessary before each call. On return, Y contains the return code. >= $80 = error, 1=OK. In some situations, 2=last byte before EOF. For OPEN you supply the filespec. Typical example .byte "E:",$9B Quote Link to comment Share on other sites More sharing options...
JamesD Posted February 7, 2012 Author Share Posted February 7, 2012 It's graphics commands for software sprites like Extended Color Basic, not GET/PUT file I/O. Quote Link to comment Share on other sites More sharing options...
Rybags Posted February 7, 2012 Share Posted February 7, 2012 CIO isn't really suited for screen I/O for moving objects. For a softsprite, you'd need to position the cursor for each line then output the number of bytes = width of sprite. Sure, you can do record I/O but it's a time-wasting exercise. CIO calls the S: handler once per byte then S: throws away most of the byte just to get a single pixel colour. I doubt you'd even get a single 4x8 pixel bitmap object moving in under a frame, and you've still to worry about the save/restore of background data. You could benchmark CIO for a "best case scenario" - just OPEN S: with the graphics mode you want, then output a constant pixel value. You'd probably find the screen fills not much quicker in Assembly than if you had a couple of PUT #6 statements inside a loop in a Basic program. Quote Link to comment Share on other sites More sharing options...
JamesD Posted February 7, 2012 Author Share Posted February 7, 2012 It has nothing to do with CIO Rybags. GET grabs a square of screen data and places it in a buffer, PUT writes data from a buffer to the screen. Quote Link to comment Share on other sites More sharing options...
Rybags Posted February 8, 2012 Share Posted February 8, 2012 It goess through CIO so it has a lot to do with it. You can use the CIO "Put Character" routine directly by getting the address from the handler's vector table but you have to use CIO for Get operations. Quote Link to comment Share on other sites More sharing options...
JamesD Posted February 8, 2012 Author Share Posted February 8, 2012 It goess through CIO so it has a lot to do with it. You can use the CIO "Put Character" routine directly by getting the address from the handler's vector table but you have to use CIO for Get operations. Where does the code use CIO? Quote Link to comment Share on other sites More sharing options...
Rybags Posted February 8, 2012 Share Posted February 8, 2012 Anything through $e456 is CIO. Resident device handlers are in a way part of CIO as well. Whether you take the CIO route or deal direct with the handler, you're still going to have the speed problem. Screen I/O is just too slow to be useful for anything other than a graphical adventure with low detail pictures. Quote Link to comment Share on other sites More sharing options...
JamesD Posted February 8, 2012 Author Share Posted February 8, 2012 Anything through $e456 is CIO. Resident device handlers are in a way part of CIO as well. Whether you take the CIO route or deal direct with the handler, you're still going to have the speed problem. Screen I/O is just too slow to be useful for anything other than a graphical adventure with low detail pictures. You didn't answer my question. Where in the code does it call CIO? Quote Link to comment Share on other sites More sharing options...
Rybags Posted February 8, 2012 Share Posted February 8, 2012 The code is practically unreadable. Byte directives which continue from the program. The call doesn't necessarily have to go through $e456. For the Put Character routine, the direct call sequence is to push the address onto the stack and do an RTS. Anyway, what are you trying to do? Are you asking for help or just arguing the point that something uses CIO or not? Quote Link to comment Share on other sites More sharing options...
phaeron Posted February 8, 2012 Share Posted February 8, 2012 I think the confusion came about because people were thinking this routine was an analog of the BASIC GET and PUT commands, which are CIO based. This function indeed doesn't have anything to do with I/O. However, either you're supposed to poke values into the code or it wasn't written by an experienced author, as it has a lot of wasteful CMP #0 instructions in it and a totally inexplicable LDA #0 / CMP #0 sequence. LDA #$00 STA $D4 STA $D5 ORA ($D6,X) STA $E1 LDA SAVMSC+1 ADC $D7 STA $E2 LDX #$00 L5012 CPX $D8 BEQ L5036 L5016 LDA $E1 CLC ADC $DC STA $E1 LDA $E2 ADC $DD STA $E2 LDA $D7 SEC SBC #$01 STA $D8 LDA $D9 SBC #$00 STA $D9 LDA #$00 CMP #$00 BEQ L5012 L5036 CPX $D9 BEQ L5040 LDA #$00 CMP #$00 BEQ L5016 L5040 LDX #$01 LDY #$00 L5044 CPY $DA BEQ $5099 LDA $E3 CMP #$01 BNE $5085 LDA $E0 CMP #$01 BNE L506A LDA ($DE),Y CMP #$00 BEQ L5064 LDA ($E1),Y CMP #$00 BEQ L5064 LDA #$01 STA $D4 L5064 LDA ($DE),Y CMP #$00 BEQ L507E L506A LDA $E0 CMP #$01 BEQ L507A LDA ($E1),Y CMP #$00 BEQ L507A LDA #$01 STA $D4 L507A LDA ($DE),Y STA ($E1),Y L507E INY L507F LDA #$00 CMP #$00 BEQ L5044 LDA ($E1),Y CMP #$00 BEQ L5091 LDA #$01 STA $D4 LDA ($E1),Y L5091 STA ($DE),Y LDA #$00 CMP #$00 BEQ L507E CPX $DB BEQ L50C0 LDY #$00 LDA $DE CLC ADC $DA STA $DE LDA $DF ADC #$00 STA $DF LDA $E1 CLC ADC $DC STA $E1 LDA $E2 ADC $DD STA $E2 INX LDA #$00 CMP #$00 BEQ L507F L50C0 RTS Quote Link to comment Share on other sites More sharing options...
JamesD Posted February 8, 2012 Author Share Posted February 8, 2012 The code is practically unreadable. Byte directives which continue from the program. The .BYTE directives were the original code, the hand disassembly for each BYTE line follows it. The call doesn't necessarily have to go through $e456. For the Put Character routine, the direct call sequence is to push the address onto the stack and do an RTS. Anyway, what are you trying to do? Are you asking for help or just arguing the point that something uses CIO or not? No, I'm trying to point out that you misunderstood what the code does and have refused to listen to what I'm saying. It's a simple software sprite routine and it has nothing to do with CIO. GET and PUT are not just I/O commands, they are also graphics commands in Extended Color Basic on the TRS-80 Color Computer and in IBM's GW BASIC. GET grabs a square of pixels and sticks it in memory (BASIC uses an array). PUT copies from that memory back to the screen. The author was just trying to create something similar for the Atari. I typed it in years ago when someone asked about software sprites for BASIC and I thought it might be a good start, but I forgot to post it. Last night I had insomnia and started cleaning things off my old laptop. I ran across the code and decided to hand disassemble the .BYTE portion of the code for something to do. I thought I should post it before I forget about it again. If someone is looking at doing software sprites, they might find it useful. Quote Link to comment Share on other sites More sharing options...
JamesD Posted February 8, 2012 Author Share Posted February 8, 2012 (edited) I think the confusion came about because people were thinking this routine was an analog of the BASIC GET and PUT commands, which are CIO based. This function indeed doesn't have anything to do with I/O. However, either you're supposed to poke values into the code or it wasn't written by an experienced author, as it has a lot of wasteful CMP #0 instructions in it and a totally inexplicable LDA #0 / CMP #0 sequence. Exactly, and yeah, I don't think he was that experienced. <edit> And the use of decimal instead of hex is probably a tipoff as to his experience as well. I'm thinking the LDA #0/CMP #0 was caused by a typo on my part from entering the .BYTE sequence. <edit> on 2nd thought, he's probably using that for a branch always since he used it multiple times. Edited February 8, 2012 by JamesD Quote Link to comment Share on other sites More sharing options...
JamesD Posted February 8, 2012 Author Share Posted February 8, 2012 (edited) He doesn't seem to need the carry bit after those branches so the LDA #0/CMP #0/BEQ could be changed to CLC/BCC. On the 65C02 you could just use BRA. Or am I forgetting a shorter way? Been a couple years since I programmed the 6502. Edited February 8, 2012 by JamesD Quote Link to comment Share on other sites More sharing options...
Rybags Posted February 8, 2012 Share Posted February 8, 2012 lda #0 sets Z so you can always BEQ not needing the CMP #0. Load instructions don't affect the carry. Quote Link to comment Share on other sites More sharing options...
JamesD Posted February 8, 2012 Author Share Posted February 8, 2012 (edited) lda #0 sets Z so you can always BEQ not needing the CMP #0. Load instructions don't affect the carry. But the LDA #0 isn't needed in the code and CLC takes fewer bytes/clocks. I'm not disputing LDA #0/BEQ would work, just saying CLC/BCC is shorter/faster if you must do a branch always. <edit> The exception would be if you need to do an LDA #0 where you are branching to, but in this case, you have to make sure LDA #0 gets executed before you enter the loop the first time. One loop in the code might be able to use that. <edit> And I forgot, if you need the carry bit preserved, you can't exactly go clearing it. Edited February 8, 2012 by JamesD Quote Link to comment Share on other sites More sharing options...
JamesD Posted February 8, 2012 Author Share Posted February 8, 2012 This was brilliant: ..... LDA CMD CMP #$01 BNE L506A ...... L506A LDA CMD CMP #$01 BEQ L507A 1 Quote Link to comment Share on other sites More sharing options...
JamesD Posted February 8, 2012 Author Share Posted February 8, 2012 (edited) Actually, after looking up the original article, it includes everything to use it from BASIC and includes some sample programs. If someone is interested, they should read the article. The code doesn't work exactly like GET/PUT from Extended Basic which worked at the pixel level, this is at the byte level. Here is the Atari BASIC code. I looked through the opcodes and it appears to be different than the assembly version from the article. The author probably tried to protect his code and extend the length of the article. Disassembling this code would probably be more useful. The first 2 lines explain how to call the code. The article describes it in depth. 1000 REM D=USR(ADR(GP$)+GET,X,Y,WIDTH,LENGTH,BYTES PER ROW,ADR(IMAGE$)) 1010 REM D=USR(ADR(GP$)+PUT,X,Y,WIDTH,LENGTH,BYTES PER ROW,ADR(IMAGE$),CMD) 1015 REM COPYRIGHT 1987 COMPUTE! PUBLICATIONS, INC. ALL RIGHTS RESERVED 1020 DIM BP*(244):FOR I = 1 TO 244:READ CODE:GP$(I,I)=CHR$(CODE):NEXT I:LET GET=0:LET PUT=0:RETURN 1021 DATA 104,56,233,6,133,227,104,133,215,104,133,214,104,133,217,104 1022 DATA 133,216,104,104,133,219,104,133,221,104,133,220 1023 DATA 104,133,223,104,133,222,165,227,201,0,240,4,104,104,133,224 1024 DATA 169,0,133,212,133,213,165,88,24,101,214,133,225,165,89,101 1025 DATA 215,133,226,162,0,228,216,240,32,165,225,24,101,220,133,225 1026 DATA 165,226,101,221,133,226,165,216,56,233,1,133,216,165,217,233 1027 DATA 0,133,217,169,0,201,0,240,220,228,217,240,6,169,0,201 1028 DATA 0,240,214,162,1,160,0,196,218,240,81,165,227,201,1,208 1029 DATA 55,165,224,201,1,208,22,177,222,201,0,240,10,177,225,201 1030 DATA 0,240,4,169,1,133,212,177,222,201,0,240,20,165,224,201 1031 DATA 1,240,10,177,225,201,0,240,4,169,1,133,212,177,222,145 1032 DATA 225,200,169,0,201,0,240,191,177,225,201,0,240,6,169,1 1033 DATA 133,212,177,225,145,222,169,0,201,0,240,229,228,219,240,35 1034 DATA 160,0,165,222,24,101,218,133,222,165,223,105,0,133,223,165 1035 DATA 225,24,101,220,133,225,165,226,101,221,133,226,232,169,0,201 1036 DATA 0,240,191,96 Edited February 8, 2012 by JamesD Quote Link to comment Share on other sites More sharing options...
JamesD Posted March 3, 2012 Author Share Posted March 3, 2012 I had a few minutes to mess with this last night. I fixed some typos and missing numbers from the code posted above and included one of the demos. The disassembly is only a little different than before. The code for BASIC pops parameters from the stack. If someone actually decides to use it, the code could be optimized to save some clock cycles. 5 REM COPYRIGHT 1987 COMPUTE! PUBLICATIONS, INC. ALL RIGHTS RESERVED. 8 PRINT "{CLEAR}COPYRIGHT 1987":PRINT "COMPUTE! PUBLICATIONS, INC.":PRINT "ALL RIGHTS RESERVED." 10 DIM A$(3*10*40):A$=CHR$(0):A$(3*10*40)=CHR$(0):A$(2)=A$ 20 GOSUB 1000:I=0:GOTO 65 30 GRAPHICS 7:SETCOLOR 2,8,0:COLOR 3 40 PLOT 9,9:PLOT 0,0:DRAWTO 39,0:DRAWTO 39,P*5+1:DRAWTO 19,P*5+1:DRAWTO 19,40-P*5:DRAWTO 39,40-P*5:DRAWTO 39,39 50 DRAWTO 0,39:DRAWTO 0,0 60 D=USR(ADR(GP$)+GET,0,0,10,40,40,ADR(A$)+(I-1)*10*40) 65 I=I+1 70 IF I=1 THEN P=2:GOTO 30 71 IF I=2 THEN P=3:GOTO 30 72 IF I=3 THEN P=4:GOTO 30 80 GRAPHICS 7:SETCOLOR 2,8,0:X=14:Y=19:I=1:DI=1 90 D=USR(ADR(GP$)+PUT,X,Y,10,40,40,ADR(A$)+(I-1)*10*40,0) 100 IF STRIG(0)<>0 THEN 100 110 I=I+DI 120 IF DI=1 THEN IF I=3 THEN DI=-1:GOTO 140 130 IF DI=-1 THEN IF I=1 THEN DI=1 140 FOR DE=1 TO 30:NEXT DE:GOTO 90 1000 REM D=USR(ADR(GP$)+GET,X,Y,WIDTH,LENGTH,BYTES PER ROW,ADR(IMAGE$)) 1010 REM D=USR(ADR(GP$)+PUT,X,Y,WIDTH,LENGTH,BYTES PER ROW,ADR(IMAGE$),CMD) 1015 REM COPYRIGHT 1987 COMPUTE! PUBLICATIONS, INC. ALL RIGHTS RESERVED 1020 DIM GP$(244):FOR I = 1 TO 244:READ CODE:GP$(I,I)=CHR$(CODE):NEXT I:LET GET=0:LET PUT=0:RETURN 1021 DATA 104,56,233,6,133,227,104,133,215,104,133,214,104,133,217,104 1022 DATA 133,216,104,104,133,218,104,104,133,219,104,133,221,104,133,220 1023 DATA 104,133,223,104,133,222,165,227,201,0,240,4,104,104,133,224 1024 DATA 169,0,133,212,133,213,165,88,24,101,214,133,225,165,89,101 1025 DATA 215,133,226,162,0,228,216,240,32,165,225,24,101,220,133,225 1026 DATA 165,226,101,221,133,226,165,216,56,233,1,133,216,165,217,233 1027 DATA 0,133,217,169,0,201,0,240,220,228,217,240,6,169,0,201 1028 DATA 0,240,214,162,1,160,0,196,218,240,81,165,227,201,1,208 1029 DATA 55,165,224,201,1,208,22,177,222,201,0,240,10,177,225,201 1030 DATA 0,240,4,169,1,133,212,177,222,201,0,240,20,165,224,201 1031 DATA 1,240,10,177,225,201,0,240,4,169,1,133,212,177,222,145 1032 DATA 225,200,169,0,201,0,240,191,177,225,201,0,240,6,169,1 1033 DATA 133,212,177,225,145,222,169,0,201,0,240,229,228,219,240,35 1034 DATA 160,0,165,222,24,101,218,133,222,165,223,105,0,133,223,165 1035 DATA 225,24,101,220,133,225,165,226,101,221,133,226,232,169,0,201 1036 DATA 0,240,191,96 Quote Link to comment Share on other sites More sharing options...
JamesD Posted March 5, 2012 Author Share Posted March 5, 2012 A little demo of my own. Just playing around with it to hint at the potential. Add lines 1000-1036 from the listing above. 10 SIZE = 7*24 20 DIM A$(SIZE):A$=CHR$(0):A$(SIZE)=CHR$(0):A$(2)=A$ 30 GOSUB 1000 40 GRAPHICS 7:SETCOLOR 0,1,0:SETCOLOR 1,6,3:SETCOLOR 2,3,4:SETCOLOR 3,10,5 50 COLOR 2:PLOT 8,0:DRAWTO 16,0:DRAWTO 24,8:DRAWTO 16,16:DRAWTO 8,16:DRAWTO 0,8:DRAWTO 8,0 60 D=USR(ADR(GP$)+GET,0,0,7,24,40,ADR(A$)) 70 FOR I=1 TO 8:READ X:READ Y 80 D=USR(ADR(GP$)+PUT,X,Y,7,24,40,ADR(A$),1) 90 NEXT I 140 GOTO 140 10000 DATA 0,0,4,8,8,16,12,24,0,16,4,24,8,32,12,40 Quote Link to comment Share on other sites More sharing options...
JamesD Posted March 5, 2012 Author Share Posted March 5, 2012 I have zero experience with Atari BASIC prior to this and the code in this post is untested at this point, but it should be at least close to working. By storing the USR code on disk along with it's length and just reading it from the file in your own code it allows alteration of the USR routine with no modifications to any program that uses it. I suppose you could just get the file length instead of storing the length in the file, but by doing this you could store multiple USR routines in a single file. This also has the added benefit of not requiring memory for DATA statements in the code which take more space than the actual USR code. Routine to write the USR data to a disk file. Line 1015 should be altered to calculate the LSB and MSB of the length if LEN is over 255. Attach the DATA code section lines 1021-1036 from above to complete it. 1000 REM WRITE THE LENGTH OF THE USR ROUTINE TO A FILE FOLLOWED BY THE USR ROUTINE 1010 LEN = 244 1015 OPEN #1,8,0,"D:GETPUT.USR": PUT #1,LEN:PUT#1,0 :REM 16 BIT LENGTH OF USR ROUTINE 1020 FOR I=1 TO LEN:READ CODE:PUT #1,CHR$(CODE):NEXT I :CLOSE #1:RETURN Read in the USR code with Atari BASIC. 1000 OPEN #1,4,0,"D:GETPUT.USR": GET #1,LENL : GET #1,LENH : LET LEN =LENL + (256*LENH) 1010 FOR I=1 TO LEN:GET #1,CODE:POKE GP$(I,I)=CHR$(CODE):NEXT I:LET GET=0:LET PUT=0 1020 CLOSE #1:RETURN Read the USR code with BASIC XL, BASIC XE, or Turbo BASIC. The GP$(LEN)=CHR$(0) is there to let basic know the length of the string but I don't know if it's required. 1000 OPEN #1,4,0,"D:GETPUT.USR": GET #1,LENL : GET #1,LENH : LET LEN =LENL + (256*LENH) 1010 DIM GP$(LEN):GP$(LEN)=CHR$(0):BGET #1,ADR(GP$),LEN:LET GET=0:LET PUT=0 1020 CLOSE #1:RETURN Quote Link to comment Share on other sites More sharing options...
JamesD Posted March 6, 2012 Author Share Posted March 6, 2012 I got the basis for this from another thread. It should read the entire USR function in one shot from ATARI BASIC if the original code works as advertised, the read continues from where the GET statements left off, and the AND works the same as other BASIC dialects. I have not tested it yet. 1020-1040 should probably be a separate subroutine if you want to read more than this USR routine in. 1000 OPEN #1,4,0,"D:GETPUT.USR": GET #1,LENL : GET #1,LENH :REM LET LEN =LENL + (256*LENH) 1010 LET ADDRL = ADR(GP$) AND 255: LET ADDRH = ADR(GP$) AND 65280 1020 POKE 852,ADDRL:POKE 853,ADDRH:REM Put low and high address bytes in IOCB #1 1030 POKE 856,LENL:POKE 857,LENH:REM Ditto for low and high length bytes 1040 POKE 850,7:I=USR(ADR("hhh*LVd"),16):REM * and d are inverse video, 7 is the "get" command, 16 is IOCB #1 1050 CLOSE #1:RETURN Quote Link to comment Share on other sites More sharing options...
JamesD Posted March 9, 2012 Author Share Posted March 9, 2012 (edited) Routine to write the USR data to a disk file. Line 1015 should be altered to calculate the LSB and MSB of the length if LEN is over 255. Attach the DATA code section lines 1021-1036 from above to complete it. 1000 REM WRITE THE LENGTH OF THE USR ROUTINE TO A FILE FOLLOWED BY THE USR ROUTINE 1010 LEN = 244 1015 OPEN #1,8,0,"D:GETPUT.USR": PUT #1,LEN:PUT#1,0 :REM 16 BIT LENGTH OF USR ROUTINE 1020 FOR I=1 TO LEN:READ CODE:PUT #1,CHR$(CODE):NEXT I :CLOSE #1:RETURN This was the quickest way I could think of to implement the code to calculate the LSB and MSB of the length of the USR routine automatically. It uses DIV and MOD which just about every BASIC other than standard ATARI BASIC supports. The LSB and MSB could be calculated by hand and hard coded in like the original version of the code above if you want to run it on Atari BASIC. 1000 REM DIV AND MOD ARE NOT AVAILABLE IN STANDARD ATARI BASIC. PICK ANY OTHER BACKWARDS COMPATIBLE BASIC TO RUN THIS 1010 LEN = 244: REM 1015 SHOULD BE ALTERED TO CALCULATE 16 BIT # BYTES IF LEN > 255 1015 OPEN #1,8,0,"D:GETPUT.USR": PUT #1,LEN MOD 256:PUT#1,LEN DIV 256 :REM 16 BIT LENGTH OF USR ROUTINE 1020 FOR I=1 TO LEN:READ CODE:PUT #1,CHR$(CODE):NEXT I :CLOSE #1:RETURN Edited March 9, 2012 by JamesD Quote Link to comment Share on other sites More sharing options...
Rybags Posted March 9, 2012 Share Posted March 9, 2012 Yep, no DIV or MOD but they're not exactly widespread. AND is common though but Atari Basic only uses AND/OR/NOT in a simple boolean mode. The common way of doing such things is: H = INT(A/256) : L = A-H*256 I suppose if you had widespread need to get hi/lo bytes throughout a program you could do it in a couple of USR routines. MOD256$ = " pla / pla / pla / sta $d4 / lda #0 / sta $d5 / rts " DIV256$ = "pla / pla / tax / pla / stx $d5 / lda #0 / sta $d4 / rts " 1 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.