Leveledit

Basic and Machine Language

Moderator: Moderators

TBCVIC
Vic 20 Hobbyist
Posts: 127
Joined: Thu Mar 05, 2009 3:38 am

Leveledit

Post by TBCVIC »

Here's my latest project. It's a level editor mostly for my own use, but maybe someone else may find it useful. As it is now, it needs a fully expanded Vic. I've gotten some inspiration from adric22's screenedit and I used KingTrode's charedit too.

Quick instructions:

Load the file "LEVELEDIT" and run it. It will load "CHR.LEDIT" and "LVL.LVL01". You start in edit mode. Keys to use:

L - Load font from "CHR.LEDIT"
S - Save level to file "LVL.LVL01"
SPACE - plot character
RETURN - Select character from chart
CURSOR KEYS - Move around
Y,G,H,B - Scroll level up,left,right,down
P - Pick up char

After you've edited your level, you can try it out by pressing C.
Use a joystick to scroll around the level.

Ok, here's a .D64 file for you: leveledit.d64
Ola Andersson
Image
TBCVIC
Vic 20 Hobbyist
Posts: 127
Joined: Thu Mar 05, 2009 3:38 am

Post by TBCVIC »

Ok, since none of you have commented I'll add this:
The "scrolling around the level"-part is a multidirectional scroll of a 11 by 4 screens large level. The technique could be used to implement for example a platformer like Sonic the hedgehog (which was my plan).

Please note though that it takes a while to "compile" the level after you have pressed 'C'.
Ola Andersson
Image
User avatar
Mike
Herr VC
Posts: 4816
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Post by Mike »

Hi, Ola!

Allowing for arbitrary character pairs would only allow for 16 different characters, most probably less - given the screen already consumes 0.5 K of a 2 K "bank" (times 2 for double buffering). That'd be then 13² = 169 < 192 characters.

I didn't dig that deep into the object code, but am I right that the "compiler" only constructs those character pairs which are actually used in the level design?
TBCVIC
Vic 20 Hobbyist
Posts: 127
Joined: Thu Mar 05, 2009 3:38 am

Post by TBCVIC »

Yes Mike, that's what the compiler does.
Ola Andersson
Image
User avatar
Mike
Herr VC
Posts: 4816
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Post by Mike »

Oh! Something like Uridium or Tutankham springs to my mind here (both don't use vertical scrolling).
User avatar
pixel
Vic 20 Scientist
Posts: 1329
Joined: Fri Feb 28, 2014 3:56 am
Website: http://hugbox.org/
Location: Berlin, Germany
Occupation: Pan–galactic shaman

Re: Leveledit

Post by pixel »

This thing really comes in handy. Would love to be able to exit the preview mode and change the level size.
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
User avatar
Mike
Herr VC
Posts: 4816
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Leveledit

Post by Mike »

O.K. let's not derail tokra's +2K RAM expansion thread. ;)

A fairly standard setup excluding vertical scrolling would put:

- one display buffer at $1000 .. $17FF, screen starting at $1000, chars from end of screen to $17FF, and
- another display buffer at $1800 .. $1FFF, screen starting at $1800.

This way, you have the entire time of one frame to update both the dynamic parts of the character set and screen, and possibly colour RAM. [1] Then all to do is change the value in $9005 somewhere in the non-display area above or below the display window. Done easily enough with a synced VIA timer, doesn't even have to be cycle-accurate.

The characters of the level data are transformed from their original values into all distinct character pairs. The number of the character pairs must not exceed the amount of the allocated dynamic part of the character set. Could be done off-line.

The character set itself is split in three parts: static, dynamic (for scrolling), and sprite pool.

The character pair 'view' results in eight copies of the dynamic part of the character set, each one shifted another pixel to the left (could also be done off-line). The display routine must be fast enough to copy the character set into the hidden video RAM page once every frame, thus an unrolled routine is recommended. Possibly 16 different versions, for the 8 sets and 2 pages.

Similarly, the screen display must also be fast enough to be refreshed once every frame. Instead of copying from the visible screen to the hidden screen (and doing lots of case selections - and anyway, what about the overlaid sprites?), the screen RAM is always refreshed from the level data. Ideally, that is one put row-wise into memory. If the horizontal extension of the level data can be limited to 256 characters, an unrolled loop over all screen rows can be employed like thus:

Code: Select all

 LDX #columns - 1
 LDY offset ; ** offset into level data
.loop
 LDA level,Y
 STA screen,X
 LDA level+columns,Y
 STA screen+columns,X
 [...]
 DEY
 DEX
 BPL loop
... with a second copy for the other screen page.

In the remaining time, the sprites are processed, and then the rest of the game logic.

If colour RAM is also used, the level has to be laid out in a way that colour clashes are not immediately visible. That most probably requires some kind of 'buffer' characters at colour changes. Attribute clash with the software sprites will still occur.

With unrolled loops, the CPU can update ~2K bytes per frame at max.

That's a round-up of the ideas currently flowing around in my mind.

[1] in that case, the screen bases should differ by mod 512 in their base address, so their colour RAM doesn't overlap. Complicates the rest a bit, though.
Vic20-Ian
Vic 20 Scientist
Posts: 1213
Joined: Sun Aug 24, 2008 1:58 pm

Re: Leveledit

Post by Vic20-Ian »

Ref earlier comments ref tristate:

While you are hacking the hardware, could the tristate buffers be removed by replacing 6502 with the Atari 6502 or the 6510?

"Tri-stating the buses
The 6510 and an Atari version of the 6502 can be tri-stated. 573s have an OC input that takes care of that. The 6510 and the Atari version go into tri-state mode the moment AEC/BE becomes (L). A 573 is active the moment OC is (L). This means an inverter is needed: IC07d.
The R/W has to be tri-stated as well: IC11c, a 125 buffer, takes care of this.
ID signal I123 takes care of enabling IC05, the 573 that outputs the data. IC06c, an OR gate, makes sure that IC05 is tri-stated as well during a tri-state demand from the outside world.

Supporting the 6510
The major difference with the 6502 is the 6-bits onboard I/O port. An added 6526 takes care of that. The 6526 may only be visible at the addresses $0000 and $0001. Two 688s, IC08 and IC09 take care of that. Signal I121 and OR gate IC06a take care of the fact whether the 6526 will be enabled at all or not.
When reading from $0000 or $0001, we must make sure that there is no conflict with IC04, the 573 that reads the data from the outside world. Inverter IC07c and OR gate IC06b take care of that."

http://www.baltissen.org/newhtm/ttl6502.htm
Vic20-Ian

The best things in life are Vic-20

Upgrade all new gadgets and mobiles to 3583 Bytes Free today! Ready
Vic20-Ian
Vic 20 Scientist
Posts: 1213
Joined: Sun Aug 24, 2008 1:58 pm

Re: Leveledit

Post by Vic20-Ian »

"On the original 400/800 design, a series of tri-state buffers surround the 6502 and
do the job of 'detaching' the 6502.

To lower the chip count on the XL & XE lines, Atari developed a custom version of the 6502 which had the simple
tri-state buffers built-in."


If I understand the article correctly it may be that an Atari XL or XE has a Tristate capable 1.7MHz 6502.

Could this be dropped into the Vic and then remove the tri-state buffers to overcome your problem?

http://www.atarimax.com/freenet/freenet ... cle.php?38
Vic20-Ian

The best things in life are Vic-20

Upgrade all new gadgets and mobiles to 3583 Bytes Free today! Ready
User avatar
Mike
Herr VC
Posts: 4816
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Leveledit

Post by Mike »

See here.
User avatar
pixel
Vic 20 Scientist
Posts: 1329
Joined: Fri Feb 28, 2014 3:56 am
Website: http://hugbox.org/
Location: Berlin, Germany
Occupation: Pan–galactic shaman

Re: Leveledit

Post by pixel »

Mike wrote:O.K. let's not derail tokra's +2K RAM expansion thread. ;)
LOL! :lol:
Mike wrote:That's a round-up of the ideas currently flowing around in my mind.
Right. I must say I'm always baffled by your most accurate descriptions!

I'm much more a man of intuition, so here's what I came up with to make it go in all directions. First of all, I'd be happy with 25fps. It's not super-smooth, but as soon as you play an action game you have other problems to deal with. ;) With my idea the screen and charset(!) is redrawn for every double frame. To knock that off I grab mountains of memory for:

Screen character hash table (1K)

It contains addresses of hash table entries for each char and three of its neighbors on the screen: one right, one below it and the one below the right one. Only eight different tiles are possible to generate the 12-bit "hash key" (to which the base of the hash table is added). The keys are only generated when a new column or row scrolls in.

This table is made of two tables actually, one for the low, the other for high byte part of the addresses. They are 512 bytes in size each and they wrap around, so instead of copying the whole table for a full character scroll with a simple loop we're finally in need for code we don't want to deal with with a hangover, so we have reason to let people pass for calling us engineers. ;)

To draw the screen we sequentially grab all these addresses into the

Tile hash table (4K)

This table just contains the values of character that have been set up already. If one is there, we simply copy that byte to the screen. If not, we allocate a new character from our charset and blit it (and parts of its neighbors) in and put the value into the hash table.

This could be the main loop:

Code: Select all

    lda (screenhash_lo),y
    sta selfmod+1
    lda (screenhash_hi),y
    sta selfmod+2
selfmod:
    lda somewhere_in_the_hashtable
    beq draw_char
    sta screen,x
    inx
    iny
    ....
Et voilá: a whole frame of cycles burned away. Finally, we have to clear the hash table. 4K is quite something to clear, so there's also a

List of allocated hash table entries (256 bytes)

to clear only tens of entries max.

So, thanks to NOT using hardware scrolling, in the rest of the second frame you can keep the player in the middle of the screen, blasting out truckloads of ammo sprites which don't need bit shifting and also reducing the number of sprite characters required immensely. The best rendering engine is between the ears. If the action is fast enough a lot of glitches go unnoticed. Sure, there'll be a couple of shifted sprites as well. Another 4K of shifting tables should help along.

Well, that'd be my recipe for some blinding platform action that'll make you find out if you're an epileptic or not. Game design has to make the best out of it. ATM my lab coat is already burning because of the Pulse tape release, so I didn't manage to be accurate and think it through until all doubts have been vanished. It has to be tried out. After all one would have to write a level editor oneself to, for example, use even more tiles, depending on the player's position in the level.

I hope you find this idea refreshing.

love+respect
pixel
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
User avatar
Mike
Herr VC
Posts: 4816
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Leveledit

Post by Mike »

Wow.

That's quite an ambitious display routine. Generating the charset on the fly is going to be rather expensive, time-wise, though? A simple copy only requires 9 cycles, a bit-shifted copy from two sources counts in with ~50 cycles. A quick calculation (1000000/(50*50*8)) shows, that roughly 50 'new' characters could be constructed in one frame - and you're doing this only 50% of the time, i.e. 50 characters every 2 frames.

As I wrote in my earlier post from 2010, I had something like a port of Uridium in mind. That one of course critically depends on a frame rate of 50/second.
User avatar
pixel
Vic 20 Scientist
Posts: 1329
Joined: Fri Feb 28, 2014 3:56 am
Website: http://hugbox.org/
Location: Berlin, Germany
Occupation: Pan–galactic shaman

Re: Leveledit

Post by pixel »

Mike wrote:That's quite an ambitious display routine. Generating the charset on the fly is going to be rather expensive, time-wise, though? A simple copy only requires 9 cycles, a bit-shifted copy from two sources counts in with ~50 cycles. A quick calculation (1000000/(50*50*8)) shows, that roughly 50 'new' characters could be constructed in one frame - and you're doing this only 50% of the time, i.e. 50 characters every 2 frames.
Uh? What would your simple copy look like?

Now, with self-modifying code and the advantage that all character setups have the same bit shifts for the whole screen I get this speed code snippet to set up a single character's line:

Code: Select all

5    lda (char_left),y
2    tax
4    lda bitshift_left,x
3    sta tmp
5    lda (char_right),y
2    tax
4    lda bitshift_right,x
3    ora tmp
5    sta (charset),y
2    iny

35 * 8 lines = 280 cycles
Racing along the hash addresses totals to about 15,000 cycles; leaving time for 25 blits in the first frame and 78 blits in the second frame.

Oh, this is fun! Now let's take this to the absolute edge, the way we'd love it:

Code: Select all

2 ldy #charline_left
5 lda (bitshift_left),y
2 ldy #charline_right
5 ora (bitshift_right),y
3 ldy cnt
5 sta (charset),y
5 inc cnt

27 * 8 lines = 216 cycles
Makes 32 blits in the first frame and 101 in the second. This code for all eight lines makes 119 bytes. We have only 8 tiles, so we can generate blitters for all 64 combinations, totaling to 7616 bytes. I guess I'm all set with this and 32 generated chars.
Mike wrote:As I wrote in my earlier post from 2010, I had something like a port of Uridium in mind. That one of course critically depends on a frame rate of 50/second.
Sounds neat. Are you going to code this anytime soon?
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
User avatar
Mike
Herr VC
Posts: 4816
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Leveledit

Post by Mike »

pixel wrote:Uh? What would your simple copy look like?
Well, what? Unrolled pairs of indexed LDA/STA of course. That of course requires pre-calculated charsets for the 8 different horizontal scroll-positions. Vertical scrolling can be done by arranging the window into the 2x2 characters column-wise and applying an offset of 0..7 while reading.
Now, with self-modifying code and the advantage that all character setups have the same bit shifts for the whole screen I get this speed code snippet to set up a single character's line: [...]
That shaves off a few cycles by replacing the 8 shift instructions with table lookups. Not entirely unreasonable ... but you need to set aside ~4K for left/right, 8 bit positions and 256 entries per table (the non-shifted version of course can be optimized away), otherwise you'd be pre-calculating 2 tables each time the scroll-offset is changed, and that takes the same time as rendering 32 characters with my method.
Mike wrote:[...] Uridium [...]
pixel wrote:Sounds neat. Are you going to code this anytime soon?
Not really. I do have another WIP, and in that case I've decided to go the comfortable way. It will be announced here when it's ready, not earlier (I do have a playable version already, though. ;))
User avatar
pixel
Vic 20 Scientist
Posts: 1329
Joined: Fri Feb 28, 2014 3:56 am
Website: http://hugbox.org/
Location: Berlin, Germany
Occupation: Pan–galactic shaman

Re: Leveledit

Post by pixel »

Mike wrote:
pixel wrote:Uh? What would your simple copy look like?
Well, what? Unrolled pairs of indexed LDA/STA of course. That of course requires pre-calculated charsets for the 8 different horizontal scroll-positions.
So you mean 8 cycles, not 9. O.K. I understood your pre-calculated charset idea already. 8)
Mike wrote: Vertical scrolling can be done by arranging the window into the 2x2 characters column-wise and applying an offset of 0..7 while reading.
Hmm... something about this is putting a spoon of sand in the gears. Got to let this sink in. I'll tell you if it works for me. Need to bugger off and get that vintage plug and cable and make that assembler generate correct WAVs.
Mike wrote:That shaves off a few cycles by replacing the 8 shift instructions with table lookups. Not entirely unreasonable ... but you need to set aside ~4K for left/right, 8 bit positions and 256 entries per table (the non-shifted version of course can be optimized away), otherwise you'd be pre-calculating 2 tables each time the scroll-offset is changed, and that takes the same time as rendering 32 characters with my method.
Yeah, I was already to say that I'd need that 4K table. :|
Mike wrote:
pixel wrote:Sounds neat. Are you going to code this anytime soon?
Not really. I do have another WIP, and in that case I've decided to go the comfortable way. It will be announced here when it's ready, not earlier (I do have a playable version already, though. ;))
I can't wait!!!1! :mrgreen:
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
Post Reply