Shawn Jefferson Posted February 9, 2011 Share Posted February 9, 2011 (edited) If anyone is interested, here is a quick example of outputting text to the VBXE using cc65. Obviously a lot of optimization could be done, this is an example that I was playing around with. I'm going to experiment with a blitter list to clear the screen instead of the plain memset I am using here. PS. I couldn't figure out how to put three blank lines in the XDL, like the DLIST 0x70 (so I actually told the XDL to display 216 lines of text mode, and started the screen three lines before $1000 in the VBXE memory... it was a quick work-around, but not really ideal.) vbxe.zip Edited February 9, 2011 by Shawn Jefferson Quote Link to comment Share on other sites More sharing options...
Rybags Posted February 9, 2011 Share Posted February 9, 2011 Blank lines are easy. At the top of the screen, no attributes, overlay or text are enabled so it's just .BYTE $20,$00,<number of blanks -1> After other stuff like overlay or text, you'll generally want to set the relevant bit that disables whatever feature you've just used, although a usual exception might be attributes since they're used for both GTIA and VBXE graphics. Also I assume you're using the "Constant source data" trick to speed up the blit... when the AND mask is $00, it skips the fetch source phase and just writes whatever you've specified in the XOR mask directly to the destination area. Quote Link to comment Share on other sites More sharing options...
danwinslow Posted February 9, 2011 Share Posted February 9, 2011 Nice! thanks Shawn for sharing this. Quote Link to comment Share on other sites More sharing options...
Dmitry Posted January 9, 2021 Share Posted January 9, 2021 Hi, all, it's been a few years. Some questions about C. These questions probably aren't about VBXE in particular, so anyone that knows C, that'd be willing to answer the question, you'd be helping me out, much appreciate. This example turns on the XDL processing as follows: // turn on XDL processing vbxe->VIDEO_CONTROL = 0x01; From what I'm reading from other Atari age posts, this will actually turn on XDL processing only if vbxe-->VIDEO_CONTROL is set to the memory location for VIDEO_CONTROL. Sadly, the VBXE PDF documentation only refers to the alias and doesn't mention the location. However, another Atari age user posted the address as : $D65E Indeed, using assembly I was able to turn on XDL processing by writing to that address, so it is my belief this is likely correct. However, when I search vbxetest.c, vbxe.h and vbxe.s I do not see where you've ever mentioned this address, so it is a bit of mystery to me how you set the address. Is it an accurate statement that you actually did not set the address in C? I do notice that you initialize vbxe, here: Quote vbxe = (_VBXE_REGS *) vbxe_detect(); And that vbxe_detect procedure appears to be written in assembly and referenced by the magic of cc65. For reference here is vbxe.s .export _vbxe_detect .code _vbxe_detect: ldx #$D6 ; try $D640 first ldy #$40 lda #0 sta $D640 lda $D640 cmp #$10 ; $10 = FX core beq fxcore inx ; try $D740 sta $D740 lda $D740 cmp #$10 ; $10 = FX core beq fxcore lda #0 ldx #0 ; no fx core rts fxcore: tya ; move low byte into a rts obviouisly in this code register x is loaded with immediate value $D6, a value that is not really used in this code for anything. So, it's purpose must be for something else. Anyway - how does this code ensure the VIDEO_CONTROL struct, does in fact reside at $D65E? Quote Link to comment Share on other sites More sharing options...
Dmitry Posted January 9, 2021 Share Posted January 9, 2021 (edited) P.s. I do understand that D640 and D740 may be chosen depending upon the fx core. I'm just more generically asking why the x and a registers are set here. My assumption is x and y register are set because they are used by the C compiler for the location where it allocates the struct in memory. Hopefully I'm not completely off base, but who knowsю Even if my guesswork is correct, I don't know how you get from D640 to D65E, since VIDEO_CONTROL is the first element in the struct. Seems to be a 30 byte offset to account for. Edited January 9, 2021 by Dmitry x and a registers, not x and y Quote Link to comment Share on other sites More sharing options...
Dmitry Posted January 9, 2021 Share Posted January 9, 2021 (edited) ah I'm guessing at somepoint I confused MEMAC control with video control. D640 must be the correct location, not D65E...doh! anyway, nevermind...I will get it turned on in kickC and then post my results. My results will not be optimized at all - but I will attempt to comment each step in turning it on... Edit: p.s. my statement earlier in the thread that the location was not documented - not true. The 2 locations are documented as Dx40 and Dx5E, therefore a search on D640 or D65E fails. one has to substitute x for 6 or 7 depending upon the location vbxe is decoded in atari memory. Edited January 9, 2021 by Dmitry Quote Link to comment Share on other sites More sharing options...
dmsc Posted January 9, 2021 Share Posted January 9, 2021 Hi! 2 hours ago, Dmitry said: obviouisly in this code register x is loaded with immediate value $D6, a value that is not really used in this code for anything. So, it's purpose must be for something else. In CC65, 16 bit values are passed in the X and A registers, X holds the high 8 bits and A the low 8 bits. The vbxe_detect() function returns the address of the VBXE base register, so it returns $D640 or $D740 depending on the location in the Atari memory map. And if no VBXE is detected, it returns 0. 2 hours ago, Dmitry said: Anyway - how does this code ensure the VIDEO_CONTROL struct, does in fact reside at $D65E? The hardware register definitions in the Atari headers for CC65 are defined using structs, the "VIDEO_CONTROL" member resides at the start of the struct, so it is at the same address returned by vbxe_detect, $D640 or $D740. This matches the PDF docs, exactly as needed. Have Fun! Quote Link to comment Share on other sites More sharing options...
mono Posted January 10, 2021 Share Posted January 10, 2021 (edited) Why this code stores $D640/$D740 (VIDEO_CONTROL)? Edited January 10, 2021 by mono Quote Link to comment Share on other sites More sharing options...
Rybags Posted January 10, 2021 Share Posted January 10, 2021 The X register is what's important there. It'll be $D6 or $D7 indicating the base page if VBXE is installed or $00 if it isn't. A, Y will hold $40 if VBXE is installed otherwise A = $00. Quote Link to comment Share on other sites More sharing options...
Dmitry Posted January 10, 2021 Share Posted January 10, 2021 Thanks all it is clear. I don't know if kickC has the equivalent of cc65 passing of x and a registers or not. But I just defined the struct in a header file, which I called ATARI_VBXE and then struct ATARI_VBXE * const vbxe = 0xd640; or, I would do a check and use 0xd740 instead, as the case may be. I didn't run the original program, but I found my port of it, at least didn't really clear the whole vbxe screen memory but left a lot of garbage at the top. So I cleared a section of vbxe memory moved the start of the vidmemory location to the cleared area and ultimately made the text area a little smaller so that my overlay was cleared. I kind of had hoped to do something someone using kickC might find useful, but there is little chance of that, but anyway...so no upload after all. Defeat! lol, well maybe I'll get back to it. Quote Link to comment Share on other sites More sharing options...
Alfred Posted January 10, 2021 Share Posted January 10, 2021 In KMK's example program, it looks like he uses the blitter to scroll. Is there any reason to do that, besides as a code example, rather than just block moving memory ? It adds some complexity for I'm not sure what benefit, it's not like a code editor needs that kind of high performance ? Quote Link to comment Share on other sites More sharing options...
drac030 Posted January 11, 2021 Share Posted January 11, 2021 On 1/10/2021 at 4:17 AM, Alfred said: Is there any reason to do that, besides as a code example, rather than just block moving memory ? I guess that if I used the simple CPU loop, someone would come and ask why I did not use the blitter. The display 80x24 is 3840 bytes. A vanilla copy loop uses ~16 CPU clocks per byte copied: 80*23*2*16 = 58880 clock cycles, plus about 1760 for clearing one row and stuff. This is much more than one VBL, nearly two, in PAL, and like more than two in NTSC. Blitter - two clock cycles per byte copied 80*23*2*2 = 7360, plus 160 clocks for clearing one row, plus 3*21 clock cycles for BCB fetch = ~7600 cycles. Of the 14 MHz clock, so in fact this is 7600/8 = 950 CPU clock cycles (~8 scanlines). The blitter is just made to do such stuff. 4 Quote Link to comment Share on other sites More sharing options...
+Stephen Posted January 11, 2021 Share Posted January 11, 2021 28 minutes ago, drac030 said: I guess that if I used the simple CPU loop, someone would come and ask why I did not use the blitter. The display 80x24 is 3840 bytes. A vanilla copy loop uses ~16 CPU clocks per byte copied: 80*23*2*16 = 58880 clock cycles, plus about 1760 for clearing one row and stuff. This is much more than one VBL, nearly two, in PAL, and like more than two in NTSC. Blitter - two clock cycles per byte copied 80*23*2*2 = 7360, plus 160 clocks for clearing one row, plus 3*21 clock cycles for BCB fetch = ~7600 cycles. Of the 14 MHz clock, so in fact this is 7600/8 = 950 CPU clock cycles (~8 scanlines). The blitter is just made to do such stuff. Sorry to go a little off-topic (and sorry again if this is a dumb question), but since we're discussing the blitter. Let's say I'm in a graphics mode (320*200) with an image covering the entire screen, and I use the blitter to move an object on the screen. Am I responsible for saving and restoring the image "behind" what is being blitted or does the blitter do this automatically? I've currently only used your S_VBXE.SYS driver in text mode, but am wanting to do a bit more graphical stuff. Quote Link to comment Share on other sites More sharing options...
drac030 Posted January 12, 2021 Share Posted January 12, 2021 9 hours ago, Stephen said: Am I responsible for saving and restoring the image "behind" what is being blitted ... ? I have never done that (yet), but I guess so: 1) copy the "square" that covers the sprite area to a safe place using mode 0, 2) copy the sprite shape to the screen using mode 1, 3) restore the background using mode 0. The first two operations can be done with one blit-list consisting of two consecutive BCBs. At least that would be my first thought, how to do that 1 Quote Link to comment Share on other sites More sharing options...
Rybags Posted January 12, 2021 Share Posted January 12, 2021 Save/restore is up to the programmer. Alternatively if the sprite objects are all that VBXE bitmap is being used for you could just do an erase operation. Of course when doing these they should be done in the same sequence for your active objects to prevent garbage appearing. 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.