;-------------------------------------------------------------------- ; GridEdit by Mark Guttenbrunner ; Version 1.00 ;----------------------------------------- ; 0.01 2008-11-16 started ; 1.00 2008-11-18 first release finished ;----------------------------------------- ; Usage: Joystick 0 to move cursor, press button to set (of grid line not set) or clear ; (if grid line set) ; Keyboard: ; C: Clear grid ; F: set Full grid ; 1: fill mode on/off ; 2: grid dots on/off ; 3: change grid color ; 4: change background color ; 5: luminance on/off ;-------------------------------------------------------------------- cpu 8048 org 400h ;-------------------------------------------------------------------- CONST_Grid_YMax equ 0CBh CONST_Grid_YMin equ 00Bh CONST_Grid_XMax equ 090h CONST_Grid_XMin equ 000h CONST_Grid_YDistance equ 018h CONST_Grid_XDistance equ 010h CONST_XSpeedInc equ 2 CONST_YSpeedInc equ 3 CONST_XSpeedDec equ -2 CONST_YSpeedDec equ -3 CONST_KB_ClearGrid equ 1 CONST_KB_SetGrid equ 2 VDC_Control equ 0A0h VDC_Status equ 0A1h VDC_Color equ 0A3h VDC_Sprite0_Control equ 000h VDC_Sprite0_Shape equ 080h BIOS_Reset equ 00F1h BIOS_ReadJoystick equ 038Fh BIOS_Divide equ 03CFh BIOS_ReadKey equ 00B0h ;-------------------------------------------------------------------- jmp start ; RESET $400 jmp intr ; interrupt $402 -> my own interrupt start: ;--------------------------------------------------------- ; system init ;--------------------------------------------------------- en i ; interrupts off sel rb1 ; everything is done in rb1, except the interrupt call BIOS_Reset ; reset the O2 call IntRAMInit ; set all startvalues orl p1,#00010100b ; init VDC Access only anl p1,#11110111b mov r0,#VDC_Control mov a,#00000000b ; turn vdc off movx @r0,a call SpriteInit clr a call fillGrid ; init Grid (we start with empty grid) mov r0,#INTRAM_Color mov a,@r0 mov r0,#VDC_Color movx @r0,a ; screen color, grid color mov r0,#INTRAM_Control ; start with Control = VDC and Grid On mov a,@r0 mov r0,#VDC_Control movx @r0,a loop ;------------------------------------------------------------ ; do all the work here (get joysticks and calculate positions) ;------------------------------------------------------------ ; read keyboard outside of VBlank, we don't need to waste VBlank time for this orl p1,#00011000b ; keyboard on anl p1,#11111011b call readKeyboard orl p1,#00010100b ; vdc on, keyboard off anl p1,#11110111b ;--------------------------------------------------------- ; wait for VSYNC ;--------------------------------------------------------- waitForVSYNC jf1 VSYNC jmp waitForVSYNC VSYNC clr f1 mov r0,#VDC_Control clr a ; vdc off movx @r0,a call moveSprite ; move the sprite to new position, if grid intersection is reached -> set incs to zero call readStick ; read the joystick mov r0,#INTRAM_Keyboard mov a,@r0 xrl a,#CONST_KB_ClearGrid ; shall the grid be cleared ? jnz noClearGrid clr a call fillGrid jmp noSetGrid noClearGrid mov a,@r0 xrl a,#CONST_KB_SetGrid ; shall the grid be set ? jnz noSetGrid mov a,#0FFh call fillGrid noSetGrid mov r0,#INTRAM_Keyboard ; reset it anyway clr a mov @r0,a mov r0,#INTRAM_Color mov a,@r0 mov r0,#VDC_Color movx @r0,a ; screen color, grid color mov r0,#INTRAM_Control mov a,@r0 mov r0,#VDC_Control ; VDC on, Grid Fill Mode, Grid Dots movx @r0,a jmp loop ;-------------------------------------------------------------------- ; readKeyboard: get the keyboard values and act accordingly ;-------------------------------------------------------------------- readKeyboard: ; read keys call BIOS_ReadKey ; get keyboard code mov r7,a xrl a,#27 ; "F" jnz notF mov a,#CONST_KB_SetGrid ; set the full Grid mov r0,#INTRAM_Keyboard mov @r0,a notF mov a,r7 xrl a,#35 ; "C" jnz notC mov a,#CONST_KB_ClearGrid ; clear the Grid mov r0,#INTRAM_Keyboard mov @r0,a notC mov a,r7 xrl a,#1 ; "1" jnz not1 mov r0,#INTRAM_Control ; Fill Mode on/off mov a,@r0 jb7 Set1 orl a,#10000000b jmp Done1 Set1 anl a,#01111111b Done1 mov @r0,a not1 mov a,r7 xrl a,#2 ; "2" jnz not2 mov r0,#INTRAM_Control ; Grid Dots on/off mov a,@r0 jb6 Set2 orl a,#01000000b jmp Done2 Set2 anl a,#10111111b Done2 mov @r0,a not2 mov a,r7 xrl a,#3 ; "3" jnz not3 mov r0,#INTRAM_Color ; increase Grid Color mov a,@r0 anl a,#11111000b ; mask out the gridcolor mov r4,a ; and save it mov a,@r0 add a,#01h ; next color anl a,#00000111b ; take only the gridcolor orl a,r4 ; and add the original color mov @r0,a ; and save it back to intram not3 mov a,r7 xrl a,#4 ; "4" jnz not4 mov r0,#INTRAM_Color ; increase Background Color mov a,@r0 anl a,#11000111b ; mask out the bgcolor mov r4,a ; and save it mov a,@r0 add a,#00001000b ; next color anl a,#00111000b ; take only the bgcolor orl a,r4 ; and add the original color mov @r0,a ; and save it back to intram not4 mov a,r7 xrl a,#5 ; "5" jnz not5 mov r0,#INTRAM_Color ; luminace bit on/off mov a,@r0 jb6 Set4 orl a,#01000000b jmp Done4 Set4 anl a,#10111111b Done4 mov @r0,a not5 retr ;================================================================================================================ ;= = ;= Page 2: Joystickroutine = ;= = ;================================================================================================================ align 256 ;-------------------------------------------------------------------- ; read Joystick, set movement-values for increase/decrease ;-------------------------------------------------------------------- readStick: mov r1,#0 call BIOS_ReadJoystick ; read Joystick 0 ; check if movement is allowed (that is -> we are not moving already mov r1,#INTRAM_SpriteIncY mov a,@r1 jnz noMovePossible ; do we move in Y ? inc r1 mov a,@r1 jnz noMovePossible ; do we move in X ? mov a,r3 xrl a,#0FFh jnz notUp mov r1,#INTRAM_SpriteIncY ; Joystick up -> decrease in Y mov a,#CONST_YSpeedDec mov @r1,a jmp noMovePossible notUp mov a,r3 xrl a,#001h jnz notDown mov r1,#INTRAM_SpriteIncY ; Joystick down -> increase in Y mov a,#CONST_YSpeedInc mov @r1,a jmp noMovePossible notDown mov a,r2 xrl a,#0FFh jnz notLeft mov r1,#INTRAM_SpriteIncX mov a,#CONST_XSpeedDec ; Joystick left -> decrease in X mov @r1,a jmp noMovePossible notLeft mov a,r2 xrl a,#001h jnz noMovePossible mov r1,#INTRAM_SpriteIncX ; Joystick right -> increase in X mov a,#CONST_XSpeedInc mov @r1,a noMovePossible cpl f0 jf0 ButtonNotPressed ; no Button -> change spriteIncs if zero (otherwise NOT) ;------------------------------------------------------------------------------------------------ ; change the current gridline if in the middle of a Girdline (X+1/2 X Distance, Y+1/2 Y Distance) ;------------------------------------------------------------------------------------------------ buttonPressed: ; Y: mov r0,#VDC_Sprite0_Control ; Sprite 0 Y-Position movx a,@r0 add a,#-(CONST_Grid_YMin+CONST_Grid_YDistance/2) ; subtract half height mov r2,a mov r3,#CONST_Grid_YDistance ; divide by distance call BIOS_Divide mov a,r5 jnz notOnYMiddle ; if there is a rest of division, then its not the middle mov r0,#VDC_Sprite0_Control+1 ; Sprite 0 X-Position movx a,@r0 swap a anl a,#00Fh add a,#0E0h mov r0,a mov a,r4 ; 0 = one rotation ! inc a mov r4,a mov a,#10000000b ; rotate to the correct bit loopYBits rl a djnz r4,loopYBits mov r4,a movx a,@r0 ; is the bit we need set ? anl a,r4 jz setGridLineY ; if not set the bit mov a,r4 ; invert the bitmask for clearing cpl a mov r4,a movx a,@r0 ; get value and clear bit anl a,r4 jmp DoneGridLineY setGridLineY movx a,@r0 ; get value and set bit orl a,r4 DoneGridLineY movx @r0,a ; write back notOnYMiddle ; X: mov r0,#VDC_Sprite0_Control+1 ; Sprite 0 X-Position movx a,@r0 mov r4,a anl a,#00Fh xrl a,#CONST_Grid_XDistance/2 ; middle of Gridline jnz ButtonNotPressed mov a,r4 ; upper halfbyte is the number of byte we need swap a anl a,#00Fh add a,#0C0h mov r0,a mov r1,#VDC_Sprite0_Control ; Sprite 0 Y-Position movx a,@r1 mov r2,a mov r3,#CONST_Grid_YDistance ; divide by distance call BIOS_Divide mov a,r4 ; bit 0 = 1 rotation inc a mov r4,a xrl a,#09h ; last line ? jnz standardXLoop mov r4,#1 ; then we have to use D0-D8 mov a,#10h ; and need only one rotation add a,r0 mov r0,a standardXLoop mov a,#10000000b ; rotate to the correct bit loopXBits rl a djnz r4,loopXBits mov r4,a movx a,@r0 ; is the bit we need set ? anl a,r4 jz setGridLineX ; if not set it mov a,r4 ; invert the bitmask for clearing cpl a mov r4,a movx a,@r0 ; get value and clear bit anl a,r4 jmp DoneGridLineX setGridLineX movx a,@r0 ; get value and set bit orl a,r4 DoneGridLineX movx @r0,a ; write it back ButtonNotPressed retr ;--------------------------------------------------------- ; fills all the grid lines ; a = value to fill with ;--------------------------------------------------------- fillGrid: mov r7,#9 ; C0 - C8 mov r0,#0C0h loopGridClearH1 movx @r0,a inc r0 djnz r7,loopGridClearH1 mov r7,#9 ; D0 - D8 mov r0,#0D0h loopGridClearH2 movx @r0,a inc r0 djnz r7,loopGridClearH2 mov r7,#10 ; E0 - E9 mov r0,#0E0h loopGridClearV movx @r0,a inc r0 djnz r7,loopGridClearV retr ;================================================================================================================ ;= Page 3: Set up all the ram and sprite = ;================================================================================================================ align 256 ;----------------------------------------------------------------------- IntRAMInit: mov r0,#20h ; Copy to Intram that is free for use (from 20h) mov r1,#RAMData & 0ffh mov r2,#RAMDataEnd-RAMData ; all the data we defined loopCopy mov a,r1 movp a,@a mov @r0,a inc r0 inc r1 djnz r2,loopCopy retr RAMData db 00000010b ; $A3 Color (0-2 GridColor, 3-5 Background, 6 Luminance db 00101000b ; $A0 Control (3 = Grid on, 5 = Foreground, 6=Dot, 7=Fill) db 0 ; Keyboard Code for setting/clearing the grid db 0 ; SpriteIncY db 0 ; SpriteIncX RAMDataEnd INTRAM_Color equ 20h INTRAM_Control equ 21h INTRAM_Keyboard equ 22h INTRAM_SpriteIncY equ 23h INTRAM_SpriteIncX equ 24h ;----------------------------------------------------------------------- ; r7 = spritedata ;----------------------------------------------------------------------- SpriteInit: mov r0,#VDC_Sprite0_Control ; Sprite 0 Control mov a,#CONST_Grid_YMin movx @r0,a ; Y-Position inc r0 mov a,#CONST_Grid_XMin+20h movx @r0,a ; X-Position inc r0 mov a,#00111100b movx @r0,a ; double sized Sprite in white mov r0,#VDC_Sprite0_Shape ; Sprite 0 Shape mov r1,#SpriteData & 0FFh mov r2,#8 SpriteShapeCopy mov a,r1 ; get sprite data from program memory movp a,@a movx @r0,a ; copy to VDC inc r0 inc r1 djnz r2,SpriteShapeCopy retr SpriteData db 00101000b ; Shape of Sprite db 00101000b db 11101110b db 00000000b db 11101110b db 00101000b db 00101000b db 00000000b ;-------------------------------------------------------------------------------------- ; move sprite to new position and reset the increase values if intersection is reached ;-------------------------------------------------------------------------------------- moveSprite: ;------------ ; Y-Position ;------------ mov r0,#VDC_Sprite0_Control ; get Y-Position movx a,@r0 mov r2,a mov r1,#INTRAM_SpriteIncY mov a,@r1 add a,r2 ; new Y-Position mov r2,a mov a,#-CONST_Grid_YMin ; is it lower than min ? add a,r2 jc notToLowY mov r2,#CONST_Grid_YMin ; set it to zero jmp notToHighY notToLowY mov a,#(0FFh-CONST_Grid_YMax+1) ; is it higher than max ? add a,r2 jnc notToHighY mov r2,#CONST_Grid_YMax ; set it to max notToHighY mov a,r2 movx @r0,a ; write back Y-Position ; set inc reg to zero if on intersection mov r4,#((CONST_Grid_YMax-CONST_Grid_YMin) / CONST_Grid_YDistance) + 1 mov r3,#(CONST_Grid_YMin-CONST_Grid_YDistance) & 0FFh IsOnXGridLoop mov a,r3 add a,#CONST_Grid_YDistance ; get next Y-Grid-Position mov r3,a xrl a,r2 ; is it the current Y ? jz IsOnXGridFound ; found position -> done djnz r4,IsOnXGridLoop ; otherwise next jmp notOnYGrid ; none found, so not on Y Grid-Position IsOnXGridFound clr a mov @r1,a ; clear Y-Add notOnYGrid ;------------ ; X-Position ;------------ mov r0,#VDC_Sprite0_Control+1 movx a,@r0 mov r2,a ; old X-Position mov r1,#INTRAM_SpriteIncX mov a,@r1 add a,r2 ; new X-Position movx @r0,a ; write back to Sprite 0 mov r2,a ; and save it for later mov a,#(CONST_Grid_XMin+CONST_XSpeedDec) ; is it lower than min ? xrl a,r2 jnz notToLowX mov r2,#CONST_Grid_XMin ; set it to zero jmp notToHighX notToLowX mov a,#(0FFh-CONST_Grid_XMax+1) ; is it higher than max ? add a,r2 jnc notToHighX mov r2,#CONST_Grid_XMax ; set it to max notToHighX mov a,r2 movx @r0,a ; write back X-Position ; set inc reg to zero if on intersection anl a,#0Fh jnz notOnXGrid ; is it on intersection ? clr a ; if yes mov @r1,a ; clear X-Add notOnXGrid retr ;----------------------------------------------------------------------- ; my interrupt routine -> set f1 ;----------------------------------------------------------------------- intr: sel rb0 mov r6,a ; r6 saves the accumulator mov r0,#VDC_status ; clear VDC_Status Register by reading it movx a,@r0 clr f1 ; we set only the f1-flag in VBlank cpl f1 mov a,r6 ; restore accumulator retr ;----------------------------------------------------------------------- db "Manopac 2008" end