Jump to content
IGNORED

Project "M", Stage 1


NRV

Recommended Posts

Hi, I wanted to share a new project.

 

This is the first part and is a test of the "renderer", the scaling system, a lot of optimizations and some software sprites.

The second part will be the raycaster and moving around a level. The third part will have moving enemies, static objects and the interactions with them.

 

post-11240-1249866070_thumb.pngpost-11240-1249866079_thumb.png

post-11240-1249866083_thumb.pngpost-11240-1249866088_thumb.png

 

PM_1.zip

The graphic mode has 128 scanlines of GTIA modes 11 and 9 (interleaved, to get the PAL chroma effect for 256 colors), with a narrow field (32 bytes per line, 4096 bytes per buffer), so we have 64x64 "virtual" pixels. It's double buffered to avoid tearing.

The GTIA 11+9 mode is done using IRQ's every 2 scanlines, with the 15KHz clock, so I lose an audio voice and the "normal" clock. I have not tested it in real hardware yet, so probably the IRQ initializing will need some adjusts.

 

Keys:

 

I: Interactive mode ON/OFF (when "ON" you can move and scale the screen holding down the arrow keys)

 

P: switch between some Player/Missile effects (used for transparent "Hud like" effects, and the color bar is there to check the VCOUNT values)

 

S: switch between 0, 1 or 2 software Sprites. The code for the sprites is unrolled, but is not fully optimized right now.. is just to add a more "real" load to the engine.

 

L: switch between two "frame rate Lock" modes. It starts with the frame rate "unlocked", but if you add the 2 software sprites you can see the frame rate going down to 30 FPS. If you press L, then the frame rate is locked to 25 FPS in PAL (20 in NTSC) and all is more smoother. My final target is something near 25 FPS. Also you can see that the speed of the "barrels" is independent of the frame rate, that is because I use the "delta time" between frames to update its positions (counting VCOUNT lines). I don't used that for the background movement so you can see the difference.

 

 

My next goal is a raycaster that supports smooth rotations and strafe. I have done a fast (but simple) raycaster before and I have most of the problems for the new one solved on paper.. yeah, I could use the old one already, but it's not the idea :)

 

post-11240-1249865908_thumb.png

 

I'm not planning to do a full conversion (maybe the first level), just getting to the point where it will be easy to do something new. Having the 256 color is veeeery nice, but is a luxury.. not that much for the IRQ's (where I lose like 3000 cycles per hardware frame), but also for the resolution extra cycles and the memory. I can do a version for GTIA 9 (a dungeon like game, with more "lighting" effects) or GTIA 10 (using different colors per row) that could be a lot faster (and can look "better" in some ways).. and also work in NTSC.

 

I think I can do a game in 64K with this (right now I'm using like 40K, but I have not optimized for memory yet), but speed and graphic variations would improve by using a 130XE..

 

Tools: Mads 1.9.0.b14, ConTEXT editor, Atari800Win PLus version 4.0, Gimp 2, Irfanview 4.2 and my own graphic tools and converters.

 

Special thanx to Space Harrier XE for inspiration, some AtariAge threads and c64 users for "motivation" :D

If someone wants to do some "ambient" music (in RMT), that only use 3 voices and the main clock in 15Khz, I will be happy to add it to the next technical demo.

 

Regards!

  • Like 1
Link to comment
Share on other sites

Nice.

 

It looks much better than I'd have imagined such a system would have.

 

What degree of actual 3D calculations are used though? I can't seem to get anything other than a straight-on view in Interactive, but going back to auto you seem to get views that look like they're just off from 90 Degrees.

Link to comment
Share on other sites

Real machine - the Timers are way off, your GPRIOR changes are occurring roughly in the middle of each scanline.

 

Better join us in Sheddy's Timer thread.

 

One thing though - if you're wanting a Timer IRQ every 1 or 2 scanlines, then why not just use Voice 1 in 1.79 MHz mode? That way, you should get cycle-exact resolution for the IRQ.

Link to comment
Share on other sites

Real machine - the Timers are way off, your GPRIOR changes are occurring roughly in the middle of each scanline.

 

Better join us in Sheddy's Timer thread.

 

One thing though - if you're wanting a Timer IRQ every 1 or 2 scanlines, then why not just use Voice 1 in 1.79 MHz mode? That way, you should get cycle-exact resolution for the IRQ.

 

don't worry, I'm reading that thread :)

 

well, I don't used 1.79 because I believed that it doesn't worked in the emulator (and that's my main development platform right now), but if it's the best solution I will use it, you are right.. anyway I suppose that it should not be that difficult to sync the start of the IRQ's to the right position (in a real machine) and then the rest should follow in sync (and I'm not using DLI's in between)

 

There are no 3D calculations right now (that would be provided by the raycaster), in the "automatic" mode the height of every row is changed based on some sinus tables, there is no "real perspective" yet, only Y-scaling (that's why the textures seems to be "wider" when you reduce the height in the "manual" mode).. for that I probably will use other kind of mip map than the one that I'm using right now

Link to comment
Share on other sites

Yes, that's the problem with the emulator - Timer behaviour is somewhat different.

 

I've done a quick program that lets you Initialize Pokey with a different horizontal offset... if I can get it such that it makes your demo work properly on the real hardware, I'll put it up.

Link to comment
Share on other sites

Not having a great amount of success here. I've been able to realign Pokey so you get a glitch-free display, but the GPRIOR swapping always seems to be offset by a scanline, so you're not getting the proper display.

 

hmmm I had that kind of problem trying to make it work in the emulator, something like needing to add or remove a line in the DL or moving the DLI that starts all IRQ's one line up or down.. I will try to post some small demo code tomorrow to work over that, thanks for the help! I really don't know the correct method to sync the starting IRQ.. at one moment I wasn't even using STIMER and all seemed to work right in the emulator, but then I added some code and the lines that should be GTIA 9 were 11 and the GTIA 11 were 9..

 

going to sleep and then to work :)

 

Regards

Link to comment
Share on other sites

I think if you did a version that was offset one scanline, I could get it to work. I might see if I can patch your file so the DLI build is slightly different.

 

The emulator isn't very useful for Timers - pretty sure you get scanline resolution at best irrespective of divisor mode, and you can't get them to align to an exact cycle either.

 

I think for the time being, for such things we need to put Emulator detection code in such programs, and make appropriate adjustments for real machine vs emulator.

Link to comment
Share on other sites

I've worked out a kludge to get this working on real hardware.

 

I've patched the demo so there's 2 Blank lines instead of 1 after the DLI. ($9406 = $10 instead of $00)

 

PM1_patched.zip

 

To get it to work, use DOS 2, 2.5 or similar.

 

Firstly, Binary Load the POKINIT.XEX program. It will put a Player onscreen. Move it about 4 characters to the right with Joystick 1, then press Fire. Probably needs to be a bit further right than in the sample pic.

The program will return to DOS. Don't press Reset. Now run the PM1P.XEX program.

 

I've also set the COLDST flag, so when you hit Reset the machine will reboot.

 

The POKINIT program just lets you reset the Pokey Timers to be aligned with a certain cycle. The Player just gives a visual indication of where.

 

The demo looks much better than the pic suggests (picture from capture card).

 

post-7804-1249881725_thumb.png

Link to comment
Share on other sites

:thumbsup: this is very nice indeed. the speed is very impressive.

 

thanks.. well, you are somehow guilty of this :D

 

As promised, here is the code that I use to set the GTIA 11+9 graphic mode:

 

gmode.zip

 

the DL's are a little over complicated and I am only showing the first buffer, but the main code is there.. you can see where the changes are made because the COLBK color is different than 0

 

Mr. Rybags, could you post your changes and the code to sync the start of the IRQ's? so I can do a version that works directly on a real machine?

 

thanks!

 

NRV

Link to comment
Share on other sites

Just copy/paste this (AtAsm source) ... it's the complete code of the program that lets you sync Timers with the joystick. The graphical indicator isn't really proportional to what the timer offset is... in fact the delay is shorter for moving further right.

The bar changes to a brighter colour if you move so it wraps around... there's about 256 combinations... the code is a bit kludgy, whipped it up in 10 minutes type thing.

 

Just a couple of Q's:

 

- did you calculate what kind of cycle-savings you get using 16 Khz Timer vs DLIs to do the GPRIOR changes?

- what about when you want to go live with a real game? Being stuck in 16 Khz mode will put a big handicap on what sound you can do, so far as losing one voice and being stuck with either 16-bit/1.79 or 8-bit/16 Khz for music/fx.

 

Anyway... I gotta say it looks mighty impressive. Kinda makes you wonder why, despite the age of APAC, more people haven't bothered to do moving graphics using it before.

 

I say go for it 100% so far as creating a Wolf3D clone - if it takes 128K or 320K to make it work, well so be it. If it ends up running at 8 FPS once all the 3D and sprite mask/render comes into play... oh well, but at least it will look good.

 

Re the Pokey code... I'd like to do a more simple and usable one. Best way would be just a subroutine that you need to call once, passing it a parameter of which cycle you want Pokey Init released.

 

ed - re changes to your program.

All I did there was change the Blank Line instruction after your DLI so it was 1 scanline longer... you'll probably notice by running the patched version I put up that the graphics in the last 2 scanlines of the 3D window aren't quite right.

 

 

*=$4000
; Initialize Pokey
;
hposp0	= $d000
sizep0	= $d008
grafp0	= $d00d
trig0	= $d010
audctl	= $d208
stimer	= $d209
skctl	= $d20f
wsync	= $d40a
nmien	= $d40e
porta	= $d300
start
ldx $222
ldy $223
stx savevbi
sty savevbi+1
lda #0
ldx #8
clear1
sta $d200,x
dex
bpl clear1
sta sizep0
sta readyflag
sta nmien
lda #1
sta audctl ; 16 Khz mode
ldx #<vbi
ldy #>vbi
stx $222
sty $223
lda #$ff
sta 580 ; set Coldstart flag
sta grafp0
lda #$38
sta $2c0
lda #$40
sta nmien
wait
lda readyflag
beq wait
lda #0
sta hposp0
sta grafp0
sta audctl
sta nmien
ldx savevbi
ldy savevbi+1
stx $222
sty $223
lda #$40
sta nmien
jmp ($000a) ; Return to DOS
savevbi
.word 0
;
vbi
lda 20
lsr a
bcc do_move
jmp $e45f ; Skip each 2nd VBI
do_move
lda porta
lsr a
lsr a
and #3
tax
lda xdelay
clc
adc movetable,x
sta xdelay
ldx #$36
lda xdelay
sta jump1
bpl move2
ldx #$3a
move2
stx $2c0
and #$7f
clc
adc #$40
sta hposp0
lda #0
sta skctl
lda #3
sta wsync
jump1	= *+1
jmp $4100
xdelay .byte 0
readyflag .byte 0
movetable .byte 0,1,$ff,0

;
*=$4100
; Variable jump goes to this area.
.word $e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0
.word $e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0
.word $e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0
.word $e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0
.word $e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0
.word $e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0
.word $e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0
.word $e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0
.word $e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0
.word $e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0
.word $e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0
.word $e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0
.word $e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0
.word $e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0
.word $e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0
.word $e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0,$e0e0
nop
sta skctl ; Turn Pokey back on
lda trig0
sta stimer
eor #1
sta readyflag
jmp $e45f
;
; RUN Segment
;
*=$2e0
.word start

Edited by Rybags
Link to comment
Share on other sites

I say go for it 100% so far as creating a Wolf3D clone - if it takes 128K or 320K to make it work, well so be it. If it ends up running at 8 FPS once all the 3D and sprite mask/render comes into play... oh well, but at least it will look good.

 

8 FPS? Do we really need another slide show or unplayable demo?

For the FPS game 15 FPS is a minimum, and 20 would be fine enough.

I mean go for a game that is playable. FPS game should be dynamic, it's not an cRPG...

 

regards,

Jakub

Link to comment
Share on other sites

Thanks for the code! I will try to integrate and test it in real hardware before the weekend. I have a 130XE at hand but I need to write a real disk for every test (I only have a 1050 to PC cable), so is a little slow (and the drive sometimes fails).. well, if not I will try to post some new versions to see which one works

 

 

Just a couple of Q's:

 

- did you calculate what kind of cycle-savings you get using 16 Khz Timer vs DLIs to do the GPRIOR changes?

- what about when you want to go live with a real game? Being stuck in 16 Khz mode will put a big handicap on what sound you can do, so far as losing one voice and being stuck with either 16-bit/1.79 or 8-bit/16 Khz for music/fx.

 

Anyway... I gotta say it looks mighty impressive. Kinda makes you wonder why, despite the age of APAC, more people haven't bothered to do moving graphics using it before.

 

I say go for it 100% so far as creating a Wolf3D clone - if it takes 128K or 320K to make it work, well so be it. If it ends up running at 8 FPS once all the 3D and sprite mask/render comes into play... oh well, but at least it will look good.

 

Re the Pokey code... I'd like to do a more simple and usable one. Best way would be just a subroutine that you need to call once, passing it a parameter of which cycle you want Pokey Init released.

 

I started using DLI's but I need to waste too much time with them, because I cannot do the change before the start of a line.. IRQ's seem to be the best way. I would like to try using the 1.79 clock, I can live without a sound voice, but is nice to have the "other clocks" alternative (by the way, Miker already did a good ambient song using the clock in 15khz with 3 voices :D .. I will attach it to the demo and post a new version soon).

If you do your Pokey-init code please post it!

 

Yeah, I also don't know why people don't used APAC for games... well I know the problems, you need to use IRQ's so you don't lose too much time, only works in PAL and the overall brightness is lower.. but yet the results are very good.

 

My primary goal is still to do something in 64K that is very playable and fast.. between 20 and 30 FPS, lower than that I see it as a failure (sounds drastic but if I don't try I will never now :D) .. in this moment, I can have this graphics and the functionality of AR at 25FPS, easily (there are no moving objects there).. my final raycaster, with smooth rotations should also have a similar frame rate, so it all depends on how many objects I want in screen at the same time.. and I think you can design a fun game that don't need that many objects (or don't show them to you all at once :) )

 

Also, full GTIA 10 and 9 screens alone provide some interesting possibilities..

 

Regards!

Link to comment
Share on other sites

Gotta wonder...

 

in narrow-screen and with the OS switched out, would a routine pointed to direct from $FFFA/B be quick enough to change GPRIOR before the window starts?

 

If we did something like:

  PHA
NEWPRIOR=*+1
 LDA #$41
 STA $D01B

9 cycles there.

To "speed up" the necessary toggle between $40, $C0, make it self-modifying. Add:

  EOR #$80
 STA NEWPRIOR
 PLA
 RTI

Link to comment
Share on other sites

I'm going to talk about the emulator, but I suppose that in this area the behavior is the same that on a real machine..

 

The answer is "almost not"..

 

I started doing something like this for every scanline (also in narrow-screen, with the OS switched out and no NMI handler) :

 

DLI1_address
sta m_saveA

lda #PRV_GTIA_11
sta PRIOR

lda #<DLI2_address
sta NMIH_VECTOR

lda m_saveA

rti

;----------------------------------------
; display list interrupt 2 code

DLI2_address
sta m_saveA

lda #PRV_GTIA_9
sta PRIOR

lda #<DLI1_address
sta NMIH_VECTOR

dec m_dliLineCounter
beq DLI2_last_line

lda m_saveA

rti

;----------------------------------------
DLI2_last_line
lda #64
sta m_dliLineCounter	; reset last line counter

lda #0				; reset PRIOR to 0 for the rest of the screen
sta wsync
sta PRIOR

lda m_saveA

rti

 

and it worked when I have a main loop of the type: "MainLoop jmp MainLoop"

but when used in a real program, the "jitter" in the response of the interruption sometimes missed the start of the line..

 

so I thinked what thing I could still do.. and did this crazy thing:

 

DLI1_address
stx PRIOR
ldx #PRV_GTIA_9

sta m_dliSaveA

lda #<DLI2_address
sta NMIH_VECTOR

lda m_dliSaveA

rti

;----------------------------------------
; display list interrupt 2 code

DLI2_address
stx PRIOR
ldx #PRV_GTIA_11

sta m_dliSaveA

lda #<DLI1_address
sta NMIH_VECTOR

dec m_dliLineCounter
beq DLI2_last_line

lda m_dliSaveA

rti

;----------------------------------------
DLI2_last_line
lda #MAX_DLI_LINE_CTD
sta m_dliLineCounter	; reset last line counter

lda #0				; reset PRIOR to 0 for the rest of the screen
sta wsync
sta PRIOR

lda m_dliSaveA

rti

 

basically, sacrificed the "X" register for ALL the code...

 

don't do that! (it worked for sometime.. until I really needed two indexes :D)

 

Hi Heaven! :)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...