Jump to content

Yaron Nir

Members
  • Posts

    508
  • Joined

  • Last visited

Everything posted by Yaron Nir

  1. With the help of my friend @Nir Deri , I was able to test this on a real HW (real Atari with real VBXE installed, with real CRT monitor) Here are the results as shown on the CRT monitor:
  2. good work guys. in my other thread of black belt i was exploring VBXE i was using a python script that extract palette and raw data from an image and compress it. So the produced script produces 3 files: 1. pallete.bin 2. orig.bin 3. compressed.bin In my project i just add palette and compressed files (as original is very big - over 30K), and decompress it in run time into VBXE memory. As the owner of the script is @popmilo and since the script has gone though some iterations, i'll let him share the python file .
  3. ok, continuing exploring VBXE and some playing around, When you press fire button you get to the 'get ready' screen. If someone has a real VBXE hardware installed and test and show results that could be great..... blackbelt.car
  4. wanted to see if i can produce black belt sega mastersystem game title screen. Here is the result for A8 using VBXE: Here is the executable: blackbelt.car if someone can test on real A8 with VBXE and show results that could be great.
  5. looks awesome! can't wait to see your code....
  6. unfortunately, i can't find anything at the moment. i guess i'll wait till you publish the code, then i will build it myself and run it
  7. how do i do that ? sorry for my ignorance....
  8. when i run the atr file i get an endless reboots.... how do i fix this?
  9. @Stephenhow do you work with .vbxe_traceblits? i set it 'on' but don't know what else?
  10. i am gradually editing the steps that is why you see partial work in the first post. i will send a final message once the steps are done
  11. that is a nice thought. I am just experiencing with VBXE so not sure if and how this will go for a full game. wonderboy is in progress but going slowly as there are others involved in this project and there are some setbacks. dragon master is almost ready - for level 1 and once i will be done with VBXE i will release it.
  12. Hello Atarians, I've decided to cancel my VBXE tutorial page and focus on this new thread providing a step by step VBXE code example in MADs assembly. I will try to provide as much detail as possible for each step, and will include the things i have picked up in the last few weeks with the good help of good AA members. Without them this would have been possible. i was trying to document the code as much as possible, so if you find areas that are wrong, or missing or you don't understand, let me know and i will try to do a better job..... The outcome of this step by step example is the following screen: What you see here is a a hi-res colorful sprite (that monster dude in the middle), overlaid on an ANTIC 4 character background (yes, ugly!) screen. here is the executable to try it out in your altirra or a real hardware (if you have VBXE installed): vbxe.xex ok, let's do the steps. Pre-step - Understanding the VBXE concept My recommendation is to read the VBXE manual. yes, it is hard to understand but gives you at a high level review of the VBXE and its controls and registers. In short, the VBXE can be looked at as an additional graphic screen layer on top of the ANTIC screen with its own memory control and registers. As A8 presented limitation for PMGs and colors, with VBXE you can create hi res colorful graphics and sprites. One thing I will definately use VBXE for is to write games that has Antic 4 background and as many sprite as I want in VBXE. VBXE memory is 512KB. The memory concept is that, you set a RAM A8 memory pointing to a VBXE virtual memory. The RAM memory is called MEMAC (which is short for memory access). You can freely choose where this RAM memory will reside and how big will it be (4 available sizes: 4KB, 16KB, 32KB, 64KB). To operate in this mode you will need to work with MEMAC-A. On the other hand, there is already a pre-defined RAM memory area and fixed size with the address of $4000 and size of $4000 = 16KB. You will need to work with MEMAC-B for that. In my example, I will work with MEMAC-A, meaning I will set the memory address and size of the RAM. Note: This RAM access is mostly referred as MEMAC window. Although this window is not really visible , it will be your direct communication with VBXE memory. Step 1 - Detecting VBXE Here is a code snippet of a routine(s) written in MADS assembly to detect the VBXE: ;********************************************************* ; proc name: check_vbxe ; purpose: as VBXE board has few versions, we need to ; check if locations $D600 or $D700 are used ; if not --> vbxe is not installed ;********************************************************* .proc check_vbxe ; set $D600 into base address ZP variable mwa #VBXE_D600 VBXE_BASE_ADDR jsr detect_vbxe beq exit_check ; if $D600 was not recognized, check $D700 inc VBXE_BASE_ADDR+1 jsr detect_vbxe beq exit_check ; no VBXE installed --> set to 0 mva #$00 VBXE_BASE_ADDR exit_check rts .endp ;check_vbxe ;********************************************************* ; proc name: detect_vbxe ; purpose: check major (core) and minor versions at ; locations base+40 and base+41 respectively ;********************************************************* .proc detect_vbxe ; check FX 1.xx (location $40) ldy #VBXE_CORE_VERSION lda (VBXE_BASE_ADDR),y cmp #$10 bne exit_detect ; check minor version (location $41) ldy #VBXE_MINOR_VERSION lda (VBXE_BASE_ADDR),y ; the following and was recommended to do in ; the VBXE documentation to avoid minor version differences and #$70 cmp #$20 exit_detect rts .endp; detect_vbxe So, the first step is to check if VBXE is installed. it could be installed in either $D600 or $D700 memory address locations. If it is not, your app can not work and you need to display an error message and exit. From the documentation the way to check if VBXE is installed is as follows: That is what the code above does, it compares the CORE register (base+$40) with $10 and the moves to check the minor version. From the documentation: That is what the code above does. load the minor register (base +$41) AND with $70 and compare with $20. if none of the above works (for both addresses $D600 and $D700) - no VBXE is installed. once VBXE is detected either in $D600 or $D700 , we store the address in a zero page variable that will be acting as he base address for all VBXE registers. it will be easier later on to load into Y register the desired register load the value into accomulator and store it with y index. example: ldy #VBXE_REGISTER lda #VALUE sta (VBXE_BASE_ADDR),y Step 2 - Disable XDL Here is a code snippet of a routine(s) written in MADS assembly to disable XDL: ; call to disable the XDL enable_xdl #VBXE_VIDEO_CONTROL_XDL_DISABLED . . . . ; call to enable the XDL enable_xdl #VBXE_VIDEO_CONTROL_XDL_ENABLED ;********************************************************* ; proc name: enable_xdl ; parameters: 0=disable, 1=enable ; purpose: sets 0/1 in VBXE video control to enable ; or disable the display ;********************************************************* .proc enable_xdl(.byte x).reg ; x-reg holds enable/disable ; enable/disable XDL ldy #VBXE_VIDEO_CONTROL txa sta (VBXE_BASE_ADDR),y rts .endp ; enable_xdl Setting the VBXE_VIDEO_CONTROL (base+ $40, yes same as the core version, but it is not 'write' rather than 'read') with 0 will disable the XDL and with 1 will enable the XDL. XDL is the display list of VBXE (short for extended display list). it is a list of display controls that basically define the VBXE overlay screen. disabling XDL before do anything else is same as turning ANTIC off. you don't want to see graphics gibberish appearing on screen due to memory setup. Step 3 - Set up VBXE memory access Here is a code snippet of a routine(s) written in MADS assembly to setup the memory access: ;********************************************************* ; proc name: setup_vbxe_memac ; purpose: set up MEMAC-A memory for VBXE ; that means set the address space for it ; choose the access (CPU/VBXE) ; and choose the memory size ;********************************************************* .proc setup_vbxe_memac ;------------------------------------------------------- ; set MEMAC-A memory ; set the MEMAC-A window address ; set CPU access ; set 4K size ;------------------------------------------------------- ldy #VBXE_MEMAC_CTRL lda #(>VBXE_MEMC_WINDOW + MEMC_CPU_ENABLE + MEMC_SIZE_4K) sta (VBXE_BASE_ADDR),y rts .endp ; setup_vbxe_memac As mentioned in the pre-step paragraph, the memory access MEMAC-A allows the developer to define on his own where the RAM of the VBXE memory access will reside. in the code example above I chose VBXE_MEMAC_WINDOW address to be $9000 so I enter the high byte order of this address hence the '>' before the address constant. I am adding the state "CPU ENABLED" and that means that VBXE will be accessed by the CPU. I am also adding the size of the VBXE memory access RAM which is 4KB. Besides CPU access there is also ANTIC access so this value can be either CPU or ANTIC or both (CPU & ANTIC) or none. common practice is to set the MEMAC RAM memory to location $8000. I chose $9000 just from a convenient perspective. Now that we have the VBXE memory access RAM in place (starting at $9000 and with the size of $1000=4KB), that means that the VBXE virtual memory (the entire 512 KB) will be divided into chunks of 4KB, where each chunk will be access through the VBXE memory access ram that point each time to a different virtual location in the VBXE memory space area. the switching between these chunks occurs with bank selection. If the VBXE address space is between $000000-$080000 , if we want to access address $00F000 for example, then we need to switch to bank $0F each bank is aligned to $1000 and if we want to access address $0004DE0 then we switch to bank $04. Step 4 - Set up VBXE XDL Here is a code snippet of a routine(s) written in MADS assembly to setup the VBXE XDL: ;********************************************************* ; proc name: setup_vbxe_xdl ; purpose: the XDL defines the screen type ; resolution, scanlines and other ; copy xdl data to MEMAC memory window ; and setup xdl addressed in the vbxe memory ; address space ;********************************************************* .proc setup_vbxe_xdl ; since we're using a standard resolution screen ; with 320x192 pixels, and each pixel takes 1 byte ; the standard resolution screen will take ; the address space $000000-$00EFFF (size of $F000) ; in the VBXE memory address space ; so anything else beside the screen memory ; should be above this address (above $00F000) ; to set this address we need to select the proper bank ; each bank is aligned to $1000 ; set XDL to the $00F000 address ; select bank $0F where the XDL will reside ; and enalbe the MEMAC-A window ; store current bank for later use mva #$0F VBXE_CURRENT_BANK ldy #VBXE_MEM_BANK_SEL lda VBXE_CURRENT_BANK clc adc #MEMAC_GLOBAL_ENABLE sta (VBXE_BASE_ADDR),y ; copy the xdl data into the MEMAC-A window address space ; then set the XDL address to point to the VBXE address ; space that will be used for the XDL ldx #(XDL_DATA_LEN-1) loop lda XDL_DATA,x sta VBXE_MEMC_WINDOW,X dex bpl loop ; as explained above, the XDL in VBXE address space will ; reside in $00F000 and on ; but the XDL data was copied to the MEMAC-A window address ldy #VBXE_XDL_ADR0 ; low byte lda #$00 sta (VBXE_BASE_ADDR),y ldy #VBXE_XDL_ADR1 ; mid byte lda #$F0 sta (VBXE_BASE_ADDR),y ldy #VBXE_XDL_ADR2 ; high byte lda #$00 sta (VBXE_BASE_ADDR),y rts .endp ;setup_vbxe_xdl ;----------------------------------------- ; XDL definition XDL_DATA ; top part of screen, overscan lines ; no overlay and repeat for 23 lines dta XDLC_OVOFF | XDLC_MAPOFF | XDLC_RPTL ; first byte dta $0 ; second byte, not used here dta $17 ; repeat data $17=23 ; main part of the screen the ; graphics mode, repeat for 192 scanlines ; setting overlay address $000000 and step dta XDLC_GMON | XDLC_MAPOFF | XDLC_RPTL | XDLC_OVADR ; first byte dta XDLC_ATT | XDLC_END ; second byte dta $BF ; repeat $BF=191 dta $00 ; overlay address $000000 dta $00 dta $00 dta $40 ; step $140=320 pixels per line dta $01 dta XDLC_ATT_OV_WIDTH_NORMAL | XDLC_ATT_OV_PALETTE_01 ; NORMAL = 320 pixel, and VBXE window takes colors from palette 1 dta XDLC_ATT_MAIN_PRIORITY_OVERLAY_ALL XDL_DATA_LEN equ *-XDL_DATA This example demonstrate the concept of VBXE and the use of XDL. In my memory layout, the VBXE screen is located at VBXE addresses $000000 till $00F000. The XDL should reside immediate after at address $00F000. in order to point to the address $00F000 , we need to switch the VBXE memory access to "point" to this address. we do this by bank selection (switching to bank $0F). We copy the XDL to reside in this address $00F000 and we set the VBXE XDL address registers to point to this address (3 bytes = low , mid, high) This example what comprises the XDL. The XDL "describes" the VBXE screen that will be used. in my example the screen has 2 parts. a top overscan part (24 scanlines) with no VBXE usage and a standard resolution screen 320x192 pixels, where the VBXE screen address for this screen is set to $000000 VBXE address space, and it will use palette #1 (and not #0 as the we want ANTIC mode 4 playfield colors to still be changed with the ANTIC PF registers) , we also define the VBXE screen priority to be on top of everything else (PMGs and PFs). in XDL, you first define the XDL controls (XDLC) which are basically the attributes you wish to use, then you set the values for these attributes. The first byte sets the XDL controls: VBXE overlay off - no VBXE usage MAPOFF=disable the color map RPTL = repeating it for 23 next scanlines The second byte also sets XDL controls, but i don't need any here so not in use The third byte sets the control values: RPTL =repeat 23 more scanlines all together 24 GMON=set graphics mode rather than text mode with fonts and charset(s) MAPOFF=disable color attributes RPTL = repeat scanlines $BF = 191 lines , in total 192. (always use Desired-1) OVADR = the VBXE screen start address (3 bytes) $00-00-00. ATT = other screen attributes such as screen width normal (320 pixels) and palette use (#1) and priority (over all) END = the last XDL line to indicate its end. will wait for VBLANK and then start again from the top of XDL (same as in ANTIC display list) Step 5 - Set up VBXE Palette Here is a code snippet of a routine(s) written in MADS assembly to setup the VBXE XDL: ;********************************************************* ; proc name: setup_vbxe_palette ; purpose: copy the rgb palette bin file ; data into VBXE memory ;********************************************************* .proc setup_vbxe_palette ; the sprite sheet data contains rgb color data as well ; this is reflected in the palette bin file ; copy the palette bin file data into VBXE rgb registers ; the rgb bin file contains 256 values for ; r,g and b respectively, we copy all of them ; start from palette 1 and color 0 ; palette 1 as we want to use ANTIC background under ; the VBXE and if you choose palette 0 it impact the ; playfield colors of ANTIC ; select palette 1 ldy #VBXE_PSEL lda #1 sta (VBXE_BASE_ADDR),y ; select color 0 ldy #VBXE_CSEL lda #0 sta (VBXE_BASE_ADDR),y ; loop all rgb values ldx #0 loop_rgb ; red ldy #VBXE_CR lda palette_bin,x sta (VBXE_BASE_ADDR),y ; green ldy #VBXE_CG lda palette_bin+$100,x sta (VBXE_BASE_ADDR),y ; blue ldy #VBXE_CB lda palette_bin+$100+$100,x sta (VBXE_BASE_ADDR),y ; color selection (VBXE_CSEL) will increment automatically inx bne loop_rgb rts .endp ;setup_vbxe_palette The code sets the palette to 0 and copy the RGB bin array into the colors registers. there are 256 Reds, 256 Greens, 256 Blues. that is why i use + $100 between each color register. What is the palette? Well, it is the RGB color list that our graphics will use in the VBXE screen. since I am using VBXE to blit sprite on screen, the palette should be the RGB list of colors of the sprite frames. my project contains a file called palette_monster.bin. This file was extracted from my sprite sheet image using a python script. the script reads each pixel in the image and creates the RGB list and convert it into 1 byte array. then you need to copy this byte array of RGB colors into the VBXE palette registers. so first you chose to which palette you want to assign these colors RGBs. I chose palette #1. the reason for that is since i am blitting the sprite over ANTIC mode 4 background, I want to still be able to change the PF colors of that background fields. If I would have chosen palette #0 then the PF color registers would have impacted by the RGB color list I have loaded and that is not good. you also need to set the transparent color RGB. so in my example the sprite is drawn over the ANTIC mode 4 background. I chose black to be the transparent color. Black RGB is 0,0,0. I needed to make sure it was set as the first color in the palette (python script did that) in order for the VBXE use that as the transparency color. Step 6 - Set up VBXE clear screen blitter Here is a code snippet of a routine(s) written in MADS assembly to setup the VBXE clear screen blitter: ;********************************************************* ; proc name: setup_vbxe_clear_screen_bcb ; purpose: set up the ZP_SRC to bcb clear screen data ; set up the vbxe address to $00F00E ; the bank will be $0F as the MEMAC window is set ; to 4K size so all banks addresses are ; aligned with $1000 ;********************************************************* .proc setup_vbxe_clear_screen_bcb ; copy the blitter address to ZP source varialbe mwa #BCB_CLEAR_SCREEN ZP_SRC ; set blitter block to $00F00E mva #$0E VBXE_MEM_ADDR mva #$F0 VBXE_MEM_ADDR+1 mva #$00 VBXE_MEM_ADDR+2 jsr setup_vbxe_blitter_block rts .endp ;setup_vbxe_clear_screen_bcb ;********************************************************* ; proc name: setup_vbxe_blitter_block ; purpose: you need to set before calling this proc ; ZP_SRC and 3 bytes for VBXE_MEM_ADDR ; from the VBXE 3 bytes address ; we take the bank , and set it ; and we set the ZP_DST ; and the 3 bytes blitter address ;********************************************************* .proc setup_vbxe_blitter_block ; source was set before the call to this proc ; set the destination ; the VBXE address is with this format ex. $00-F0-00 ; we need to get the half part of the high byte ; and half part of the mid byte to select the proper ; VBXE bank ; load mid byte lda VBXE_MEM_ADDR+1 ; store it temporary sta ZP_TMP ; load high byte lda VBXE_MEM_ADDR+2 ; 4 shifts 4 rolls to get the half byte and half byte asl ZP_TMP rol asl ZP_TMP rol asl ZP_TMP rol asl ZP_TMP rol ; select the bank for this address of VBXE ; restore current bank back ldy #VBXE_MEM_BANK_SEL ; acc holds the bank clc adc #MEMAC_GLOBAL_ENABLE sta (VBXE_BASE_ADDR),y ; we need to add to the MEMAC-A window the offset ; of the VBXE address lda VBXE_MEM_ADDR sta ZP_DST lda VBXE_MEM_ADDR+1 ; extrac the 3rd digit and #$0F ora #>VBXE_MEMC_WINDOW sta ZP_DST+1 ; loop copy ldy #BCB_SIZE-1 copy_loop lda (ZP_SRC),y sta (ZP_DST),y dey bpl copy_loop ; set the blitter address in VBXE memory address space ; VBXE_MEM_ADDR ldy #VBXE_BL_ADR0 ; low byte lda VBXE_MEM_ADDR sta (VBXE_BASE_ADDR),y ldy #VBXE_BL_ADR1 ; mid byte lda VBXE_MEM_ADDR+1 sta (VBXE_BASE_ADDR),y ldy #VBXE_BL_ADR2 ; high byte lda VBXE_MEM_ADDR+2 sta (VBXE_BASE_ADDR),y ; restore current bank back ldy #VBXE_MEM_BANK_SEL lda VBXE_CURRENT_BANK clc adc #MEMAC_GLOBAL_ENABLE sta (VBXE_BASE_ADDR),y rts .endp ;setup_vbxe_blitter_block ;----------------------------------------------- ; blit data for clear screen ;----------------------------------------------- BCB_CLEAR_SCREEN ; BCB is 21 bytes long ; 3 bytes = no source - ignored dta $00 dta $00 dta $00 ; step Y - each change of Y - ignored dta a($0000) ; step X - each change of X - ignored dta $0 ; the address of the VBXE screen top left dta $00 dta $00 dta $00 ; step Y - screen width in pixels $140 (320) dta a($140) ; step X - 1 pixel dta $01 ; width of blitter to copy dta a($140 - 1) ; height of blitter to copy dta $C0-$1 ; AND mask for source dta $00 ; XOR mask for source dta $00 ; AND mask collision detection - ignored dta $00 ; ZOOM value X-Axis Y-Axis - ignored dta $00 ; Pattern fill - ignored dta $00 ; blt ctrl - ignored dta $00 BCB_SIZE equ 21 What is a blitter? Well, it is a fast way to copy things into memory. the usages are mostly to erase, update and draw the graphics on the VBXE screen. The way the blitter work, is you define a blitter control block and you copy it into the VBXE address space and then set the blitter address to point to the VBXE address space where the blitter resides. In order to copy the blitter into the VBXE address space you will need 2 parameters: source=blitter data to copy destination=the VBXE memory address where the blitter block will reside. This code example for clear screen is used to clear the entire VBXE visible screen. and that means, we place transparent color ($00) into the screen memory of the visible VBXE screen which is from address $000000 to $00F000 (320x192 pixels) Source = our blitter block data Destination= VBXE memory , $00F00E. why do we place it at $00F00E? if you recal we have placed the XDL in the address $00F000. XDL size is with the size of $0D. so we can use $0E low byte as the right place to set the blitter block. we use a zero page address (3 bytes) and we store in it the high, mid and low parts of the address to be used to copy the blitter. As explained in early steps, to access memory we need to switch the bank to point to that memory. in our case the bank is $0F as before. but since my code can interpret any address, we extract the bank from the zero page 3 byte address. We select the proper Bank and also we make sure the MEMAC memory access is enabled (we add this flag to the select bank register). We set the destination in the MEMAC-A access memory to the same offset as we explained above ($0E). We loop and copy the data from source to destination. last thing remaining to do is point the blitter block register to the correct address space in VBXE (including the offset $0E). Each blitter block is always 21 bytes long. source address 3 byte = ignored, as we're clearing the screen there is no source step y 2 bytes = for source, also ignored step x 1 bytes = for source, also ignored add 3 bytes = top left of the VBXE screen (in our case $000000) step y 2 bytes = for our screen, 320 pixels ($140, we always do Desire-1) step x 1 bytes = for our screen, 192 ($C0, we always do Desire-1) AND mask = not in use as we do not have source. keep it $00 XOR mask = the desired outcome, we want to place the transparent color $00 in each byte. so we XOR with this color COLLISION mask = ignored . keep $00 ZOOM = ignored. keep $00. you can use zoom for faster memset operation, but i am not using it here. PATTERN FILL= ignored. keep $00 BLT CONTROL=ignored. keep $00 Step 7 - Start the blitter Here is a code snippet of a routine(s) written in MADS assembly to setup the VBXE clear screen blitter: ;********************************************************* ; proc name: start_blitter ; purpose: once blitter is free (not busy) ; start ;********************************************************* .proc start_blitter ; first wait for blitter busy to finish jsr wait_for_blitter ldy #VBXE_BLITTER_START lda #$01 sta (VBXE_BASE_ADDR),y rts .endp ; start_blitter ;********************************************************* ; proc name: wait_for_blitter ; purpose: read the register BLITTER BUSY ; and wait till its not busy anymore ;********************************************************* .proc wait_for_blitter ; read the blitter busy register ; if it is 0 -->it is ready ldy #VBXE_BLITTER_BUSY do_wait lda (VBXE_BASE_ADDR),y bne do_wait rts .endp ; wait_for_blitter There could be other blitters at work, so we must wait until blitter is ready to be used. we test the blitter busy register (base + $53) , read operation, and when it is 0 the blitter is ready to process another block. to start the blitter we set 1 to the blitter start register (base + $53), this time write operation. Note: It is recommended to clear the screen before your main loop and do it one time only. If you don't clear your screen, you may see garbage appearing and that is not desired. Step 8 - copy sprite sheet data into VBXE memory Here is a code snippet of a routine(s) written in MADS assembly to setup the VBXE clear screen blitter: ;********************************************************* ; proc name: setup_vbxe_sprite_data ; purpose: copy the sprite bin file data ; into MEMAC-A window memory ; take into account the MEMAC-A window size ; you have defined and see if the sprite sheet ; does not exceed that ;********************************************************* .proc setup_vbxe_sprite_data ; copy the sprite into the MEMAC-A VBXE address ; the offset needs to take into account the XDL ; and the blitter blocks so we set the address ; to be the MEMAC-A window address + $100 as offset ; $100 is enough as we only have 2 blitter blocks ; that takes 2x21 = 42 bytes ; set the bin file hi byte address ; into a ZP source variable mwa #sprite_data ZP_SRC ; set the MEMAC-A window + offset($100) address ; into a ZP destination variable lda #0 sta ZP_DST lda #>(VBXE_MEMC_WINDOW + $100) sta ZP_DST + 1 ; loop sprite height ldx #SPRITE_HEIGHT copy_sprite_row_loop ldy #SPRITE_HEIGHT-1 copy_sprite_byte_loop lda (ZP_SRC),y sta (ZP_DST),y dey bpl copy_sprite_byte_loop clc lda ZP_SRC adc #SPRITE_WIDTH sta ZP_SRC lda ZP_SRC + 1 adc #0 sta ZP_SRC + 1 clc lda ZP_DST adc #SPRITE_WIDTH sta ZP_DST lda ZP_DST + 1 adc #0 sta ZP_DST + 1 dex bne copy_sprite_row_loop rts .endp ;setup_vbxe_sprite_data We copy the sprite sheet data into the MEMAC-A memory access area, so we can later create a blitter block to blit it on screen I've placed it in MEMAC-A memory + $100 as it was enough right after XDL and 2 blitter blocks (one will be listed in the next steps). you can use offset at the exact memory point right after XDL ($0D) blitter 1 ($23) blitter 2 ($38) so you could place it in base+$39 if you want. source = sprite data. what is that? it is a bin file created outside the program using python again and basically reading the image and getting the pixels from it and storing it in a byte array. we copy the byte array into MEMAC-A memory access addresses. each sprite has a width and a height. there could be several frames per sprite in one sprite sheet. It is recommended to set all your sprite of the game in one sheet so you can set the color palette and sprite data once. destination=MEMAC-A memory access + $100. Now whenever we want we can blit this sprite onto the screen. Step 9 - blit sprite on VBXE screen Here is a code snippet of a routine(s) written in MADS assembly to setup the VBXE clear screen blitter: ;********************************************************* ; proc name: setup_vbxe_sprite_draw_bcb ; purpose: set up the ZP_SRC to bcb sprite draw data ; set up the vbxe address to $00F023 ; each blitter block is 21 bytes and last ; block was set to $00F00E ; the bank will be $0F again as the MEMAC window is set ; to 4K size so all banks addresses are ; aligned with $1000 ;********************************************************* .proc setup_vbxe_sprite_draw_bcb ; copy the blitter address to ZP source varialbe mwa #BCB_SPRITE_DRAW ZP_SRC ; set blitter block to $00F00E mva #$23 VBXE_MEM_ADDR mva #$F0 VBXE_MEM_ADDR+1 mva #$00 VBXE_MEM_ADDR+2 jsr setup_vbxe_blitter_block rts .endp ;setup_vbxe_sprite_draw_bcb ;----------------------------------------------- ; blit data for "sprite" ;----------------------------------------------- BCB_SPRITE_DRAW ; BCB is 21 bytes long ; 3 bytes = address of the sprite data we are copying ; our sprite resides in VBXE memory $00F100 dta $00 dta $F1 dta $00 ; step Y - sprite width for each change of Y dta a(SPRITE_WIDTH) ; step X - step 1 byte each change of X dta $1 ; the address of middle of the VBXE visible screen dta $80 dta $50 dta $00 ; step Y - screen width in pixels $140 (320) dta a($140) dta $1 ; width of blitter to copy dta a(SPRITE_WIDTH - 1) ; height of blitter to copy dta SPRITE_HEIGHT - 1 ; AND mask for source dta $FF ; XOR mask for source dta $00 ; AND mask collision detection dta $00 ; ZOOM value X-Axis Y-Axis dta $00 ; Pattern fill dta $00 dta $01 So once again we create a blitter block this time to copy the sprite data from MEMAC-A + $100 memory space to the VBXE screen address space. let's review the blitter block: (Each blitter block is always 21 bytes long) source address 3 byte = now our source will be our sprite data in VBXE memory address space ($00F100) step y 2 bytes = sprite width (always use Desired-1) step x 1 bytes = always 1 pixel ($1) add 3 bytes = destination middle of the VBXE screen (in our case $005080) step y 2 bytes = step of the scree ($140=320 pixels) to move to the next row to draw the sprite. step x 1 bytes = always 1 pixel ($1) AND mask = $FF, in order not to change the sprite data XOR mask = $00, in order not to change the sprite data COLLISION mask = ignored . keep $00 ZOOM = ignored. keep $00. PATTERN FILL= ignored. keep $00 BLT CONTROL=$1 , the main blitter mode. copy source to destination Don't forget to call: jsr start_blitter In order to start the blitter. Other things in my example to consider The DLIST is ANTIC mode 4. the background charset and map are bin files exported from charpad app. Here is the zipped source code. vbxe_step_by_step_example.zip Just run build command in your IDE and that will compile and runt the example. Special thanks to @popmilo who helped me creating this demo. and also to @phaeronwho helped me overcome some of my hurdles. Hope it will be beneficial to you. Cheers, Yaron
  13. i am cancelling this thread and moving to a step by step VBXE coding example using MADs i think it is a better way of experiencing the VBXE coding rather than reading a boring tutorial/summaries.
  14. here is an example i have been working on in the past few days. i was using VBXE over ANTIC mode 4. the sprite is drawn on VBXE memory area whereas the background is drawn on ANTIC mode 4 area. i had few hurdles along the way and with the help of excellent AA members! I've overcome most of them. i am going to cancel my all summary tutorial thread and create new thread for a VBXE step by step coding example using MADs assembly code. the result of the step by step is what you see below. here is executable: vbxe.xex
  15. ok, work in progress, 6 revisions so far. I am still in my learning curve, but i think the tutorial is shaping up to my satisfactory. i would be happy to receive feedback or mistakes or comments of any sort from anyone, so feel free to share your thoughts or if a section is not clear enough let me know and i will re-write it. i've done that so far for some of the sections as i wasn't happy with the result.
  16. great practice! What I have found to be interesting was, when I had "pressed any key" and the program exited to that default altirra screen, it seemed that VBXE was still on (i could see the special effect). Should there be 'clear VBXE', disable XDL and other cleanup whilst exiting your app?
  17. VBXE Overview Revision History v.0.1 - Jan, 17th 2023 - document created v.0.2 - Jan, 17th 2023 - fix formatting v.0.3 - Jan, 19th 2023 - added step by step, added memory access sections, fixed formatting issues v.0.4 - Jan, 20th 2023 - added code definition for the XDL registers v.0.5 - Jan, 24th 2023 - added MADs examples for XDLC controls and chose better phrases for some of the definitions v.0.6 - Jan, 24th 2023 - added XDLC second byte controls explanation What is VBXE? Video Board XE (VBXE) in an Atari 8bit machine hardware add on board which work as a is a piggyback chip in the ANTIC socket. It will work in Any XE (130XE, 65XE, 800XE, XEGS) Atari 8 bit machine and will provide RGB video out for whatever machine you install it in. VBXE device info includes: RGB output providing crisp clear picture using LCD TV or RGB monitor up to 1024 colors on screen from 21 bit palette graphics resolution up to 640x480i (640x240p) in 64 colours, 320x240p in 1024 colours, and 160x240p in 1024 true 80 char mode for text display blitter with 7 modes of operations capable of zooming displayed data, transparency, collision detection and many other features full downward compatible with GTIA chip What are some of the VBXE use cases? Developers use VBXE to enhance their graphics in their programs. There are several nice demos out there which present good graphics with nice resolution and nice colors. There are also few games that were developed using this board capabilities (not many games though, and this is my main purpose of this tutorial, so anyone can develop VBXE new games and ports from other machines and arcade). What I've noticed is (and that is not set in stone, but my own opinion) that VBXE game developers, uses Antic mode 4 (char mode) to draw their game's background and on-top of that use a VBXE layer to draw the sprites. if i am not mistaken, this is how castelvania game works, developed by @Thelen, but i guess only him can confirm How to configure VBXE with your Altirra emulator In your altirra, choose the 'System menu' in the menu bar, and select 'Configure system' in the configure system options, search down for the 'Peripherals' and select 'Devices' On the right side, click the 'add' button to add a new device. search for 'VideoBoard XE (VBXE)' and select to add it. Select the address you wish your VBXE will reside on (either $D600 or $D700). you can just leave the default as-is and click 'OK'. You're all set. just make sure the VBXE was added to your devices list VBXE detection As the first step when writing VBXE program, you must ensure the VBXE was installed successfully on your machine. In order to do that you peek and poke VBXE memory area and check the results. you need to do 2 checks: one for base location $D600 and one for base location $D700. if both fails, it means there is no VBXE installed and you can exit your app as there is no reason to continue. if $D600 check succeeds, you set your VBXE base address to $D600, if it fails you continue to check address $D700. if $D700 check succeeds, you set your VBXE base address to $D700, if it fails, you exit your program. in the step by step section below, you can find a code example on how to detect VBXE. VBXE memory layout address space and banks The VBXE memory size is 512KB. The VBXE memory address space is between $000000 and $7FFFFF The VBXE memory address is being categorized via banks. The VBXE bank size is defined by dividing 512KB with the size we choose for the VBXE window (that 'window' will be discussed below). For example, if we choose the VBXE window size to be 4K then each bank will be 512/4 = 128KB. If we choose the window size to be 8K then each bank will be 512/8 = 64KB etc.... VBXE components and memory layout consideration XDL The extended display list. similar to the ANTIC display list, the XDL defines the screen type. Could be placed anywhere in the VBXE address space but common practice puts the XDL in the the first bank (bank0) starting at VBXE memory $000000. The XDL can be of any size (with the limit of 4K/$1000). XDL size commonly used is 22 bytes but it can vary from few bytes to 5.2KB (22*240 - max of 240 scanlines). It mostly depend on type of screen you wish to create using the VBXE. Will be discussed more in details below. Blitter The Blitter built into the VBXE core allows you to fast copy and fill the virtual RAM areas of any size. The Blitter is controlled by the BlitterList which is a sequence of data loaded into the virtual RAM by the Atari CPU. The BlitterList consists of one or more BCBs (Blitter Control Blocks). The BCB is a set of information for the Blitter. Each BCB defines one blitter operation. A BCB is 21 bytes long. Sprite sheet Holds the width and height size of the sprite sheet for several sprite frames. For example, 5 sprite frames with the size of 12 by 40. you will normally copy your sprites from the sprite sheet to the VBXE screen. Screen ram The screen memory address space. you should consider your screen memory based on the screen resolution and color you select. the screen memory address space should have a read and write access. Buffers Used for any RAM storage. Window The one and only way to communicate with the VBXE is through the VBXE window. The VBXE window must be aligned to a $1000 memory address. The VBXE window has 2 methods of access: A user configurable size (MEMAC-A). A pre-defined size (MEMAC-B). MEMAC-A can be configured to any of the sizes 4KB, 8KB, 16KB and 32KB and could be anywhere in the VBXE address space. MEMAC-B uses a pre-defined size of 16KB and reside on the RAM location $4000-$7FFF Overlay modes These are the screen modes you will use. for screen type there is either graphics type or text type. for resolution there are 3 horizontal modes: LR (Low resolution), SR (Standard resolution) and HR (High resolution). The SR mode is a pixel screen mode that can display 256/320/336 pixels in 256 colors per a scanline. The LR mode is a pixel screen mode that can display 128/160/168 pixels in 256 colors per a scanline. The HR mode is a pixel screen mode that can display 512/640/672 pixels in 16 colors. The vertical mode of the screen is defined by the XDL structure. The XDL The XDL (eXtended Display List) is a list of commands that controls the display of the VBXE. it is similar to the ANTIC display list. The XDL is loaded to the VBXE memory using MEMAC registers and can be loaded to any location inside the 512KB VBXE virtual RAM. There are no limitations on the XDL’s size, and its structure is vertical. After you copy the XDL into the VBXE memory you need to point VBXE address of the XDL to that memory location using the XDL_ADR0, XDL_ADR1, XDL_ADR2 registers. The VBXE will start processing the XDL once the bit XDL_ENALBED will be set to 1 in the VIDEO_CONTROL. setting 0 for this bit in the VIDEO_CONTROL will disable the XDL. it is recommended to disable the XDL at the beginning of the program , before you initialize the VBXE. it is similar to turning off ANTIC display and turning it on once screen was initialized and ready. The XDL structure is comprised from XDLC (XDL Control) which tells the type and nature (control) of the VBXE screen we want to use and an additional data to support the controls. An example of XDL structure can look like this: XDLC (2 bytes) additional data (0-20 bytes) XDLC (2 bytes) additional data (0-20 bytes) ... ... XDLC with the XDLC_END marker (2 bytes) additional data (0-20 bytes) The XDLC is 2 bytes long (word) and it describes the controls the screen would have. XDLC first byte The first byte of the XDLC is comprised out of the following bits: 1. bit 0 - XDLC_TMON, Overlay text mode 2. bit 1 - XDLC_GMON, Overlay graphics mode 3. bit 2 - XDLC_OVOFF, disable overlay 4. bit 3 - XDLC_MAPON, enable color attributes 5. bit 4 - XDLC_MAPOFF, disable color attributes 6. bit 5 - XDLC_RPTL, repeat for the next x scanlines 7. bit 6 - XDLC_OVADR, set the address of the Overlay display memory (screen memory) and the step of the overlay display (how many pixels per line) 8. bit 7 - XDLC_OVSCRL, set scrolling values for the text mode text mode, graphics mode, disable overlay and enable/disable color attributes are XDLC controls that do not have additional data. repeat, overlay address and overlay scroll are XDLC control that do have additional data. XDLC_RPTL With this control, you need to specify the number of scanline that will be exactly the same as you have defined (with the same controls). A MADS assembly example of the control used with additional data, disable the overlay for the next 23 scanlines ($17): XDL dta XDLC_OVOFF | XDLC_RPTL dta $17 XDLC_OVADR With this control, you need to specify 2 addresses: the screen memory, and the screen step for each line. The screen memory is 3 bytes long (the address goes from least significant byte to the more significant byte), the step is 2 bytes long (and goes also from LSB TO MSB). for example, if our screen memory is at location $070800 (in the VBXE 512KB memory space), the 3 bytes will look like this: ADR0=$00,ADR1=$08,ADR2=$07 A MADS assembly example of the control used with additional data, setting screen memory address to $070800 and setting step to 320 ($140) pixels per scanline XDL dta XDLC_GMON | XDLC_RPTL | XDLC_OVADR dta $BF dta $00 dta $08 dta $07 dta $40 dta $01 repeat 192 ($BF) times, set the address to $070800 and set step to 320 ($140) XDLC_OVSCRL With this control, you need to specify 2 bytes: one for HSCROLL and one for VSCROLL. as this control is used with text mode where each character is 8x8 pixels, the first byte (HSCROLL) can use bits 1-7 which indicates the number of pixels scrolled to the left. 0 - means no scroll. the second byte (VSCROLL) works exactly the same but scrolls pixels up. By default, at the top of the screen, hscroll = vscroll = 0. Scrolling values can be changed in every scanline. Setting the XDLC_OVSCRL does not enable the scroll (which is always on), but only sets the VALUES OF THE SCROLLING REGISTERS. These values will be used for every consecutive scanline until the XDL changes them. The horizontal scrolling unit is 1 pixel VBXE hires (or 0.5 pixel GR.8). A MADS assembly example of the control used with additional data, scrolling 1 pixel to the left and no vertical scroll XDL dta XDLC_TMON | XDLC_RPTL | XDLC_OVSCRL dta $BF dta $01 dta $00 Define text graphics mode for 191 scanlines, with horizontal scroll with 1 pixel to the left and no vertical scroll settings. XDLC second byte The second byte of the XDLC is comprised out of the following bits: 1. bit 0 - XDLC_CHBASE, sets the font (text mode) 2. bit 1 - XDLC_MAPADR, sets the address and step of the colour attribute map 3. bit 2 - XDLC_MAPPAR, sets the scrolling values, width and height of a field in the colour attribute map 4. bit 3 - XDLC_ATT, sets the display size(Narrow=256 pixels, Normal=320 pixels, Wide = 336 pixels) the Overlay priority to the ANTIC display and the Overlay color modification 5. bit 4 - XDLC_HR, enables the high resolution mode, works only with graphics mode, 640 pixels with 16 colors supported 6. bit 5 - XDLC_LR, enables the low resolution mode, works only with graphics mode, 160 pixels with 256 colors supported 7. bit 6 - reserved (not is use) 8. bit 7 - XDLC_END, ends the XDL and wait for VSYNC to occur All the XDLC controls in the second byte takes additional data. bit 0 - XDLC_CHBASE With this control, you need to specify 1 byte of the font address. The font should contain 256 characters, 8x8 pixels each and should be loaded into the VBXE memory. the font address must be aligned to 2K address space boundary. max of 256 fonts can be uploaded to the VBXE 512KB virtual RAM. the fonts are stored in memory using the MEMAC registers. Here is a MADs assembly example of font: [TBD] bit 1 - XDLC_MAPADR With this control, you need to specify 2 addresses: the address for the color attribute map (3 bytes) , and the step for each line (2 bytes). The color attribute map may start at any location in the VBXE memory. Here is a MADs assembly example of font: [TBD] bit 2 - XDLC_MAPPAR With this control, you set 4 bytes: scrolling values, width and height of a field in the color attribute map. the bytes order is as follows: 1. hscroll: 0 = line is not scrolled, 1..31 = line is scrolled X pixels to the left. 2. vscroll: 0 = line is not scrolled, 1..31 = line is scrolled X pixels up. 3. width: The width of the field in pixels, range is between 8 and 32 pixels (as in ANTIC GR.8) 4. height: The height of the field in scanlines, range is between 1 and 32 lines hscroll and vscroll for the map should never get greater than the respective values of width and height. Default values (at the top of the screen) are: hscroll = vscroll = 0; height = width = 7; (the field size is 8x8) The field size and scrolling values may be changed in any scanline. The hscroll unit for the map is 1 pixel GR.8. Setting XDLC_MAPPAR does not enable the map to scroll (this function is always on), it only loads the scrolling registers. The values loaded will be used in consecutive scanlines until they are explicitly changed with XDL. Here is a MADs assembly example of font: [TBD] bit 3 - XDLC_ATT With this control, you set 2 bytes: setting the display size (both Overlay and Color map) and Overlay priority to the ANTIC display. And Overlay color modification. The first byte is comprised out of the following bits: 1. bit 0,1: OV_WIDTH, The Overlay width and attribute map width: 00 = NARROW (256 pixels, as ANTIC narrow) 01 = NORMAL (320 pixels, as ANTIC normal) 10 = WIDE (336 pixels, as ANTIC wide. In this mode the display is 8 pixels wider at both sides, than NORMAL) The default (at the top of the screen) width is NORMAL (320 pixels). 2. bit 2,3: not in use. 3. bit 4,5: XDL OV PALETTE, The palette for OVERLAY active from this screen line. By default, OVERLAY uses palette #1 from the top of the screen. 4. bit 6,7: XDL PF PALETTE, The palette for PLAYFIELD and PMG active from this screen line. By default the PLAYFIELD and PMG use palette #0 from the top of the screen. if the attribute map is turned on, the palettes for OVERLAY and PLAYFIELD/PMG are selected by the corresponding attribute maps. The second byte is comprised out of the following bits: bits 0-7 - priority 1. bit 0 - Overlay window over PM0 2. bit 1 - Overlay window over PM1 3. bit 2 - Overlay window over PM2 4. bit 3 - Overlay window over PM3 5. bit 4 - Overlay window over PF0 6. bit 5 - Overlay window over PF1 7. bit 6 - Overlay window over PF2 and PF3 1. bit 7 - Overlay window over COLBK Here is a MADs assembly example of XDLC_ATT for both first and second bytes: XDL dta XDLC_GMON | XDLC_MAPOFF | XDLC_RPTL | XDLC_OVADR dta XDLC_ATT | XDLC_END dta .... ; here data for repeat and overlay addresses . . . ; first byte for XDLC_ATT dta XDLC_ATT_OV_WIDTH_NORMAL | XDLC_ATT_OV_PALETTE_10 | XDLC_ATT_PF_PALETTE_00 ; second byte for XDLC_ATT dta XDLC_ATT_MAIN_PRIORITY_OVERLAY_PM0 | XDLC_ATT_MAIN_PRIORITY_OVERLAY_PM1 | XDLC_ATT_MAIN_PRIORITY_OVERLAY_PM2 | XDLC_ATT_MAIN_PRIORITY_OVERLAY_PM3 | XDLC_ATT_MAIN_PRIORITY_OVERLAY_PF0 | XDLC_ATT_MAIN_PRIORITY_OVERLAY_PF1 | XDLC_ATT_MAIN_PRIORITY_OVERLAY_PF2_PF3 | XDLC_ATT_MAIN_PRIORITY_OVERLAY_COLBK ;----------------------------------------- ; XDLC XDLC_ATT first byte attributes ; OV_WIDTH XDLC_ATT_OV_WIDTH_NARROW equ %00000000 ; (256 pixels) bit 0,1=00 XDLC_ATT_OV_WIDTH_NORMAL equ %00000001 ; (320 pixels) bit 0,1=01 XDLC_ATT_OV_WIDTH_WIDE equ %00000010 ; (336 pixels) bit 0,1=10 ; XDL OV PALETTE XDLC_ATT_OV_PALETTE_00 equ %00000000 ; bit 4,5=00 XDLC_ATT_OV_PALETTE_01 equ %00010000 ; bit 4,5=01 XDLC_ATT_OV_PALETTE_10 equ %00100000 ; bit 4,5=10 XDLC_ATT_OV_PALETTE_11 equ %00110000 ; bit 4,5=11 ; XDL PF PALETTE XDLC_ATT_PF_PALETTE_00 equ %00000000 ; bit 6,7=00 XDLC_ATT_PF_PALETTE_01 equ %01000000 ; bit 6,7=01 XDLC_ATT_PF_PALETTE_10 equ %10000000 ; bit 6,7=10 XDLC_ATT_PF_PALETTE_11 equ %11000000 ; bit 6,7=11 ;----------------------------------------- ; XDLC XDLC_ATT second byte attributes ; MAIN_PRIORITY XDLC_ATT_MAIN_PRIORITY_OVERLAY_PM0 equ %00000001 XDLC_ATT_MAIN_PRIORITY_OVERLAY_PM1 equ %00000010 XDLC_ATT_MAIN_PRIORITY_OVERLAY_PM2 equ %00000100 XDLC_ATT_MAIN_PRIORITY_OVERLAY_PM3 equ %00001000 XDLC_ATT_MAIN_PRIORITY_OVERLAY_PF0 equ %00010000 XDLC_ATT_MAIN_PRIORITY_OVERLAY_PF1 equ %00100000 XDLC_ATT_MAIN_PRIORITY_OVERLAY_PF2_PF3 equ %01000000 XDLC_ATT_MAIN_PRIORITY_OVERLAY_COLBK equ %10000000 bit 4 - XDLC_HR With this control, you enable hi resolution pixel mode. This bit is only taken into account, when XDLC_GMON is 1 (Graphics mode). The HR mode (or hi-res) has a resolution of 640 pixels horizontally for the NORMAL display width and can display 16 colors, from $00 to $0F, in the current Overlay palette. Here is a MADs assembly example of XDLC_HR: TBD bit 5 - XDLC_LR With this control, you enable low resolution pixel mode. This bit is only taken into account, when XDLC_GMON is 1 (Graphics mode). The HR mode (or hi-res) has a resolution of 160 pixels horizontally for the NORMAL display width. The number of displayable colors is the same as in the standard display mode (256). Here is a MADs assembly example of XDLC_LR: TBD bit 6 - not in used Skipped bit 7 - XDLC_END With this control, you end the XDL. This is the last XDL record. it waits for VBLANK. Here is a MADs assembly example of XDLC_END: XDL dta XDLC_GMON | XDLC_MAPOFF | XDLC_RPTL | XDLC_OVADR dta XDLC_ATT | XDLC_END dta ..... Below are all XDLC controls defined, in MADs assembly: ;----------------------------------------- ; XDLC controls definition ;----------------------------------------- ; first byte XDLC_TMON equ %00000001 ; Overlay text mode XDLC_GMON equ %00000010 ; Overlay graphics mode XDLC_OVOFF equ %00000100 ; disable overlay XDLC_MAPON equ %00001000 ; enable color attributes XDLC_MAPOFF equ %00010000 ; disavble color attributes XDLC_RPTL equ %00100000 ; repeat for the next x scanlines XDLC_OVADR equ %01000000 ; set the address of the Overlay display memory (screen memory) and the step of the overlay display (how many pixels per line) XDLC_OVSCRL equ %10000000 ; set scrolling values for the text mode ;----------------------------------------- ; second byte XDLC_CHBASE equ %00000001 ; sets the font (text mode) XDLC_MAPADR equ %00000010 ; sets the address and step of the colour attribute map XDLC_MAPPAR equ %00000100 ; sets the scrolling values, width and height of a field in the colour attribute map XDLC_ATT equ %00001000 ; sets the display size(Narrow=256 pixels, Normal=320 pixels, Wide = 336 pixels) the Overlay priority to the ANTIC display and the Overlay color modification XDLC_HR equ %00010000 ; enables the high resolution mode, works only with graphics mode, 640 pixels with 16 colors supported XDLC_LR equ %00100000 ; enables the low resolution mode, works only with graphics mode, 160 pixels with 256 colors supported ; bit 6 in second byte is not in use (reserved) XDLC_END equ %10000000 ; ends the XDL and wait for VSYNC to occur ;----------------------------------------- ; XDLC XDLC_ATT first byte attributes ; OV_WIDTH XDLC_ATT_OV_WIDTH_NARROW equ %00000000 ; bit 0,1=00(256 pixels) XDLC_ATT_OV_WIDTH_NORMAL equ %00000001 ; bit 0,1=01(320 pixels) XDLC_ATT_OV_WIDTH_WIDE equ %00000010 ; bit 0,1=10(336 pixels) ; XDL OV PALETTE XDLC_ATT_OV_PALETTE_00 equ %00000000 ; bit 4,5=00 XDLC_ATT_OV_PALETTE_01 equ %00010000 ; bit 4,5=01 XDLC_ATT_OV_PALETTE_10 equ %00100000 ; bit 4,5=10 XDLC_ATT_OV_PALETTE_11 equ %00110000 ; bit 4,5=11 ; XDL PF PALETTE XDLC_ATT_PF_PALETTE_00 equ %00000000 ; bit 6,7=00 XDLC_ATT_PF_PALETTE_01 equ %01000000 ; bit 6,7=01 XDLC_ATT_PF_PALETTE_10 equ %10000000 ; bit 6,7=10 XDLC_ATT_PF_PALETTE_11 equ %11000000 ; bit 6,7=11 ;----------------------------------------- ; XDLC XDLC_ATT second byte attributes ; MAIN_PRIORITY XDLC_ATT_MAIN_PRIORITY_OVERLAY_PM0 equ %00000001 XDLC_ATT_MAIN_PRIORITY_OVERLAY_PM1 equ %00000010 XDLC_ATT_MAIN_PRIORITY_OVERLAY_PM2 equ %00000100 XDLC_ATT_MAIN_PRIORITY_OVERLAY_PM3 equ %00001000 XDLC_ATT_MAIN_PRIORITY_OVERLAY_PF0 equ %00010000 XDLC_ATT_MAIN_PRIORITY_OVERLAY_PF1 equ %00100000 XDLC_ATT_MAIN_PRIORITY_OVERLAY_PF2_PF3 equ %01000000 XDLC_ATT_MAIN_PRIORITY_OVERLAY_COLBK equ %10000000 XDLC_ATT_MAIN_PRIORITY_OVERLAY_ALL equ %11111111% You can use the operator OR (|) between the XDLC controls. The VBXE Window methods (MEMAC-A/MEMAC-B) The access to the VBXE is mostly done by defining the memory of the VBXE window. There are 2 methods to define the VBXE window: Method-1: MEMAC-A In MEMAC-A method, the developer sets the VBXE window address. This address can be placed arbitrary inside the 6502 address space and must be aligned to $1000. so it can be from $0000 to $F000. the size of the window is also configured by the developer and it could be one of the following: 1. 4KB ($1000) 2. 8KB ($2000) 3. 16KB ($4000) 4. 32KB ($8000) For example, as a developer I can use MEMAC-A method and define my VBXE window memory address to be $4000 and the size of my window would be 4KB. A MEMAC-A window type can be one of the following: 1. off (standard RAM will be used rather than virtual RAM). 2. on for CPU (CPU sees the virtual RAM, ANTIC sees the standard RAM) 3. on for ANTIC (ANTIC sees the virtual RAM, CPU sees the standard RAM) 4. on for both CPU & ANTIC (both see virtual RAM) MEMAC-A is controlled by 2 registers: 1. MEMAC_CONTROL (MEMC) - this register selects the base address of the VBXE window and also the window size. 2. MEMAC_BANK_SEL (MEMS) - this register decides which part of the virtual RAM is available. what it does is make a specific VRAM bank available. MEMC You should use the MEMAC_CONTROL (MEMC), to enable your VBXE window. The MEMC is one byte and has the following bits: 1. bit 0,1 - r/w sets the window size 00=4KB, 01= 8KB, 10=16KB, 11=32KB 2. bit 2 - r/w (0 only) , MAE - MEMAC ANTIC ENABLE - when set, MEMAC A window will be accessible by ANTIC. 3. bit 3 - r/w (0 only), MCE - MEMAC CPU ENABLE - when set, MEMAC A window will be accessible by 6502. 4. bit 4,5,6,7 - r/w, Base address of MEMAC MEMS You should use the MEMAC_BANK_SEL (MEMS), to select the virtual RAM bank number that will be mapped to the Atari address space. The MEMS is one byte and has the following bits: 1. Bit 0-6 - Selects VRAM bank number that will be mapped into Atari address space. 2. Bit 7 - MGE, MEMAC GLOBAL ENABLE, enables MAMAC-A window as previously defined in MEMAC_CONTROL register. This global enable bit allows to use MEMAC_CONTROL register as configuration only, so the programmer can set it once at the beginning of the code, and use only MEMAC_BANK_SEL register during the run. Method-2: MEMAC-B In MEMAC-B method the VBXE window base address is already set to $4000 and the window size is set to be 16KB ($4000). A MEMAC-B window type can be one of the following: 1. off (standard RAM will be used rather than virtual RAM). 2. on for CPU (CPU sees the virtual RAM, ANTIC sees the standard RAM) 3. on for ANTIC (ANTIC sees the virtual RAM, CPU sees the standard RAM) 4. on for both CPU & ANTIC (both see virtual RAM) MEMAC-B is controlled by the following registers: MEMAC_B_CONTROL (MEMB) - This register selects the base address of the VBXE window and also the window size. MEMAC_B_CONTROL (MEMB) MEMAC-B method window configuration and bank selection is done using the MEMAC_B_CONTROL register (MEMB). This register is write only, and it is a legacy from the previous VBXE core version. The MEMB is one byte and has the following bits: 1. bit 0-4 - write only, The virtual bank number (32 banks, 16kB each gives access to whole 512k of virtual RAM) 2. bit 5 - Not in use 3. bit 6 - write only, MBAE - MEMAC-B ANTIC ENABLE, when set, ANTIC can access the virtual RAM. 4. bit 7 - write only, MBCE - MEMAC-B CPU ENABLE - when set, CPU can access VRAM The VBXE main registers ($40-$5F) The base address of the VBXE is either $D600 or $D700, the following register addresses are offsets to the base address of the VBXE: BASE+40: READ - core version. WRITE - video control BASE+41,42,43: READ - 41=minor version, 42,43=255. WRITE - 3 bytes , XDL address reversed (example: $07800 base_41=$00, base+42=$08, base+43=$07) BASE+44: READ - result 255. WRITE - CSEL (color select) BASE+45: READ - result 255. WRITE - PSEL (palette select) BASE+46,47,48: READ - result 255. WRITE - RGB color (46=CR, 47=CG, 48=CB) BASE+49: READ - result 255. WRITE - COLMASK (color mask) BASE+4A: READ - COLDETECT (collision detection), WRITE - COLCLR (color clear) BASE+4B,4C,4D,4E,4F: READ - result 255. WRITE - N/A BASE+50,51,52: READ - 50=BLT_COLLISION_CODE, 51,52=255. WRITE - BL_ADR0-BL_ADR2 (the blitter list address) BASE+53: READ - BLITTER_BUSY. WRITE - BLITTER_START BASE+54: READ - IRQ_STATUS. WRITE - IRQ_CONTROL BASE+55,56,57,58: READ - result 255. WRITE - P0-P3 (overlay-playfield/pmg priority) BASE+59,5A,5B,5C: READ - result 255. WRITE - N/A BASE+5D: READ - result 255. WRITE - MEMAC_B_CONTROL BASE+5E: READ - MEMAC_CONTROL. WRITE - MEMAC_CONTROL BASE+5F: READ - MEMAC_BANK_SEL. WRITE - MEMAC_BANK_SEL Here is an example in MADs assembly for the VBXE main registers definition: ;------------------------------------------- ; VBXE main registers ; some of the registeres can be r/w VBXE_VIDEO_CONTROL equ $40 ; write VBXE_CORE_VERSION equ $40 ; read VBXE_XDL_ADR0 equ $41 ; write VBXE_MINOR_BERSION equ $41 ; read VBXE_XDL_ADR1 equ $42 ; write VBXE_XDL_ADR2 equ $43 ; write VBXE_CSEL equ $44 ; write VBXE_PSEL equ $45 ; write VBXE_CR equ $46 ; write VBXE_CG equ $47 ; write VBXE_CB equ $48 ; write VBXE_COLMASK equ $49 ; write VBXE_COLCLR equ $4A ; write VBXE_COLDETECT equ $4A ; read ; 4B-4F skipped, no use VBXE_BL_ADR0 equ $50 ; write VBXE_BLT_COLLISION_CODE equ $50 ; read VBXE_BL_ADR1 equ $51 ; write VBXE_BL_ADR2 equ $52 ; write VBXE_BLITTER_START equ $53 ; write VBXE_BLITTER_BUSY equ $53 ; read VBXE_IRQ_CONTROL equ $54 ; write VBXE_IRQ_STATUS equ $54 ; read VBXE_P0 equ $55 ; write VBXE_P1 equ $56 ; write VBXE_P2 equ $57 ; write VBXE_P3 equ $58 ; write ; 59-5C skipped, no use VBXE_MEMAC_B_CONTROL equ $5D ; write VBXE_MEMAC_CTRL equ $5E ; write & read VBXE_MEM_BANK_SEL equ $5F ; write & read ;----------------------------------------- The VBXE implementation step by step Step 1 - check if VBXE is installed as mentioned above, you need to check if the board is installed on your machine or not (or the add-on was added in your emulator). in order to do that you poke the Major and Minor version in VBXE memory. please refer to the example code above if you wish to see how one can detect VBXE. The code below follows the VBXE manual document and check for core and minor versions of the VBXE to determine if it is installed. another method i have seen for checking if VBXE is installed is peeking & poking screen memory area of the VBXE and see results. this methods was used by @Mark2008 and can be found on his VBXE thread. ;********************************************************* ; proc name: check_vbxe ; parameters: none ; output: none ; purpose: as VBXE board has few versions, we need to ; check if locations $D600 or $D700 are used ; if not --> vbxe is not installed ;********************************************************* .proc check_vbxe ; set $D600 into base address ZP variable mwa #VBXE_D600_BASE VBXE_BASE_ADDR jsr detect_vbxe beq exit_check ; if $D600 was not recognized, check $D700 inc VBXE_BASE_ADDR+1 jsr detect_vbxe beq exit_check ; no VBXE installed --> set to 0 mva #$00 VBXE_BASE_ADDR exit_check rts .endp ;check_vbxe ;********************************************************* ; proc name: detect_vbxe ; parameters: none ; output: none ; purpose: check major (core) and minor versions at ; locations base+40 and base+41 respectively ;********************************************************* .proc detect_vbxe ; check FX 1.xx (location $40) ldy #VBXE_CORE_VERSION lda (VBXE_BASE_ADDR),y cmp #$10 bne exit_detect iny ; MINOR_VERSION (location $41) lda (VBXE_BASE_ADDR),y and #$70 cmp #$20 exit_detect rts .endp; detect_vbxe ;------------------------------------------- ; D600/D700 VBXE_D600_BASE equ $D600 VBXE_CORE_VERSION equ $40 VBXE_BASE_ADDR equ $A0 after the call to the check_vbxe, the VBXE_BASE_ADDR will hold either $D600 or $D700 if the VBXE is installed, or $00 if the VBXE is not installed. It is recommended to set the video control to 0 before you do anything else (it disables the XDL). here is a code to disable the XDL: ;********************************************************* ; proc name: disable_xdl ; parameters: none ; output: none ; purpose: xdl_disabled (Disable vbxe display list) ;********************************************************* .proc disable_xdl ldy #VIDEO_CONTROL mva #0 (VBXE_BASE_ADDR),y .endp ; disable_xdl ;------------------------------ VIDEO_CONTROL equ $40 Step 2 - Enable the VBXE window (MEMAC-A/MEMAC-B) Step 3 - Clear VBXE screen memory If your screen memory address for example, is set to be in the address $8000, it should be cleared first (zeroed out). so if you're using a screen memory of 4K then you need to zero the memory from $8000 to $8FFF. here is a code example on how to zero the screen memory using MADs assembly: ;********************************************************* ; proc name: clear_vbxe_sceen_mem ; parameters: none ; output: none ; purpose: put zeros in screen memory starting at $8000 ; and has 4K ($1000) size ;********************************************************* .proc clear_vbxe_sceen_mem ldx #0 lda #0 loop :16 sta VBXE_MEM_SCR+#*256,x Dex bne loop rts .endp ;clear_vbxe_sceen_mem Looping 16 times 256 bytes = 4K and setting 0 in the screen memory address starting at $8000 Step 4 - Load the Extended Display List Copy the XDL structure into VBXE memory. Step 4.1 - define the XDL screen structure you wish to use Here is a code example of XDL definition, creating a graphics screens with 320x192 resolution and setting the graphics screen address to $071000. the screen also defines a top margin area to avoid over-scan : ;-------------------------------------------------------------------------------- xdl ; create top screen margin ; no overlay for 23 ($17) scanlines dta XDLC_OVOFF | XDLC_RTPL ; the next byte data is for the repeat attribute (23 scanlines) dta $17 ; create graphics mode, 320 ($140) pixel over 191 ($BF) scanlines ; and set the graphics screen address to $071000 dta XDLC_GMON | XDLC_RTPL | XDLC_OVADR | XDLC_END ; the next byte data is for the repeat attribute (191 scanlines) ; the attribute for the XDLC_RTPL value dta $BF ; the next 3 bytes are the graphics memory address $071000 reversed ; the attributes for the XDLC_OVADR value dta $00 dta $01 dta $07 ; the next 2 bytes are the graphics step between each scanline 320 pixels ($140) ; the attributes for the XDLC_OVADR value dta $40 dta $01 ;------------------------------------------------------------------------------- xdl_length equ *-xdl Now we need to copy the XDL definition to the VBXE memory. Here is a sample code to do that: [TBD] Step 5 - Load the Palette [TBD] Step 6 - Load the Blitter Control Blocks (BCB) [TBD] Step 7 - Load the Sprite Sheet [TBD] [I will update this frequently till it will be mature enough to become a release candidate document.]
  18. new thread created and summary is in the works. for your convenience -
  19. As requested, i have created a generic thread to discuss the VBXE and to summarize all of its topic. there are few other in-depth threads that cover specific areas of the VBXE so we do not want to interfere with those discussions. special thanks to everyone who chime in and help creating these tutorials. as i consider myself as a VBXE beginner this tutorial will be edit over time, where more and more things will be added until we will create the ultimate user guide (a big challenge by itself). Special thanks to @Stephen , @Mark2008 and @Thelen who did tremendous work so far and to all other atarians who chime in giving more broader picture on the VBXE. the first response to this thread will be my summary so please be patient
×
×
  • Create New...