 |
| Author |
Message |
jhbvic20man
Joined: 11 Apr 2009 Posts: 24 Location: Atlanta,GA |
|
XGS_NTSC_TILE_MODE1_V010.S is now jitter free |
|
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.
jhbvic20man
 |
 |
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// 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 |
|
 |
necron
Site Admin

Joined: 01 Jan 1970 Posts: 4815
|
|
|
|
Very cool -- I am glad I am done writing all these drivers, kinda makes you go crazy counting so many clocks
Andre'
|
|
| Sat Jul 24, 2010 6:37 pm |
|
 |
jhbvic20man
Joined: 11 Apr 2009 Posts: 24 Location: Atlanta,GA |
|
Thanks Andre' you did an excellent job on the drivers |
|
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.
jhbvic20man
|
|
| Sat Jul 24, 2010 11:09 pm |
|
 |
necron
Site Admin

Joined: 01 Jan 1970 Posts: 4815
|
|
|
|
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 |
|
 |
|
|
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
|
|
|