RegisterSearchFAQMemberlistUsergroupsLog in
XGS_NTSC_TILE_MODE1_V010.S is now jitter free

 
Reply to topic    XGameStation Forum Index » XGS AVR 8-Bit Development System View previous topic
View next topic
XGS_NTSC_TILE_MODE1_V010.S is now jitter free
Author Message
jhbvic20man



Joined: 11 Apr 2009
Posts: 24
Location: Atlanta,GA

Post XGS_NTSC_TILE_MODE1_V010.S is now jitter free Reply with quote
Hi guys and gals,

I have made the graphics driver XGS_NTSC_TILE_MODE1_V010.S jitter free!.
So you won,t need to put the CPU to sleep or have to interrogate certain scan lines to execute code.
All you need is to put a delay at the end of your main loop. I also changed the code that checks for
if your in the inactive or active parts of the screen to indirect jmps. I tested it out using the centipede demo
and it looks great. I'm thinking of adding sound to the driver that shouldn't be to hard. So I have included the
driver so that other people can check it out.


Very Happy jhbvic20man

Code:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Copyright Nurve Networks LLC 2008
//
// Filename: XGS_NTSC_TILE_MODE1_V010.S
//
// Description: 160x192, 20x24, 8x8 tiles resolution NTSC driver tile engine
// 
// Original Author: Andre' LaMothe
//
// Last Modified: 9.1.08
//
// This is a 20x24 NTSC tile engine. Each tile is 8x8 pixels, where each pixel is encoded as a full byte LUMA4:CHROMA4.
//
//
// 20 tiles per row / 24 rows
//
//  colum 0      1       2              17       18       19
// |........|........|........| ... |........|........|........|  Row 0
// |........|........|........| ... |........|........|........|  Row 1
// |........|........|........| ... |........|........|........|  Row 2
// |........|........|........| ... |........|........|........|
// .
// .  24 rows
// .
// |........|........|........| ... |........|........|........|  Row 23
//
// The engine supports fine scrolling in the vertical direction as well as course scrolling scrolling in the
// horizontal direction via a controllable tile map logical width or "pitch" parameter, so eventhough the physical
// screen is always 20x24 tiles the logical width can be anything up to 256 tiles wide.
//
//
// The interface to the tile engine from the C/C++ caller consists of a set of pointers to data structures as well as
// some read/write variables exported from the tile engine that the caller needs to control the engines operation. Here
// are the important variables that the tile engine must have initialized:
//
// .extern tile_map_ptr      // 16-bit pointer to tile map, allows indirection
// .extern tile_bitmaps_ptr  // 16-bit pointer to 8x8 tile bitmaps, allows indirection
//
//
// First, are the tile map, tile bitmap data structures. The tile map is a simple byte array MxN, where each
// byte represents the tile "index" to be rendered at that position. Each index refers to the tile bitmap that should
// be drawn. The tiles themselves are a continguous array of 8x8 pixel (byte) tiles, thus 64-bytes per tile. Both of
// these data structures are referred to by pointers to allow movement of the data structure in real-time. So the
// caller would typically dynamically or statically allocate the tile map and tile bitmaps then point the below pointers
// at them, so the tile engine could locate them
//
//
// Moving on, there are a few values that are EXPORTED out from the tile engine to give the user control of the
// engine as well as indicate the state of the engine (what line its on, etc.), so the user can initiate render
// changes properly as not to disturb the video scan. These values are:
//
//
// .global curr_line                   // int, read only, current physical line
// .global curr_raster_line            // byte, read only, current logical raster line
// .global tile_map_logical_width      // byte, read/write, logical width of tile map
// .global tile_map_vscroll            // byte, read/write, current vertical scroll value 0..7
//
// They are self explanatory. The caller can read curr_line to determine the video line 0..261 of the NTSC scan,
// similarly curr_raster_line indicates the logical raster line for the resolution. Finally, tile_map_logical_width
// allows logical tile maps larger than the 18 wide to support scrolling, and tile_map_vscroll controls smooth
// scrolling vertically.
//
// Modifications|Bugs|Additions:
//
// Author Name:
//
//
//
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SET PROCESSOR TYPE (must come first)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef __AVR_ATmega644__
#define __AVR_ATmega644__
#endif

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// INCLUDES
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
#include <avr/interrupt.h>
#include <avr/io.h>

// include header file for driver
#include "XGS_AVR_NTSC_TILE_MODE1_V010.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DEFINES
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define __SFR_OFFSET 0 // needed for macro, also fixes so you can use register names directly and NOT need macro _SFR_IO_ADDR( x )


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// MACROS
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// this macro delays any number of clocks, uses chunks of 4
.macro  DELAYX reg = r16, clocks
    ldi     \reg, (\clocks)/4        // (1)
1:
    dec     \reg                     // (1)
    nop                              // (1)
    brne    1b                       // (1/2)

    // now delay fractional component
    .rept   (\clocks % 4)
    nop                              // (1)
    .endr

.endm

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// this macro delays any number of clocks that are a multiple of 4, anything else is truncated
.macro  DELAY4X reg = r16, clocks
    ldi     \reg, (\clocks)/4        // (1)
1:
    dec     \reg                     // (1)
    nop                              // (1)
    brne    1b                       // (1/2)
.endm

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// this macro delays any number of clocks that are a multiple of 3, anything else is truncated
.macro  DELAY3X reg = r16, clocks
    ldi     \reg, (\clocks)/3        // (1)
1:
    dec     \reg                     // (1)
    brne    1b                       // (1/2)
.endm

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

.macro COMPUTE_TILE_PTR
        // point Y at bitmap data based on tile index etc.
        // tile_index = tile_map [ tile_index_x... + tile_index_y * 20 ]
        ld      r18, Z+                      // (2), get next tile from tile map

        // tile_bitmap_ptr      = tile_bitmaps_base_ptr + tile_index*64 
        //ldi     r19, 64                      // (1)
        mul     r19, r18                     // (2)  r1:r0 = tile_index*64 

        // note r17:r16 holds tile_bitmaps_base_ptr from above since reading out of vars is too slow
        // thus corruption of Y is ok, since restored below
        add     YL, r0                       // (1)
        adc     YH, r1                       // (1) Y -> tile_bitmaps + tile_bitmap_row*8 + tile_index*64 
                                         
        // now simply insert Y pointer into storage array which will be used during rendering
        st     X+, YL                        // (2), store low byte first
        st     X+, YH                        // (2), now high byte, [low0, high0], [low1, high1]...[lowN, highN]

        // reset Y for next pass
        mov     YL, r16                      // (1)  restore Y, tile_bitmap_base_ptr from r17:r16   
        mov     YH, r17                      // (1)
.endm
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

.macro DRAW_TILE_PIXELS_NTSC_PT0 rt = r0
    // draws a single row of tile bitmap pixels by retrieving the next pointer in the tile bitmap row pointer array
    // then streams out 8 pixels, this macro initiates the process
    // on entry assumes:
    // Y -> pointer array containing pointers to bitmap rows to render for each tile
    // X will be used to retrieve pixels from bitmaps, therefore, save before call   

    // pixel 0, retrieve pointer, draw pixel
    ld      XL, Y+              // (2)
    ld      XH, Y+              // (2) X <- [ Y ], X -> tile bitmap data
    nop                         // (1), do nothing
    ld      \rt, X+             // (2), retrieve next pixel from tile bitmap row
    out     PORTA, \rt          // (1), render to screen
.endm

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

.macro DRAW_TILE_PIXELS_NTSC_PT1 rt = r0
    // draws a single row of tile bitmap pixels by retrieving the next pointer in the tile bitmap row pointer array
    // then streams out 8 pixels, this macro continues the process
    // on entry assumes:
    // X -> pointer array containing pointers to bitmap rows to render for each tile
    // Y will be used to retrieve pixels from bitmaps, therefore, save before call   

    // pixel n, draw pixel
    nop                         // (5)
    nop
    nop
    nop
    nop

    ld      \rt, X+             // (2), retrieve next pixel from tile bitmap row
    out     PORTA, \rt          // (1), render to screen
.endm

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

.macro  RESTORE_SREG reg = r16

    pop     \reg
    out     _SFR_IO_ADDR( SREG ), \reg      // restore status register

.endm

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// LOCAL INITIALIZED VARIABLES (SRAM)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

.section .data

// tile map variables
tile_index_x:             .byte 0
tile_index_y:             .byte 0
tile_bitmap_row:          .byte 0

tile_map_save_ptr:        .byte 0,0
tile_bitmap_base_ptr:     .byte 0,0

// current video line
curr_line:                .byte 0,0   

// current raster line 0..virtual rez-1
curr_raster_line:         .byte 0
raster_line:              .byte 0

// amount of vertical scroll 0..7 (caller controlled)
tile_map_vscroll:         .byte 0

// the logical tile map width, used to access rows, this support horizontal course scrolling, (caller controlled)
tile_map_logical_width:   .byte  TILE_MAP_WIDTH


// tile bitmaps pointer array buffer, 20 tiles, 16-bit pointer for each that points to a bitmap row to render. 2x20 = 40 bytes
tile_bitmaps_ptr_array:   .byte 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0
                          .byte 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0
graphics_driver_jmp:     .word Top_Overscan_Compare
L0A:                 .word L0
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DATA STRUCTURES IN FLASH/ROM - NOTE: MUST ON WORD BOUNDARIES
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

.section .text

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// EXTERNALS
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

.extern tile_map_ptr      // 16-bit pointer to tile map
.extern tile_bitmaps_ptr  // 16-bit pointer to 8x8 tile bitmaps
.extern tile_map_vscroll  // int value of amount of fine vertical scroll 0..7 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// GLOBALS EXPORTS
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// export these to caller, so he can interogate and change
.global curr_line                   // read only, current physical line
.global curr_raster_line            // read only, current logical raster line
.global tile_map_logical_width      // read/write, logical width of tile map
.global tile_map_vscroll            // read/write, current vertical scroll value 0..7

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ASM FUNCTIONS
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

// VGA Interface Reference
//DDRA  = 0xFF; // NTSC/PAL LUMA7:4 | CHROMA3:0, VGA7:0 [vsync, hsync, B1,B0, G1,G0, G1,G0]
//                                                        b7      b6    b5:4   b3:2   b1:0

.section .text

// asm entry point

.global   TIMER1_COMPA_vect 
TIMER1_COMPA_vect:

Save_Regs:

   // save working registers on stack
    push         r0                                     // (2)       
    in         r0, SREG                             // (1)
    push       r0                                   // (2) save the status register
    push         r1                                   // (2)
    push       r16                                  // (2)
    push       r17                                  // (2)
    push       r18                                  // (2)
    push       r19                                  // (2)
    push       r20                                  // (2)
    push       r24                                  // (2)
    push       r25                                  // (2)
    push       r26                                  // (2)   X
    push       r27                                  // (2)
    push       r28                                  // (2)   Y
    push       r29                                  // (2)
    push       r30                                  // (2)   Z
    push       r31                                  // (2)

// latency code
   lds         r16, TCNT1L                           // (2)
   subi      r16, 7 + 33                         // (1)
   lsl         r16                                 // (1)
   lds         ZL, L0A                              // (2)
   lds         ZH, L0A + 1                           // (2)
   clr         r17                                 // (1)
   add         ZL, R16                              // (1)
   adc         ZH, R17                              // (1)
   lsr         ZH                                 // (1)
   ror         ZL                                 // (1)
   ijmp                                       // (2)

L0:

   nop                                          // (1)

L1:

   nop                                          // (1)

L2:

   nop                                          // (1)

L3:

   nop

L4:

   nop

   lds        r24, curr_line                              // (2)
    lds        r25, curr_line + 1                          // (2)     
   lds         ZL,  graphics_driver_jmp                 // (2)
   lds         ZH,  graphics_driver_jmp + 1             // (2)
   lsr         ZH                                  // (1)
   ror         ZL                                  // (1)
   ijmp                                        // (2)   

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*
Brief overview of design. This tile engine is ideal for most games and mixed text displays. The mode supports 20x24 tiles
at 8x8, so. The engine works on a single scanline basis, thus everything has to be done very quickly. The division
of work is between HSYNC/Blank and the active scan regions. In the HSYNC/Blank regions the tile map is interrogated
and the current row of tiles is intersected with the current raster line, the resulting intersections are computed
and the bitmap data from the tile bitmaps is retrieved and stored in an array, thus, the array holds pointers to
all the 8 pixel sets of tile bitmap rows that make up the current scanline. Then during the active scan the data
structure is acceessed, the data retrieved and rendered all in 8 clocks per pixel, exactly matching the color burst
frequency.
*/
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Top_Overscan_Compare:

   cpi      r24, NTSC_VERTICAL_OFFSET - 1                     // (1)
   breq    TO                                          // (1/2)
   .rept ( 7 )
   nop                                                // (1)
   .endr
   rjmp    HSYNC_Period                                 // (2)

TO:   ldi      r16, lo8(Draw_Active_Line_Compare)                  // (1)
   sts      graphics_driver_jmp, r16                        // (2)
   ldi      r16, hi8(Draw_Active_Line_Compare)                  // (1)
   sts    graphics_driver_jmp + 1, r16                     // (2)
   rjmp    HSYNC_Period                                 // (2)

Draw_Active_Line_Compare:   

   cpi      r24, lo8(NTSC_SCREEN_HEIGHT + NTSC_VERTICAL_OFFSET - 1)   // (1)
   breq    DA                                          // (1/2)
   .rept ( 7 )
   nop                                                // (1)
   .endr
   rjmp    NTSC_Draw_Active_Line                           // (2)

DA:   ldi      r16, lo8(Bottom_Overscan_Compare)                   // (1)
   sts      graphics_driver_jmp, r16                        // (2)
   ldi      r16, hi8(Bottom_Overscan_Compare)                  // (1)
   sts    graphics_driver_jmp + 1, r16                     // (2)
   rjmp    NTSC_Draw_Active_Line                           // (2)

Bottom_Overscan_Compare:

   cpi      r24, lo8(256 - 1)                              // (1)
   breq    BO                                          // (1/2)
   .rept ( 7 )
   nop                                                // (1)
   .endr
   rjmp    HSYNC_Period                                 // (2)

BO:   ldi      r16, lo8(Vertical_Sync_Period)                     // (1)
   sts      graphics_driver_jmp, r16                        // (2)
   ldi      r16, hi8(Vertical_Sync_Period)                     // (1)
   sts    graphics_driver_jmp + 1, r16                     // (2)
   rjmp    HSYNC_Period                                 // (2)

Vertical_Sync_Period:

   .rept ( 9 )
   nop
   .endr   
   rjmp    NTSC_Draw_Vsync_Line                           // (2)

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

HSYNC_Period:

    // enable hsync, set video to black
    ldi     r16, NTSC_SYNC           // (1)
    out     PORTA, r16               // (1)

    // test if this is the top of frame here, we need to initialize the rendering kernel
    // if (curr_line == 0) then NTSC_Reset_Kernel
    ldi     r16, hi8(0)              // (1)
    cpi     r24, lo8(0)              // (1)
    cpc     r25, r16                 // (1)

    // now based on flags set above, jump to normal blank line or reset
    breq    NTSC_Reset_Kernel        // (1/2)

    // else delay hsync time (this will be filled with processing in later versions)

    // 16 color clocks sync (128 clocks), this needs to be adjusted correctly to take above computation into consideration
    DELAYX r16, (18*CLOCKS_PER_PIXEL - 8)
   
    // disble hsync, maintain black
    ldi     r16, NTSC_BLACK          // (1)
    out     PORTA, r16               // (1)

    // now color burst
    DELAYX r16, (2*CLOCKS_PER_PIXEL)
   
    ldi     r16, NTSC_CBURST0               // (1)
    out     PORTA, r16                      // (1)

    // now color burst
    DELAYX r16, (10*CLOCKS_PER_PIXEL)

    // back to black HSYNC off
    ldi     r16, NTSC_BLACK                 // (1)
    out     PORTA, r16                      // (1)

    jmp     NTSC_Next_Line           // (3)   

NTSC_Reset_Kernel:

    // reset all data structures each frame at line 0

    // initialize any variables for algorithm   

    // initialize raster_line for next frame, take into consideration vertical scroll value
    lds     r16, tile_map_vscroll            // (2)
    sts     curr_raster_line, r16            // (2)

    // 16 color clocks sync (128 clocks), this needs to be adjusted correctly to take above computation into consideration..
    DELAYX r16, (18*CLOCKS_PER_PIXEL - 12)

    // disble hsync, maintain black
    ldi     r16, NTSC_BLACK                 // (1)
    out     PORTA, r16                      // (1)

    // now color burst
    DELAYX r16, (2*CLOCKS_PER_PIXEL)
   
    ldi     r16, NTSC_CBURST0               // (1)
    out     PORTA, r16                      // (1)

    // now color burst
    DELAYX r16, (10*CLOCKS_PER_PIXEL)

    // back to black HSYNC off
    ldi     r16, NTSC_BLACK                 // (1)
    out     PORTA, r16                      // (1)

    jmp     NTSC_Next_Line                  // (3)

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

NTSC_Draw_Vsync_Line:

    // invert hsync and maintain sync for 4-6 lines
    ldi     r16, NTSC_BLACK   // (1)
    out     PORTA, r16        // (1)

    // delay for hsync pulse length

    // 16 color clocks sync (128 clocks)
    DELAYX r16, (16*CLOCKS_PER_PIXEL)
   
    // disble hsync, but maintain vsync and black
    ldi     r16, NTSC_SYNC   // (1)
    out     PORTA, r16       // (1)

    jmp     NTSC_Next_Line   // (3)

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

NTSC_Draw_Active_Line:

    // (37) for entire setup process..
    // enable hsync, set RGB to black (want approximately 16 color clocks for sync
    ldi     r16, NTSC_SYNC               // (1)
    out     PORTA, r16                   // (1)

    // on entry tile_index_x = 0 for start of scan left to right, line 0,1,2

    // tile_index_y = curr_raster_line / 8, later cache curr_raster_line as well
    lds     r16, curr_raster_line        // (2)    (7) clocks
    lsr     r16                          // (1)
    lsr     r16                          // (1)
    lsr     r16                          // (1)
    sts     tile_index_y, r16            // (2)    r16 = tile_index_y

    // tile_bitmap_row = curr_raster_line mod 8, then multiply by 8, so directly indexes into tile bitmap data, 8 bytes per row
    lds     r17, curr_raster_line        // (2)    (8) clocks
    andi    r17, 0x07                    // (1)   
    lsl     r17                          // (1)    multiply by 8
    lsl     r17                          // (1)
    lsl     r17                          // (1)
    sts     tile_bitmap_row, r17         // (2)    r17 = tile_bitmap_row*8

    // Z  -> tile_map [ tile_index_x=0 + tile_index_y * 20 ]
   
    lds     ZL, tile_map_ptr             // (2), (9) this code for pointer location storage
    lds     ZH, tile_map_ptr+1           // (2)
 
    lds     r18, tile_map_logical_width  // (2)    r18 = 20 constant, 20 tiles per row
    mul     r18, r16                     // (2)    r1:r0 = tile_index_y:r16 * 20:r18

    add     ZL, r0                       // (1)    Z -> tile_map[ tile_index_x=0 + tile_index_y * 20 ]
    adc     ZH, r1                       // (1)    first tile, in current row intersected by current raster line

    // now pre-compute tile_bitmap_base_ptr (might need be needed due to register caching, review later)
    // tile_bitmap_base_ptr = tile_bitmaps + tile_bitmap_row*8
    lds     YL, tile_bitmaps_ptr         // (2), (9) this code for pointer location storage
    lds     YH, tile_bitmaps_ptr+1       // (2)

    clr     r0                           // (1)   Y = tile_bitmaps + tile_bitmap_row*8
    add     YL, r17                      // (1)   r17 = tile_bitmap_row*8 (0..56)
    adc     YH, r0                       // (1)   dummy add to take into consideration carry bit C overflow from lower byte
   
    //sts     tile_bitmap_base_ptr,   YL   // (2)   tile_bitmap_base_ptr = Y
    //sts     tile_bitmap_base_ptr+1, YH   // (2)   global storage variable might not be necessary, since its cached in r17:r16
   
    mov     r16, YL                      // (1)   save tile_bitmap_base_ptr in r17:r16 for transient usage
    mov     r17, YH                      // (1)

    // X -> tile bitmaps base address pointer array
    ldi     XL, lo8( tile_bitmaps_ptr_array ) // (1), (2) this code for pointer location storage
    ldi     XH, hi8( tile_bitmaps_ptr_array ) // (1)

    // initialize constant in r19 = tile bitmap size in bytes
    ldi     r19, 64                           // (1)   

    // setup on entry to tile bitmap pointer conputation and storage, computes pointer to every tile bitmap
    // to be rendered on this row, stores in array
    // X -> tile bitmaps base address pointer array
    // Z -> tile map next tile index entry
    // Y =  tile_bitmap_base_ptr
    // r19 = 64, number of bytes per tile bitmap


    // each pass takes (12) clocks * 20 = 240 clocks, break up into pieces to interleave hsync and color burst
    .rept 9
        COMPUTE_TILE_PTR
    .endr

    // turn HSYNC off, make sure to align with blank and vsync lines total time of hsync pulse, make as short as possible,
    // so other lines can exit out ASAP and return to C
    ldi     r18, NTSC_BLACK                 // (1)
    out     PORTA, r18                      // (1)

    // now begin color burst
    // each pass takes (12) clocks * 20 = 240 clocks, break up into pieces to interleave hsync and color burst
    .rept 2
    COMPUTE_TILE_PTR   
    .endr
    // now turn on color burst 
    ldi     r18, NTSC_CBURST0               // (1)
    out     PORTA, r18                      // (1)

    // now color burst
    // each pass takes (12) clocks * 20 = 240 clocks, break up into pieces to interleave hsync and color burst
    .rept 6
    COMPUTE_TILE_PTR       
    .endr

    // a little more delay for color burst to complete
    // back to black HSYNC off
    ldi     r18, NTSC_BLACK                 // (1)
    out     PORTA, r18                      // (1)

    // each pass takes (12) clocks * 20 = 240 clocks, break up into pieces to interleave hsync and color burst
    .rept 3
    COMPUTE_TILE_PTR
    .endr

    // total of 20 tiles now complete

    // increment raster line
    lds     r0, curr_raster_line       // (2)
    inc     r0                         // (1)
    sts     curr_raster_line, r0       // (2)

// fall thru to render the pixels...

///////////////////////////////////////////////////////////////////////////////////////////////////////

NTSC_Draw_Tile_Pixels:
// this draws the actual pixels in the front scanline buffer to the screen

    // Y -> tile bitmaps base address pointer array
    ldi     YL, lo8( tile_bitmaps_ptr_array ) // (1), this code for pointer location storage
    ldi     YH, hi8( tile_bitmaps_ptr_array ) // (1)

    // move display out a bit
    DELAYX r16, (NTSC_HORIZONTAL_OFFSET)

    // render the tiles in sets of 8 pixels, retrieve pointer to bitmap data for current tile row
    // and render it..., repeat
    .rept TILE_MAP_WIDTH // each pixel takes (8) clocks, 20*8*8 = 1280 clocks, 160 pixels, 160 color clocks
        DRAW_TILE_PIXELS_NTSC_PT0 // pixel 0
        DRAW_TILE_PIXELS_NTSC_PT1 // pixel 1
        DRAW_TILE_PIXELS_NTSC_PT1 // pixel 2
        DRAW_TILE_PIXELS_NTSC_PT1 // pixel 3
        DRAW_TILE_PIXELS_NTSC_PT1 // pixel 4
        DRAW_TILE_PIXELS_NTSC_PT1 // pixel 5
        DRAW_TILE_PIXELS_NTSC_PT1 // pixel 6
        DRAW_TILE_PIXELS_NTSC_PT1 // pixel 7
    .endr

    // hold last pixel for a moment
    .rept 6
    nop                                     // (1)
    .endr

    // and back to black
    ldi     r16, NTSC_BLACK                 // (1)
    out     PORTA, r16                      // (1)

    jmp     NTSC_Next_Line                  // (3)

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

NTSC_Next_Line:

    // curr_line++
    adiw    r24, 1                 // (2)

    // if (curr_line >= 262) curr_line = 0
    ldi     r16, hi8(262)          // (1)
    cpi     r24, lo8(262)          // (1)
    cpc     r25, r16               // (1)
    brne    NTSC_End_Line          // (1/2)

    // curr_line = 0
    clr     r24                     // (1)
    clr      r25                    // (1)
   ldi   r16, lo8(Top_Overscan_Compare)
   sts   graphics_driver_jmp, r16
   ldi   r16, hi8(Top_Overscan_Compare)
   sts graphics_driver_jmp + 1, r16

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

NTSC_End_Line:

    // save registers back to curr_line in SRAM for exit back to C/C++ caller
    sts     curr_line,   r24       // (2)
    sts     curr_line+1, r25       // (2)
   
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 

Restore_Regs:

    // restore working registers
    pop     r31         // (2), Z
    pop     r30         // (2)

    pop     r29         // (2), Y
    pop     r28         // (2)

    pop     r27         // (2), X
    pop     r26         // (2)

    pop     r25         // (2)
    pop     r24         // (2)


    pop     r20         // (2)

    pop     r19         // (2)
    pop     r18         // (2)

    pop     r17         // (2)
    pop     r16         // (2)

    pop     r1          // (2)
    // restore the status register
    pop     r0          // (2)
    out     SREG, r0    // (1)       
    pop     r0          // (2)

#if 0
    .rept 50
    nop
    .endr
#endif
   
    reti                // (5) return from interrupt and reset interupt flag, total time of restore 36 clocks for restore

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// END ASM FUNCTIONS
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

.end







Last edited by jhbvic20man on Thu Jul 29, 2010 4:12 pm; edited 1 time in total
Sat Jul 24, 2010 3:13 pm View user's profile Send private message
necron
Site Admin


Joined: 01 Jan 1970
Posts: 4815

Post Reply with quote
Very cool -- I am glad I am done writing all these drivers, kinda makes you go crazy counting so many clocks Smile

Andre'
Sat Jul 24, 2010 6:37 pm View user's profile Send private message Send e-mail Visit poster's website
jhbvic20man



Joined: 11 Apr 2009
Posts: 24
Location: Atlanta,GA

Post Thanks Andre' you did an excellent job on the drivers Reply with quote
Andre'

I couldn't have wrote the changes to this driver without all the code that you wrote and its well documented.
I am going to try and add some sprites and maybe add a few square or sinewave sound generators.
plus now I have some tools to create tilemaps to create a character set.


Very Happy jhbvic20man
Sat Jul 24, 2010 11:09 pm View user's profile Send private message
necron
Site Admin


Joined: 01 Jan 1970
Posts: 4815

Post Reply with quote
Thanks -- they are a lot of fun to write, I tried to keep them sane and semi understandable, but by the time I got to tiles plus sprites, etc. I felt the optimizations were so complex, it was hard for anyone to understand, so I stopped. The PIC is much easier of course since its so much faster, so you can get the same results with sane code, but the AVR stuff has to be SOOOOO optimized, one little change can break it --

Andre'
Sun Jul 25, 2010 1:11 am View user's profile Send private message Send e-mail Visit poster's website
Display posts from previous:    
Reply to topic    XGameStation Forum Index » XGS AVR 8-Bit Development System All times are GMT
Page 1 of 1

 
Jump to: 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group
Design by Vjacheslav Trushkin / Easy Tutorials (Photoshop Tutorials).