Leveledit
Moderator: Moderators
Leveledit
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
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
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'.
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'.
- Mike
- Herr VC
- Posts: 4846
- Joined: Wed Dec 01, 2004 1:57 pm
- Location: Munich, Germany
- Occupation: electrical engineer
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?
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?
- pixel
- Vic 20 Scientist
- Posts: 1362
- Joined: Fri Feb 28, 2014 3:56 am
- Website: http://hugbox.org/
- Location: Berlin, Germany
- Occupation: Pan–galactic shaman
Re: Leveledit
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
https://github.com/SvenMichaelKlose
- Mike
- Herr VC
- Posts: 4846
- Joined: Wed Dec 01, 2004 1:57 pm
- Location: Munich, Germany
- Occupation: electrical engineer
Re: Leveledit
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:
... 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.
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
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.
Re: Leveledit
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
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
The best things in life are Vic-20
Upgrade all new gadgets and mobiles to 3583 Bytes Free today! Ready
Re: Leveledit
"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
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
The best things in life are Vic-20
Upgrade all new gadgets and mobiles to 3583 Bytes Free today! Ready
- Mike
- Herr VC
- Posts: 4846
- Joined: Wed Dec 01, 2004 1:57 pm
- Location: Munich, Germany
- Occupation: electrical engineer
Re: Leveledit
See here.
- pixel
- Vic 20 Scientist
- Posts: 1362
- Joined: Fri Feb 28, 2014 3:56 am
- Website: http://hugbox.org/
- Location: Berlin, Germany
- Occupation: Pan–galactic shaman
Re: Leveledit
LOL!Mike wrote:O.K. let's not derail tokra's +2K RAM expansion thread.
Right. I must say I'm always baffled by your most accurate descriptions!Mike wrote:That's a round-up of the ideas currently flowing around in my mind.
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
....
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
https://github.com/SvenMichaelKlose
- Mike
- Herr VC
- Posts: 4846
- Joined: Wed Dec 01, 2004 1:57 pm
- Location: Munich, Germany
- Occupation: electrical engineer
Re: Leveledit
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.
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.
- pixel
- Vic 20 Scientist
- Posts: 1362
- Joined: Fri Feb 28, 2014 3:56 am
- Website: http://hugbox.org/
- Location: Berlin, Germany
- Occupation: Pan–galactic shaman
Re: Leveledit
Uh? What would your simple copy look like?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.
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
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
Sounds neat. Are you going to code this anytime soon?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.
A man without talent or ambition is most easily pleased. Others set his path and he is content.
https://github.com/SvenMichaelKlose
https://github.com/SvenMichaelKlose
- Mike
- Herr VC
- Posts: 4846
- Joined: Wed Dec 01, 2004 1:57 pm
- Location: Munich, Germany
- Occupation: electrical engineer
Re: Leveledit
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.pixel wrote:Uh? What would your simple copy look like?
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.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: [...]
Mike wrote:[...] Uridium [...]
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. )pixel wrote:Sounds neat. Are you going to code this anytime soon?
- pixel
- Vic 20 Scientist
- Posts: 1362
- Joined: Fri Feb 28, 2014 3:56 am
- Website: http://hugbox.org/
- Location: Berlin, Germany
- Occupation: Pan–galactic shaman
Re: Leveledit
So you mean 8 cycles, not 9. O.K. I understood your pre-calculated charset idea already.Mike wrote:Well, what? Unrolled pairs of indexed LDA/STA of course. That of course requires pre-calculated charsets for the 8 different horizontal scroll-positions.pixel wrote:Uh? What would your simple copy look like?
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: Vertical scrolling can be done by arranging the window into the 2x2 characters column-wise and applying an offset of 0..7 while reading.
Yeah, I was already to say that I'd need that 4K table.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.
I can't wait!!!1!Mike wrote: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. )pixel wrote: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
https://github.com/SvenMichaelKlose