rje Posted December 23, 2021 Share Posted December 23, 2021 I have a two-parter question. 1. How might I dump a screen of PETSCII to a binary file? I print splash screens and similar, storing the content char arrays in C, or sometimes programmatically printing it out. I’d like to store that data in a binary. I’m not sure how to do that from the X16. 2. Then of course I want to write a short asm that prints that to the screen. The only way I think of this is by using FFD2, but maybe there are better ways? Also note problems with my code here! entry: lda clear-screen-code jsr $ffd2 ldx #0 printloop: lda $8000,x cmp $ff or whatever makes sense here beq done jsr $ffd2 inx Uh oh that won’t work because x is only 8 bits.... can I increment A indirectly? jmp printloop. But I know there’s a better way to do that. done: rts Quote Link to comment Share on other sites More sharing options...
Super Administrators TomXP411 Posted December 23, 2021 Super Administrators Share Posted December 23, 2021 (edited) The general solution is to 1. read up on file I/O using KERNAL calls I’ll dig out my ASM directory program for you. It might also be in the file section here 2. use a 16 bit counter. This involves doing the usual INC and checking the carry flag. This opens a file for reading. I believe to write to the file, you'd use CHKOUT at the end. lda #filename_len-filename ldx #<filename ldy #>filename jsr SETNAM lda #FILE_CHANNEL ldx #DEVICE_NUMBER ldy #SECONDARY_ADDRSS_DIR jsr SETLFS jsr OPEN ldx #FILE_CHANNEL jsr CHKIN After that, calls to CHRIN or BASIN would read from the disk channel. To change back to the screen JSR CLRCHN I've attached my directory reader ASM and my labels for your reference. labels.asm dir.asm Edited December 24, 2021 by TomXP411 Quote Link to comment Share on other sites More sharing options...
Greg King Posted December 23, 2021 Share Posted December 23, 2021 (edited) On 12/23/2021 at 12:22 PM, rje said: I have a two-parter question. 1. How might I dump a screen of PETSCII to a binary file? I print splash screens and similar, storing the content char arrays in C, or sometimes programmatically printing them out. I’d like to store that data in a binary. I’m not sure how to do that from the X16. 2. Then of course I want to write a short asm that prints that to the screen. The only way I think of this is by using $FFD2, but maybe there are better ways? Also note problems with my code here! entry: lda clear-screen-code jsr $ffd2 ldx #0 printloop: lda $8000,x cmp $ff; or whatever makes sense here beq done jsr $ffd2 inx ; Uh oh, that won’t work because x is only 8 bits. Can I increment A indirectly? jmp printloop. ; But, I know there’s a better way to do that. done: rts Answer #2: You must read the text through an indirect pointer. Use two nested loops. Increment the index in the inner loop. Increment the high byte of the pointer in the outer loop. entry: lda #clear-screen-code jsr CHROUT lda #<$8000 ldx #>$8000 sta r0 stx r0+1 ldy #0 loop: lda (r0),y beq done jsr CHROUT iny bne loop inc r0+1 bra loop done: rts Edited December 23, 2021 by Greg King 1 Quote Link to comment Share on other sites More sharing options...
Greg King Posted December 23, 2021 Share Posted December 23, 2021 What kind of data do you want to put in a file? Some text before it's printed. Or, something that you programmatically formatted and printed onto the display screen? (If it's the second kind, then you will have screen-codes in VRAM, not PetSCII in main RAM.) Quote Link to comment Share on other sites More sharing options...
ZeroByte Posted December 23, 2021 Share Posted December 23, 2021 (edited) Does VSAVE exist? If so just do that and do VLOAD to put it on the screen. In assembly, VLOAD is: Usual call to SETNAM/ and usual call SETLFS with A=0, X = 8 and Y=0 Then call LOAD with A=2|3 and XY = VRAM address. (A = bank+2) (edited to fix erroneous info) Edited December 26, 2021 by ZeroByte 1 Quote Link to comment Share on other sites More sharing options...
ZeroByte Posted December 23, 2021 Share Posted December 23, 2021 (edited) If no VSAVE then copy the screen tile map data from 00000 to 03FFF into main memory from 5000 Then do a normal call to save giving 5000 to 8FFF as the area to save. SAVE doesn’t work right for HiRAM yet (at least not in the Kernal) which is why I suggested Main memory. Edited December 23, 2021 by ZeroByte 1 Quote Link to comment Share on other sites More sharing options...
Greg King Posted December 24, 2021 Share Posted December 24, 2021 On 12/23/2021 at 6:34 PM, ZeroByte said: Does VSAVE exist? If so just do that and do VLOAD to put it on the screen. In assembly, VLOAD is: Usual call to SETNAM. Call SETLFS with A=2 or 3 (VRAM bank + 2), X = 8, and Y=0. Then call LOAD with A=0 and XY = VRAM address. That's BASIC's way of doing it. In Assembly, SETLFS doesn't take anything in the accumulator for LOAD/SAVE calls. And, the "VRAM bank + 2" is put into the accumulator of the LOAD call (i.e., the 17-bit VRAM address is given directly to the LOAD call). 1 Quote Link to comment Share on other sites More sharing options...
rje Posted December 25, 2021 Author Share Posted December 25, 2021 THANK YOU! Now some more questions. lda #<$8000 ldx #>$8000 Are the < and > operators how we split a word into low and high bytes? Second question. Can I just directly increment a memory location, and use the carry bit to increment the high byte? That might look messier than nested loops... Quote Link to comment Share on other sites More sharing options...
rje Posted December 25, 2021 Author Share Posted December 25, 2021 And, merry Christmas! Quote Link to comment Share on other sites More sharing options...
Stefan Posted December 25, 2021 Share Posted December 25, 2021 (edited) On 12/25/2021 at 4:28 PM, rje said: lda #<$8000 ldx #>$8000 Are the < and > operators how we split a word into low and high bytes? Yes. On 12/25/2021 at 4:28 PM, rje said: Can I just directly increment a memory location, and use the carry bit to increment the high byte? I'm not sure what you exactly mean. However, the INC, INX, INY, and INA opcodes don't affect the carry bit, so I guess the answer is no. In @Greg King's post above, there is a complete code sample using the Y register to walk through the low byte of the address. As may be seen in the sample, wrap around of Y is tested by checking for 0, not carry (the row BNE LOOP in Greg's code). Edited December 25, 2021 by Stefan 1 Quote Link to comment Share on other sites More sharing options...
rje Posted December 25, 2021 Author Share Posted December 25, 2021 Thank you Stefan — I didn’t know that. I had the ADC in mind, if I stored 1 in A, then I’d be incrementing with carry. Then I’d have to BCS or whatever that’s called, which is still messy I suppose. Quote Link to comment Share on other sites More sharing options...
rje Posted December 25, 2021 Author Share Posted December 25, 2021 (edited) Found hints of this on the infowebs... But I may be very wrong. clc Lda #01 adc >my-address adc <my-address Its probably really slow, right? 4 clocks each for the ADC $$$$. Or there’s a fundamental flaw in my logic. Edited December 25, 2021 by rje Quote Link to comment Share on other sites More sharing options...
rje Posted December 25, 2021 Author Share Posted December 25, 2021 This makes me think about SWEET16 Quote Link to comment Share on other sites More sharing options...
Stefan Posted December 25, 2021 Share Posted December 25, 2021 (edited) I guess you could use ADC, but it would be more code and slower. Assuming you are using r0 as zero page vector, this might work (not tested): ldx #<$8000 ldy #>$8000 stx r0 sty r0+1 loop: clc lda r0 adc #1 sta r0 lda r0+1 adc #0 ;Adding carry sta r0+1 lda (r0) ;Indirect addressing mode without Y, not supported by original 6502 beq end jsr $ffd2 ;Print char bra loop end: rts Edited December 25, 2021 by Stefan Quote Link to comment Share on other sites More sharing options...
Ed Minchau Posted December 25, 2021 Share Posted December 25, 2021 (edited) On 12/25/2021 at 8:40 AM, rje said: Found hints of this on the infowebs... But I may be very wrong. clc Lda #01 adc >my-address adc <my-address Its probably really slow, right? 4 clocks each for the ADC $$$$. Or there’s a fundamental flaw in my logic. You're just looking to increment a 16 bit index spread across two bytes. The INC and INX and INY operations set the Z flag if the result is zero and sets the N flag if the most significant bit of the result is 1. So, if your 16 bit value is stored in say zero page addresses 7E (low byte) and 7F (high byte) then INC 7E BNE# 02 INC 7F And @ZeroByte is correct, the easiest way to save something from VRAM to file is to copy it to low RAM and save it from there. Or if it is a big file, copy it to consecutive banks of banked RAM and save it from there. Edited December 25, 2021 by Ed Minchau Quote Link to comment Share on other sites More sharing options...
ZeroByte Posted December 26, 2021 Share Posted December 26, 2021 On 12/23/2021 at 9:53 PM, Greg King said: That's BASIC's way of doing it. In Assembly, SETLFS doesn't take anything in the accumulator for LOAD/SAVE calls. And, the "VRAM bank + 2" is put into the accumulator of the LOAD call (i.e., the 17-bit VRAM address is given directly to the LOAD call). I knew better than that - it's the .A value of LOAD, not SETLFS. Whoops. (fixed my post) Thanks for pointing it out. 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.