WIP: Tetris + any GCL tips?

Using, learning, programming and modding the Gigatron and anything related.
Forum rules
Be nice. No drama.
Cwiiis
Posts: 27
Joined: 14 May 2018, 09:04

WIP: Tetris + any GCL tips?

Post by Cwiiis »

I've been working on Tetris for the Gigatron (On emulator: https://youtu.be/BATJq6sy6eM On device: https://youtu.be/6YYSNdGqg_0) and it's going ok so far, all the basic building blocks are there now (excuse the pun), and it's mostly a case of polish. The game is currently about 6k, which is mostly the title-screen graphic. I have a couple of questions;

- What have people found to be the fastest way of copying from one region of memory to another? A memcpy or blit style command feels like it's sorely missing from the ROM - I achieve fast-ish clears via SYS_Draw4_30, but it's a little awkward for arbitrary memory copying.

- Does anyone know off-hand how \videoY corresponds to which scanline is being drawn? I currently save a bit of memory/some complexity by using the video display to do collision detection (which is why the piece flickers). I could work around this by doing checks for all possible collisions once when the piece moves and then leave it solid, but I'd be interested in knowing how to time it so that it can happen immediately after the piece is drawn to see if it can happen in the time of one vblank

Something that'd be really nice in GCL would be labels - it'd be nice to be able to do something like:
label@ $00# $00# $00# $00#
And have label treated as the address of the next byte in memory. Currently my code is littered with absolute addresses because you can't do this (or can you?) and I don't have stack space to waste on defs.
I could probably easily add this if people think it's a good idea?

Any feedback welcome!
at67
Site Admin
Posts: 647
Joined: 14 May 2018, 08:29

Re: WIP: Tetris + any GCL tips?

Post by at67 »

Cwiiis wrote: 14 May 2018, 09:59 I've been working on Tetris for the Gigatron (On emulator: https://youtu.be/BATJq6sy6eM On device: https://youtu.be/6YYSNdGqg_0) and it's going ok so far, all the basic building blocks are there now (excuse the pun), and it's mostly a case of polish. The game is currently about 6k, which is mostly the title-screen graphic. I have a couple of questions;
Looks great, but I have to laugh as I have been working on a Tetris clone for the last few hours! The more the merrier :)
- What have people found to be the fastest way of copying from one region of memory to another? A memcpy or blit style command feels like it's sorely missing from the ROM - I achieve fast-ish clears via SYS_Draw4_30, but it's a little awkward for arbitrary memory copying.
In my experience, blits, sprites and memory copies are severely handicapped without using Native code and or a 2nd scanline disabled. In my Tetris clone there are no memory copies, I am using screen memory for my main board data structure, so directly testing and manipulating screen memory for the blocks, (Pokes and Peeks).
- Does anyone know off-hand how \videoY corresponds to which scanline is being drawn? I currently save a bit of memory/some complexity by using the video display to do collision detection (which is why the piece flickers). I could work around this by doing checks for all possible collisions once when the piece moves and then leave it solid, but I'd be interested in knowing how to time it so that it can happen immediately after the piece is drawn to see if it can happen in the time of one vblank
videoY is odd during VBlank, but vCPU code will have a hard time doing anything interesting in just one VBlank. e.g. I use videoY like this in my code after I have drawn everything, to wait for VBlank, (obviously you need to be drawing quickly enough or you start to stall for integer multiples of VBlanks):

Code: Select all

vBlank1     LD      videoY
            ANDI    0x01
            BEQ     vBlank1
            RET
When videoY is even it's actually used by the video bit banger to generate the next scanline starting address, reading through the ROM, (and I am not 100% sure on this, Marcel will obviously know), it's used as an offset within the videoTable at 0x0100 to fetch the next scanlines address, it needs to increment by 2 to offset to the correct 16 bit address, hence why it is even.

Code: Select all

scanline 0 should be videoY 0
scanline 1 should be videoY 2
scanline 2 should be videoY 4
		.
		.
		.
scanline 119 should be videoY 238
User avatar
marcelk
Posts: 488
Joined: 13 May 2018, 08:26

Re: WIP: Tetris + any GCL tips?

Post by marcelk »

Racer and Pictures use this GCL snippet to resync with the video signal:

Code: Select all

  {Sync with video loop}
  [do \videoY, 1& if=0loop]
It waits until the video loop is in vertical blank. The variable is odd in vertical blank and even in the visible area. There it indeed indexes the video indirection table at $100 in increments of two. So making it odd in vertical blank allows for this sync loop. (If I remember correctly it is also 0 on the very last scanline of vertical blank.)

You have to play a bit with where you put it in your loop. In Racer I could have placed it somewhere such that the car sprite doesn't flicker. But that flicker is also revealing something about how things are done, so I kept it like that on purpose. A bit of such crappiness shining through can have educational value.

In the case of Pictures this sync makes things unnecessary slow when retro lines are disabled. But applications aren't expected to work well in every mode.
Last edited by marcelk on 15 May 2018, 22:20, edited 1 time in total.
Cwiiis
Posts: 27
Joined: 14 May 2018, 09:04

Re: WIP: Tetris + any GCL tips?

Post by Cwiiis »

Great answers, thanks both :) I'll try briefly to see if I can time the collision/control check to happen quickly enough to be able to blank and draw the piece, but otherwise I think I'll do what I was suggesting and just check possible collisions on moving. I want to get scoring and progression in quickly so I can start tackling other parts - I'm especially looking forward to exploring the musical capabilities of the gigatron!

I guess perhaps a quicker way of copying from one part of the screen to another would be to do 2 16-bit reads into \sysArgs0 and \sysArgs2 and then proceed with using \SYS_Draw4_30, that might/should be quicker than the 8-bit read/write loop I'm using at the moment...

In your clone, if you have no copies, I'm interested in knowing how you shift the board down when you get lines in a space-efficient way - most of my decisions have been constrained by having to fit code within a page (or usually less) of memory. When I see a complete line, I then copy each line from block_size above downwards - this eliminates needing to do any more complex checking that might take more space (but is, as you can see in the video, very slow at the moment - I quite like the delay, but it's a little too large right now).
at67
Site Admin
Posts: 647
Joined: 14 May 2018, 08:29

Re: WIP: Tetris + any GCL tips?

Post by at67 »

Cwiiis wrote: 14 May 2018, 14:51 In your clone, if you have no copies, I'm interested in knowing how you shift the board down when you get lines in a space-efficient way - most of my decisions have been constrained by having to fit code within a page (or usually less) of memory. When I see a complete line, I then copy each line from block_size above downwards - this eliminates needing to do any more complex checking that might take more space (but is, as you can see in the video, very slow at the moment - I quite like the delay, but it's a little too large right now).
I really meant I had no copies for graphics routines, (blits, sprites etc), I do line shifting and memory copies like you, right now I am using a native routine to blast a source line into a fixed address in page0 memory, and then another native routine to blast that line into it's destination address, (it's fast being native code, but also a cheat). I am planning on using the exact same strategy except for 2 differences when I convert the code to non native.

1) replace the native blasters with unrolled loads and stores.
2) spread the workload over multiple frames, because a Tetromino has a maximum board speed, (except when user dropping, I'll worry about that later), you only have to finish the entire move lines down, insert blank line on top at this speed. e.g. if a Tetromino moves 5 spaces per second at it's maximum speed, that gives you twelve 60Hz cycles to spread the line shifting over.
3) P.S. forgot the most important one, (disable that pesky second scan line).
User avatar
marcelk
Posts: 488
Joined: 13 May 2018, 08:26

Re: WIP: Tetris + any GCL tips?

Post by marcelk »

Something that'd be really nice in GCL would be labels - it'd be nice to be able to do something like:
label@ $00# $00# $00# $00#
In a way defs are labels not just for functions but also for data.

Code: Select all

[def $00# $00# $00# $00#] MyData=
def does nothing but copying vPC into vAC and then hopping over to the end of the block. Almost like a subroutine call.

Your proposal will still fit in the two-pass scheme of asm.py and no need to make GCL two-pass for example. So I think it will work.

Considering the cost in the current scheme: 4 bytes to setup (DEF $DD + STW $DD), and 2 bytes on each use (LDW $DD). Immediate inlining of a word value is 3 bytes on each use (LDWI $DDDD) and you save a zero page variable.

Some background: GCL's main goal was not really to make a language we care about much, but more to avoid having to make a traditional tool chain for just the few applications that are in the first ROM revisions. So we copied a trick from FALSE and do the linking at startup time of the program and that became def. In FALSE a block pushes itself on the stack, so it works slightly different there but the idea is the same. ROM v1 was made possible by abusing Python itself as a macro assembler for native code and adding only a thin layer of notation on top of vCPU.
Cwiiis
Posts: 27
Joined: 14 May 2018, 09:04

Re: WIP: Tetris + any GCL tips?

Post by Cwiiis »

I implemented what I suggested, but of course it doesn't stop the flickering when the piece moves (though the code is tidier for it, so it's a net benefit). Sped up line clearing to the point I think it's acceptable too.

I think if I want to have flicker-less piece moving, I'll need to change how collision detection works, then write a dedicated piece-moving function that doesn't blank the piece before redrawing it, but I'm not sure there's really space left with the rest of the game in there and other bits I want to add. Perhaps I'll save that for a later time, or for a later gigatron rom revision with sprite support (or perhaps a 64k version of the game?)

I can think of ways to do it, but I think they'll probably cost a fair few bytes... I should move on from this and come back to it really.
Cwiiis
Posts: 27
Joined: 14 May 2018, 09:04

Re: WIP: Tetris + any GCL tips?

Post by Cwiiis »

Actually, came up with an idea at lunch after realising that there are 2 spare bits for every pixel on the screen - very handy, hopefully I can get the movement smooth :)
at67
Site Admin
Posts: 647
Joined: 14 May 2018, 08:29

Re: WIP: Tetris + any GCL tips?

Post by at67 »

That sounds pretty cool, so where is the video and when do we get to play it?!?!
User avatar
marcelk
Posts: 488
Joined: 13 May 2018, 08:26

Re: WIP: Tetris + any GCL tips?

Post by marcelk »

Code: Select all

there are 2 spare bits for every pixel on the screen - very handy
That is where the "head" in Snake stuffs directional information that the "tail" needs for following. Can also be handy in maze games, acting as invisible guiding rails for enemies.

PS: I'm still unsuccessful at running Gigatris.gt1. I tried with the PROGMEM route and also by sending data over USB (using the sendGt1.py script for flow control). It did start once on my hardware, so perhaps there is a dependency on uninitialised memory. But it can equally well be a problem with my recent LoaderTest.ino updates. The file structure looks fine. Could you test it with my sketch in GitHub?
Last edited by marcelk on 15 May 2018, 22:20, edited 1 time in total.
Post Reply