attempt to make tetris in starbound game.
- viruskiller
- Posts: 399
- Joined: June 14th, 2012, 5:07 pm
attempt to make tetris in starbound game.
so i got alot of time on my hands lately, and decided to take on a close to/imposible task.
making a tetris game inside starbound game! (its a terraria like game ).
the only mechanics i can use are logic gates,and light bulbs for the blocks.
so i'm making this post in hope u can get me some ideas on how to go about it.
so far i got the concept for the block array and the idea for line full check ,deleting and moving the lines down and whatnot, but the real problem comes hadling the shape going down, and probably the hardest part is rotating it.
i was thinking to make like a stack thing to store the coords of the shape and then have some predefined steps for moving it and rotating it, but i don't know how to select what pixel i want to change .
in essence i probably need to make a sort of computer first and have that run tetris, don't think it's possible to have it all hardwired or something.(by hardwired i mean no software to be loaded by some computer thing, think of it like a electronic tetris game or something)
making a tetris game inside starbound game! (its a terraria like game ).
the only mechanics i can use are logic gates,and light bulbs for the blocks.
so i'm making this post in hope u can get me some ideas on how to go about it.
so far i got the concept for the block array and the idea for line full check ,deleting and moving the lines down and whatnot, but the real problem comes hadling the shape going down, and probably the hardest part is rotating it.
i was thinking to make like a stack thing to store the coords of the shape and then have some predefined steps for moving it and rotating it, but i don't know how to select what pixel i want to change .
in essence i probably need to make a sort of computer first and have that run tetris, don't think it's possible to have it all hardwired or something.(by hardwired i mean no software to be loaded by some computer thing, think of it like a electronic tetris game or something)
Re: attempt to make tetris in starbound game.
Well, maybe you should start with something simpler. Try to make a simple 4-bit ALU.
I'm not sure once you add all the memory subsystem and try to get a ROM going that your 2D map will give you enough elbow room to route all the signals though.
I'm not sure once you add all the memory subsystem and try to get a ROM going that your 2D map will give you enough elbow room to route all the signals though.
Chili
- viruskiller
- Posts: 399
- Joined: June 14th, 2012, 5:07 pm
Re: attempt to make tetris in starbound game.
tetris has a grid of 10x20 so i need to make it 8 bit to be able to address all the points in the table:/ , and the main reason i don't wana do it is because then i'd have to figure out what functions i need for it, and then program the thing , and i'm not even sure if making the whole thing run trough an ALU will be fast enough or if it even run at all..
thre was a guy that made a comuter inside minecraft and that had a draw line function that worked preety much the same way as the one in the tutorials, the problem was that the cpu had a clock cycle of about 2 seconds, so it took like 15 min to calculate all the x and y values for a line about 32 pixels in length.
now i know tetris doesn't require that many calculations per frame, i think i can get away with 1-4 compare operations,and 4-8 increment operations for the shape,the line check and empty line can be hardware handled.
one thing i don't know how to do with that is how to make it loop, guess i have to have a go to instruction built in.
anyway while typing this i just googled tetris assembly to get a glimpse of how is done with such limited instruction set
i can get rid of a good chunk of this code by not needing to handle the lines, but still generating new shape, moving and rotating still takes quite a bit.
i might need more than 8 bit address space,unless i somehow make it so it switches memory set or something, like have the collision check on one memory bank, the rotation on another one and moving the shape on the last one, and then at the end of each i have a special call that switches all the lines to the other bank, i'm preety sure this has been done already irl...... gota stop googling while i type, just found out is called extended memory,feels like i'd have to reinvent quite a few wheels to make this:)
thre was a guy that made a comuter inside minecraft and that had a draw line function that worked preety much the same way as the one in the tutorials, the problem was that the cpu had a clock cycle of about 2 seconds, so it took like 15 min to calculate all the x and y values for a line about 32 pixels in length.
now i know tetris doesn't require that many calculations per frame, i think i can get away with 1-4 compare operations,and 4-8 increment operations for the shape,the line check and empty line can be hardware handled.
one thing i don't know how to do with that is how to make it loop, guess i have to have a go to instruction built in.
anyway while typing this i just googled tetris assembly to get a glimpse of how is done with such limited instruction set
Code: Select all
---- GAME LOOP, PART 1 START: Choose a tetra randomly and draw it on initial poisition on screen ----
; Set the tetraType variable randomly:
mov si, seed
call Randomizer
xor ah, ah
mov bl, MEANING_OF_LIFE
div bl
mov byte[tetraType], al
; Set the rotation to zero and layoutPos to its starting point:
mov byte[rotation], 0
mov byte[layoutPos], 3
mov byte[layoutPos+1], 0
; Set the control net positions:
Call SetNewBlockFormation
; See if the player has failed:
mov byte[rotationTest], 0
mov word[layoutPosTest], 0003h
Call NewFormationCheck
cmp dl, 0
jne _DrawBlocks
jmp GameOver
; Draw the block sprites on screen:
_DrawBlocks:
Call CopyNewToOld
Call UpdateBlockSprites
;---- GAME LOOP, PART 1 END ----
;---- GAME LOOP, PART 2 START: Wait key presses and delay to pass, and do something accordingly ----
CheckCtrl:
; Save any present key scancode from port 60h to the keyStroke variable. If it isn't the left ctrl key, check for the left key.
GetKey keyStroke
cmp byte[keyStroke], LCTRL
jne CheckLeft
; See if enough time has passed to allow a rotation by subtracting rotTime from the current time and see if the difference is large enough:
Call CentiSec
mov ecx, ebx
sub ebx, dword[rotTime]
cmp ebx, ROTATION_DELAY
jl CheckLeft
; See if a rotation would be possible by increasing the rotationTest variable one step and calling NewFormationCheck:
mov al, byte[rotation]
inc al
cmp al, 4
jne _Rot
mov al, 0
_Rot:
mov byte[rotationTest], al
Call NewFormationCheck
cmp dl, 1
jne CheckLeft
; A rotation was possible, so update the rotation and rotTime variables:
mov byte[rotation], al
mov dword[rotTime], ecx
; Save off the old block positions (so that UpdateBlockSprites can put black boxes at these positions), set a new formation according to the updated rotation variable, and update the on-screen sprites accordingly:
call CopyNewToOld
Call SetNewBlockFormation
Call UpdateBlockSprites
; Do the equivalent of the above, for the left key:
CheckLeft:
; Save any present key scancode from port 60h to the keyStroke variable. If it isn't the left key, check for the right key.
GetKey keyStroke
cmp byte[keyStroke], LEFT
jne CheckRight
Call CentiSec
mov ecx, ebx
sub ebx, dword[moveTime]
cmp ebx, MOVE_DELAY
jl CheckRight
mov ax, word[layoutPos]
cmp al, 0
jna CheckRight
dec al
mov word[layoutPosTest], ax
mov al, byte[rotation]
mov byte[rotationTest], al
Call NewFormationCheck
cmp dl, 1
jne CheckRight
mov dword[moveTime], ecx
call CopyNewToOld
sub byte[layoutPos], 1
Call UpdateBlockSprites
; Do the equivalent of the above, for the right key:
CheckRight:
GetKey keyStroke
cmp byte[keyStroke], RIGHT
jne CheckDown
Call CentiSec
mov ecx, ebx
sub ebx, dword[moveTime]
cmp ebx, MOVE_DELAY
jl CheckDown
mov al, byte[rotation]
mov byte[rotationTest], al
mov ax, word[layoutPos]
inc al
mov word[layoutPosTest], ax
Call NewFormationCheck
cmp dl, 1
jne CheckDown
mov dword[moveTime], ecx
call CopyNewToOld
add byte[layoutPos], 1
Call UpdateBlockSprites
; Do the equivalent of the above, for the down key:
CheckDown:
GetKey keyStroke
cmp byte[keyStroke], DOWN
jne CheckAlt
Call CentiSec
mov ecx, ebx
sub ebx, dword[moveTime]
cmp ebx, MOVE_DELAY
jl CheckAlt
mov dword[fallTime], ecx
mov al, byte[rotation]
mov byte[rotationTest], al
mov ax, word[layoutPos]
inc ah
mov word[layoutPosTest], ax
Call NewFormationCheck
cmp dl, 1
je _NotBlockedDown
Call RecordBlockPositions
Call TerminateFilledLines
jmp GameLoop
_NotBlockedDown:
mov dword[moveTime], ecx
call CopyNewToOld
add byte[layoutPos+1], 1
Call UpdateBlockSprites
CheckAlt:
GetKey keyStroke
cmp byte[keyStroke], LALT
jne CheckFall
Call CentiSec
mov ecx, ebx
sub ebx, dword[startoverTime]
cmp ebx, STARTOVER_DELAY
jl CheckCtrl
mov ebx, ecx
sub ebx, dword[moveTime]
cmp ebx, MOVE_DELAY
jl CheckFall
mov dword[moveTime], ecx
mov al, byte[rotation]
mov byte[rotationTest], al
mov ax, word[layoutPos]
_ShootDown:
inc ah
mov word[layoutPosTest], ax
Call NewFormationCheck
cmp dl, 1
je _ShootDown
dec ah
call CopyNewToOld
mov byte[layoutPos+1], ah
Call RecordBlockPositions
Call UpdateBlockSprites
Call TerminateFilledLines
mov dword[startoverTime], ecx
jmp GameLoop
; Check to see if it's time for the tetra to fall one step; if so, make it fall:
CheckFall:
; Check to see if it's time for a fall, by taking in the current time in centiseconds and subtracting the time from the fallTime variable.
Call CentiSec
mov ecx, ebx
sub ebx, dword[startoverTime]
cmp ebx, STARTOVER_DELAY
jl CheckCtrl
mov ebx, ecx
sub ebx, dword[fallTime]
cmp ebx, FALL_DELAY
jl CheckEsc
; Load the rotationTest and layoutPosTest variables appropriately such that NewFormationCheck will check all block positions one step below:
mov al, byte[rotation]
mov byte[rotationTest], al
mov ax, word[layoutPos]
inc ah
mov word[layoutPosTest], ax
Call NewFormationCheck
cmp dl, 1
je _NotBlockedFall
; The tetra is blocked by something below, so record the current block positions in the control net:
Call RecordBlockPositions
; Eliminate any filled lines (that have just been filled as a consequence of the stopped tetra):
Call TerminateFilledLines
mov dword[startoverTime], ecx
jmp GameLoop
; We're not blocked below so move the blocks one step down:
_NotBlockedFall:
mov dword[fallTime], ecx
call CopyNewToOld
add byte[layoutPos+1], 1
Call UpdateBlockSprites
; If the user hasn't pressed the escape-key, start the game loop over:
CheckEsc:
cmp byte[keyStroke], ESCAPE
jne CheckCtrl
;---- GAME LOOP, PART 2 END ----
GameOver:
QuitGame:
; Go back to text mode and quit to DOS:
SetTextMode
QuitToDos
;---------------------------------------------------------------------------------------------------------------
; NewFormationCheck -- Checks if the formation proposed by the tetraType and rotationTest variables would
; be possible, at the layout position given by layoutPosTest. "Possible" is defined as the case where the blocks in
; the proposed formation don't overlap with occupied space in the control net and their positions are all within
; the play field. AL is set according to below:
; "Possible" => AL:=1
; !"Possible" => AL:=0
;--------------------------------------------------------------------------------------------------------------
NewFormationCheck:
push eax
push bx
push cx
push si
push di
; Copy the suggested formation to a test array, blockPosTest:
xor ah, ah ; Calculate the source address and put it in SI.
mov al, BYTES_PER_TETRA
mul byte[tetraType]
mov si, ax
add si, tetra
mov al, byte[rotationTest]
xor ah, ah
xor bh, bh
mov bl, 8
mul bl
add si, ax
mov di, blockPosTest ; Set the distination address to DI.
mov cx, 2 ; Copy all two double words (two bytes for each of the four blocks) of tetra data.
CopyFormation:
mov eax, dword[si]
mov dword[di], eax
add si, 4
add di, 4
loop CopyFormation
; Add the value of layoutPosTest to all of the block positions.
mov ax, word[layoutPosTest]
add byte[blockPosTest], al
add byte[blockPosTest+2], al
add byte[blockPosTest+4], al
add byte[blockPosTest+6], al
add byte[blockPosTest+1], ah
add byte[blockPosTest+3], ah
add byte[blockPosTest+5], ah
add byte[blockPosTest+7], ah
mov cx, 0
; Loop through each suggested block position; the bytes in blockPosTest.
TestLoop:
; See if the position's x-component < CONTROLNET_WIDTH. If not, set DL:=0 and ret.
mov bx, blockPosTest
add bx, cx
cmp byte[bx], CONTROLNET_WIDTH
jl _CheckY
mov dl, 0
jmp _Through
; Do the same thing with the position's y-component with CONTROLNET_HEIGHT.
_CheckY:
inc bx
cmp byte[bx], CONTROLNET_HEIGHT
jl _CheckControlNet
mov dl, 0
jmp _Through
; Get the byte of the same position in the controlNet array to see if it's 0 or something else. If not 0, set DL:=0 and ret:
_CheckControlNet:
mov al, byte[bx]
dec bx
mov dl, byte[bx]
Call GetControlNetValue
cmp bl, 0
je _LoopAgain
mov dl, 0
jmp _Through
_LoopAgain:
add cx, 2
cmp cx, 8
jl TestLoop
; If we've made it this far, it means there are no obstacles to moving in the suggested direction, so set DL:=1 and return:
mov dl, 1
_Through:
pop di
pop si
pop cx
pop bx
pop eax
ret
;END of NewFormationCheck
;---------------------------------------------------------------------------------------------------------
; UpdateBlockSprites -- Calculates the x and y screen coordinates for all four blocks, from the block
; position byte variables; draws filled black boxes on the old positions and new sprites on the new positions.
;---------------------------------------------------------------------------------------------------------
UpdateBlockSprites:
push ax
push bx
push cx
push si
push di
mov cx, 0
BoxDrawLoop:
; Calculate the positions:
mov si, layoutPosOld
mov bp, blockPosOld
Call GetScreenPositions
; Draw the black box:
DrawFullRect word[xpos], word[ypos], BLOCK_WIDTH, BLOCK_HEIGHT, BLACK
inc cx
cmp cx, 4
jne BoxDrawLoop
mov cx, 0
SpriteDrawLoop:
; Calculate the positions:
mov si, layoutPos
mov bp, blockPos
Call GetScreenPositions
; Calculate the adress of the sprite to use:
xor ah, ah
mov al, byte[tetraType]
mov dx, TETRA_SPRITE_SIZE
mul dx
mov word[sprite], ax
add word[sprite], spritedata
; Draw the sprite:
DrawSprite word[xpos], word[ypos], word[sprite]
inc cx
cmp cx, 4
jne SpriteDrawLoop
pop di
pop si
pop cx
pop bx
pop ax
ret
; END of UpdateBlockSprites
;---------------------------------------------------------------------------------------------------------
; TerminateFilledLines -- Eliminates any filled line that has occurred as a consequence of the tetra that
; just stopped falling.
;---------------------------------------------------------------------------------------------------------
TerminateFilledLines:
push ax
push bx
push cx
push dx
push bp
mov byte[lineCount], 0
mov byte[yPosCheck], 21
mov byte[yPosCheck+1], 21
mov byte[yPosCheck+2], 21
mov cx, 7
add cx, 2
EliminateLine:
cmp cx, 1
je UpdateControlNet
sub cx, 2
mov bx, blockPos
add bx, cx
xor ah, ah
mov al, byte[bx]
add al, byte[layoutPos+1]
mov bx, yPosCheck
mov dl, 0
_CheckYPos:
cmp al, byte[bx]
je EliminateLine
inc bx
inc dl
cmp dl, 3
jl _CheckYPos
mov dl, 0
_CheckThroughLine:
Call GetControlNetValue
cmp bl, 0
je EliminateLine
inc dl
cmp dl, CONTROLNET_WIDTH
jl _CheckThroughLine
mov dx, ax
mov byte[elimLine], al
Call MoveControlNetPiece
cmp cx, 1
je _LineCount
mov ax, cx
mov bl, 2
dec al
div bl
xor ah, ah
mov bp, yPosCheck
add bp, ax
mov byte[bp], dl
_LineCount:
add byte[lineCount], 1
jmp EliminateLine
UpdateControlNet:
cmp byte[lineCount], 0
jz _SkipRedraw
Call RedrawControlNet
_SkipRedraw:
pop bp
pop dx
pop cx
pop bx
pop ax
ret
;END of TerminateFilledLines
;---------------------------------------------------------------------------------------------------------
; MoveControlNetPiece -- Copies data in the control net; the region between X=0, Y=m and X=9, Y=AX-1
; (where m is the smallest Y-coordinate for which the line is not nulled), is displaced one step down.
; If Y!=0, a nulled line is placed at Y' = Y-1.
; - Input:
; AX: Y-coordinate for the line that is to be eliminated.
; - Outout:
; Modifications to the controlNet and controlNetTemp arrays according to above.
;---------------------------------------------------------------------------------------------------------
MoveControlNetPiece:
push ax
push bx
push cx
push dx
push si
push di
push bp
xor ah, ah
mov bp, ax
; Find m:
mov cx, CONTROLNET_WIDTH
mov al, 0
mov dl, 0
_FindmLineLoop:
Call GetControlNetValue
cmp bl, 0
jne _mFound
inc dl
loop _FindmLineLoop
inc al
mov dl, 0
mov cx, CONTROLNET_WIDTH
jmp _FindmLineLoop
_mFound:
mov byte[m], al
CalculateAdressDisplacement:
; Calculate the address displacement for the starting coordinate and put to some register.
mov bl, CONTROLNET_WIDTH
xor ah, ah
mul bl
mov dx, ax
; Calculate the address displacement for the ending coordinate and put to some regiser.
mov ax, bp
dec al
mul bl
add al, 9
; Calculate the difference of the displacement addresses and put in the second register.
sub ax, dx
; Do a copy loop from address controlNet+[starting coordinate adress displacement] in a number of steps equal to the difference above, to the temp variable.
mov cx, ax
inc cx
mov si, controlNet
add si, dx
mov di, controlNetTemp
_CopyFromControlNet:
mov bl, byte[si]
mov byte[di], bl
inc si
inc di
loop _CopyFromControlNet
; Add CONTROLNET_WIDTH to the starting coordinate address displacement.
add dx, CONTROLNET_WIDTH
; Do a copy loop from the temp variable to control net from the new starting coordinate address.
mov cx, ax
inc cx
mov si, controlNetTemp
mov di, controlNet
add di, dx
_CopyToControlNet:
mov bl, byte[si]
mov byte[di], bl
inc si
inc di
loop _CopyToControlNet
; Nullify the m line:
mov di, controlNet
mov al, byte[m]
xor ah, ah
mov bl, CONTROLNET_WIDTH
mul bl
add di, ax
mov dword[di], 00000000h
add di, 4
mov dword[di], 00000000h
add di, 4
mov word[di], 0000h
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
;END of MoveControlNetPiece
;-----------------------------------------------------------------------------------------------------------
; RedrawControlNet -- Updates the on-screen graphics on the playfield according to the updated controlNet
; array. Updates graphics on the screen corresponding to control net coordinates (0, m-lineCount) and (9, DL).
;------------------------------------------------------------------------------------------------------------
RedrawControlNet:
push ax
push bx
push cx
push dx
; Draw filled black box on the area of interest:
; . Calculate the starting x and y screen positions:
mov al, byte[m] ; AL now containts the control net y coordinate of the line one step above the top line that contains at least one block.
sub al, byte[lineCount] ; Depending on the number of total lines that were just eliminated, there will be block graphics a number of lines up.
add byte[lineCount], 1
mov bl, BLOCK_HEIGHT
mul bl
add ax, RECT_Y+2
mov word[ypos], ax
mov word[xpos], RECT_X+2
; . Calculate delta_x and delta_y for the big filled black rectangle:
mov dl, byte[elimLine]
sub dl, byte[m]
add dl, byte[lineCount]
mov ax, BLOCK_HEIGHT
mul dl
mov word[deltay], ax
mov bx, 10
mov ax, BLOCK_WIDTH
mul bl
mov word[deltax], ax
; . Draw the box:
DrawFullRect word[xpos], word[ypos], word[deltax], word[deltay], BLACK
; Draw block sprites on positions according to the control net at these positions.
mov byte[xCont], 0
mov dl, byte[m]
mov byte[yCont], dl
mov dl, byte[lineCount]
sub byte[yCont], dl
add byte[yCont], 1
mov cl, byte[elimLine]
inc cl
DrawControlNetBlocks:
; . Get the value of the control net at these coordinates with GetControlNetValue.
mov al, byte[yCont]
mov dl, byte[xCont]
Call GetControlNetValue
cmp bl, 0
je _SkipDraw
; . From the control net byte value, calculate the address to the appropriate block sprite.
dec bl
mov word[sprite], spritedata
mov ax, TETRA_SPRITE_SIZE
mul bl
add word[sprite], ax
DrawSprite word[xpos], word[ypos], word[sprite]
; . Increase xpos by BLOCK_WIDTH, but if xpos=C+10*, set xpos:=0 and ypos=ypos+BLOCK_HEIGHT; and if ypos=CL, quit:
_SkipDraw:
add byte[xCont], 1
add byte[xpos], BLOCK_WIDTH
cmp byte[xCont], 10
jne DrawControlNetBlocks
mov byte[xCont], 0
sub byte[xpos], 10*BLOCK_WIDTH
add byte[yCont], 1
add byte[ypos], BLOCK_HEIGHT
cmp byte[yCont], cl
jl DrawControlNetBlocks
pop dx
pop cx
pop bx
pop ax
ret
;END of RedrawControlNet
;---------------------------------------------------------------------------------------------------------
; GetScreenPositions -- Calculates the x and y screen coordinates for one of four blocks from the byte values
; of a block position variable, and from a layout position variable.
; - Input:
; SI: Address of the first byte of the layout position variable.
; BP: Address of the first byte of the block position variable.
; CX: Number of the block in the block position variable to use.
; - Output:
; byte[xpos]: X-screen coordinate for the CX:th block in to the block position variable.
; byte[ypos]: Y-screen coordinate for the CX:th block in to the block position variable.
;---------------------------------------------------------------------------------------------------------
GetScreenPositions:
; Set the xpos and ypos variables for each block:
; word[xpos] = (RECT_X+2)+BLOCK_WIDTH*(byte[layoutPos]+byte[blockPosOld+2*n])
; word[ypos] = (RECT_Y+2)+BLOCK_HEIGHT*(byte[layoutPos+1]+byte[blockPosOld+2*n+1])
push ax
push bx
push di
push dx
; Calculate the x position:
mov ax, 2
mul cx
mov di, ax
add di, bp
xor bh, bh
mov bl, byte[di]
add bl, byte[si]
mov al, BLOCK_WIDTH
mul bl
mov bx, ax
add bx, BLOCK_X
; Move the calculated x value to the xpos variable:
mov word[xpos], bx
; Calculate the y position:
mov ax, 2
mul cx
mov di, ax
inc bp
add di, bp
xor bh, bh
mov bl, byte[di]
inc si
add bl, byte[si]
mov ax, BLOCK_HEIGHT
mul bx
mov bx, ax
add bx, BLOCK_Y
; Move the calculated y value to the ypos variable:
mov word[ypos], bx
pop dx
pop di
pop bx
pop ax
; END of GetScreenPositions
;---------------------------------------------------------------------------------------------------------
; SetNewBlockFormation -- Updates the blocks' control net byte values according to current tetraType and rotation.
;---------------------------------------------------------------------------------------------------------
SetNewBlockFormation:
; Set the block positions appopriately:
; for n=0 to 3
; byte[blockPos+2*n] = byte[tetra+BYTES_PER_TETRA*byte[tetraType]+8*rotation+2*n] <-- x-position
; byte[blockPos+2*n+1] = byte[tetra+BYTES_PER_TETRA*byte[tetraType]+8*rotation+2*n+1] <-- y-position
; end for
;mov bx, tetraType
push eax
push cx
push si
push di
; Calculate the source address and put it in SI:
xor ah, ah
mov al, BYTES_PER_TETRA
mul byte[tetraType]
mov si, ax
add si, tetra
mov al, byte[rotation]
xor ah, ah
xor bh, bh
mov bl, 8
mul bl
add si, ax
; Set the distination address to DI:
mov di, blockPos
; Copy all two double words (two bytes for each of the four blocks) of tetra data:
mov cx, 2
CopyLoop:
mov eax, dword[si]
mov dword[di], eax
add si, 4
add di, 4
loop CopyLoop
pop di
pop si
pop cx
pop eax
ret
; END of SetNewBlockFormation
;---------------------------------------------------------------------------------------------------------------
; CopyNewToOld -- Copies the current values of the blockPos and layoutPos variables to their "old" counterparts.
;---------------------------------------------------------------------------------------------------------------
CopyNewToOld:
push si
push di
push cx
push eax
mov si, blockPos
mov di, blockPosOld
mov cx, 2
_blockPosCopy:
mov eax, dword[si]
mov dword[di], eax
add si, 4
add di, 4
loop _blockPosCopy
mov ax, word[layoutPos]
mov word[layoutPosOld], ax
pop eax
pop cx
pop di
pop si
ret
;END of CopyNewToOld
;---------------------------------------------------------------------------------------------------------------
; GetControlNetValue -- Get the byte-value of the control net array at the position given in AX, and set
; AL to that byte-value.
; - Input:
; AL: Y-coordinate of the control net space.
; DL: X-coordinate of the control net space.
; - Output:
; BL: Byte in the controlNet array at the given coordinates.
;--------------------------------------------------------------------------------------------------------------
GetControlNetValue:
push ax
push dx
mov bl, CONTROLNET_WIDTH
xor ah, ah
mul bl
xor dh, dh
add ax, dx
mov bx, controlNet
add bx, ax
mov al, byte[bx]
mov bl, al
pop dx
pop ax
ret
;END of GetControlNetValue
;---------------------------------------------------------------------------------------------------------------
; RecordBlockPositions -- Sets byte[tetraType]+1 - bytes at places in controlNet according to the blockPosition and
; layoutNet variables.
;--------------------------------------------------------------------------------------------------------------
RecordBlockPositions:
push ax
push cx
push bp
push dx
push bx
mov cx, 0
RecordLoop:
; Copy the appropriate word (with firt byte=x-position and second byte=y-position in layout net) from blockPos to half-registers bl and dl:
mov bp, blockPos
add bp, cx
mov bl, byte[bp]
inc bp
mov dl, byte[bp]
; Add the layoutPos bytes to the bytes in those half-registers such that they then contain the control net coordinates:
add bl, byte[layoutPos]
add dl, byte[layoutPos+1]
; Calculate the memory adress displacement from controlNet, from the half-register coordinates:
mov ax, CONTROLNET_WIDTH
mul dl ; Multiply the y-coordinate with the control net width and put product in AX.
xor bh, bh
add ax, bx ; Add the X-coordinate.
; Make BX contain the address to the byte where the 01h-byte will be put:
mov bx, controlNet ; Load BX with the controlNet address.
add bx, ax ; Add the memory adress displacement to get the address to byte of interest.
; Set a byte[tetraType]+1 - byte at the memory location pointed to by BX.
mov al, byte[tetraType]
inc al
mov byte[bx], al
add cx, 2
cmp cx, 8
jne RecordLoop
pop bx
pop dx
pop bp
pop cx
pop ax
ret
;END of RecordBlockPositions
;---------------------------------------------------------------------------------------------------------------
; NullifyControlNet -- Sets all the values in the controlNet array to zero.
;--------------------------------------------------------------------------------------------------------------
NullifyControlNet:
push ax
push cx
push di
; Set CX to the number of words in controlNet, 105:
mov cx, 105
; Set DI to controlNet:
mov di, controlNet
; Copy!
NullifyLoop:
mov word[di], 0000h
add di, 2
sub cx, 1
jnz NullifyLoop
pop di
pop cx
pop ax
; END of NullifyControlNet
%include "ttrfun.asm"
[SECTION .data]
%include "palette.asm" ; Palette data.
%include "sprdata.asm" ; Block sprites.
%include "ttrdat.asm" ; Tetra positions.
rotation db 0
rotationC db 0
rotationTest db 0
rotTime dd 0
moveTime dd 0
fallTime dd 0
startoverTime dd 0
score dw 0
oldLineNumber dw 11
lineCount db 1
m db 0
yPosCheck db 21, 21, 21
[SECTION .bss]
elimLine resb 1
a resb 1
b resb 1
keyStroke resb 1 ; Byte for temporary storage of key-stroke bytes.
layoutPos resb 2 ; The offset position from which all the block positions are set. First byte=x, second byte=y.
layoutPosTest resb 2 ; The offset position from which all the block positions are set. First byte=x, second byte=y.´
layoutPosOld resb 2
blockPos resb 8 ; x and y control net positions per block.
blockPosTest resb 8
blockPosOld resb 8 ; The old control net positions (positions corresponding the positions of the sprites until UpdateBlockSprites erases them).
controlNet resb 210 ; The control net where information about whether each position is set or not, is stored.
controlNetTemp resb 210
tetraType resb 1 ; Variable indicating the identification number of the current tetra.
seed resd 1 ; Seed data for the Randomizer function.
posInfoOffset resw 1
blockPosOffset resw 1
xpos resw 1
ypos resw 1
sprite resw 1
blockPosAdr resw 1
layoutPosAdr resw 1
deltax resw 1
deltay resw 1
xCont resb 1
yCont resb 1
i might need more than 8 bit address space,unless i somehow make it so it switches memory set or something, like have the collision check on one memory bank, the rotation on another one and moving the shape on the last one, and then at the end of each i have a special call that switches all the lines to the other bank, i'm preety sure this has been done already irl...... gota stop googling while i type, just found out is called extended memory,feels like i'd have to reinvent quite a few wheels to make this:)
- viruskiller
- Posts: 399
- Joined: June 14th, 2012, 5:07 pm
Re: attempt to make tetris in starbound game.
i think i'm going to let this go for now:/ the game mechanics are kinda hindering me to do any complicated build
i started to make the ram first, and only made 3 bytes and is already a complete mess
this is how it looks without the wiring shown
http://snag.gy/7SiCL.jpg
as u can see it's preety neat looking, but to work with it and connect the parts i have to see the wiring of the entire thing and below is what it looks like
http://snag.gy/jI97T.jpg
so i guess minecraft may be slower but atleast it scales better , and also has tools to support copy/pasting. i tought that not having to bother with phisical wires would make it much more easyer to get things compact and fast because i'd not have to wory about wires crossing eachother and stuff
but then it gets bigger and bigger and it gets to be a big mess
this analogy i think its perfect to describe old programing style versus OOP, i think of it as OOP is the first picture, each object has it's own function and u don't see the interaction between them,
the second picture is what hardcoding stuff does , u see the entire thing, and the bigger it gets the harder is to understand
i started to make the ram first, and only made 3 bytes and is already a complete mess
this is how it looks without the wiring shown
http://snag.gy/7SiCL.jpg
as u can see it's preety neat looking, but to work with it and connect the parts i have to see the wiring of the entire thing and below is what it looks like
http://snag.gy/jI97T.jpg
so i guess minecraft may be slower but atleast it scales better , and also has tools to support copy/pasting. i tought that not having to bother with phisical wires would make it much more easyer to get things compact and fast because i'd not have to wory about wires crossing eachother and stuff
but then it gets bigger and bigger and it gets to be a big mess
this analogy i think its perfect to describe old programing style versus OOP, i think of it as OOP is the first picture, each object has it's own function and u don't see the interaction between them,
the second picture is what hardcoding stuff does , u see the entire thing, and the bigger it gets the harder is to understand
Re: attempt to make tetris in starbound game.
Well don't feel about it it's difficult to create a CPU even when you have a proper framework to work with.
The people making computers in Minecraft usually use a good set of mods to facilitate everything and also have worked with FPGAs previously.
Plus you might have trouble wiring everything, TBH I didn't play Starbound much, but if it's wiring mechanics are anything like Terraria there will be only so much you can do.
The people making computers in Minecraft usually use a good set of mods to facilitate everything and also have worked with FPGAs previously.
Plus you might have trouble wiring everything, TBH I didn't play Starbound much, but if it's wiring mechanics are anything like Terraria there will be only so much you can do.
0x5f3759df
Re: attempt to make tetris in starbound game.
From what I saw that thing seems to be missing tri-state buffers, so you'd be screwed for any kind of data bus. It'd all have to be done with multiplexers.
Chili
- viruskiller
- Posts: 399
- Joined: June 14th, 2012, 5:07 pm
Re: attempt to make tetris in starbound game.
the latches act as tri state buffers, the only problem is that they get stuck sending the last signal if u close the gate before the input signal.
but as i said in previous post the real problem is the mechanics of wiring the circuits,there must be some way to turn certain parts off, so u can see what u work on,the way it is now u'd have to have all things separated by long distance and the lines going at different angles to see what u're doing.
but as i said in previous post the real problem is the mechanics of wiring the circuits,there must be some way to turn certain parts off, so u can see what u work on,the way it is now u'd have to have all things separated by long distance and the lines going at different angles to see what u're doing.
Re: attempt to make tetris in starbound game.
Nope, they are simple latches. There is no high-impedance enabling input for them so they cannot act as tri-state buffers.
The problem you're having is that you're trying to use a latch like a flip-flop. To fix that, you need to connect two latches together in master-slave configuration. That will give you an edge-sensitive flip flop that you can use for synchronous processing.
http://en.wikipedia.org/wiki/Flip-flop_ ... _flip-flop
But yeah, the real problem is that while Starbound might be an okay game, it's a shitty logic design tool
The problem you're having is that you're trying to use a latch like a flip-flop. To fix that, you need to connect two latches together in master-slave configuration. That will give you an edge-sensitive flip flop that you can use for synchronous processing.
http://en.wikipedia.org/wiki/Flip-flop_ ... _flip-flop
But yeah, the real problem is that while Starbound might be an okay game, it's a shitty logic design tool
Chili