Jump to content

NRV

Members
  • Posts

    444
  • Joined

  • Last visited

  • Days Won

    2

Everything posted by NRV

  1. Yep, that's the original PC port. There was another version with improvements, but the links seem to be broken: https://code.google.com/archive/p/envisionpc-reborn/ http://atarionline.pl/forum/comments.php?DiscussionID=1220&page=3 Here is the version that I have: epcr.zip The "language" is something that I did for Project M because I was low on memory for more maps x). That second map (27 x 20 tiles, should use 540 bytes) look like this in code: TabMazeCode2 .byte MCMD_BLOCK, 28, 0,0, 32,45 ; full level .byte MCMD_REPEAT_IN_BLOCK, 5,2, 4,4 ; 5x2 empty rooms of 3x3 .byte MCMD_BLOCK, 0, 6,12, 3,3 .byte MCMD_REPEAT_END .byte MCMD_BLOCK_ARRAY, 9, 0 ; 9 empty space blocks .byte 2,1, 9,9 .byte 12,3, 7,7 .byte 24,3, 3,3 .byte 11,4, 1,2 .byte 19,7, 2,1 .byte 21,4, 1,4 .byte 22,4, 2,1 .byte 15,10, 1,6 .byte 17,17, 5,1 .byte MCMD_BLOCK, 28, 4,3, 5,5 ; normal brick block .byte MCMD_BLOCK, 22, 14,4, 3,2 ; purple brick block .byte MCMD_BLOCK, 21, 14,7, 3,2 ; red brick block .byte MCMD_POINT_ARRAY, 3, 11 ; yellow metal .byte 6,4, 7,5, 5,17 .byte MCMD_POINT_ARRAY, 4, 14 ; green metal .byte 6,0, 11,7, 13,17, 21,13 .byte MCMD_POINT_ARRAY, 8, 0 ; empty space .byte 9,17, 11,15, 13,13, 19,15, 4,5, 5,5, 6,6, 6,7 .byte MCMD_POINT, 1, 6,5 ; key .byte MCMD_POINT, 4, 6,17 ; gold cup .byte MCMD_POINT, 5, 26,4 ; teleporter .byte MCMD_POINT, 47, 27,4 ; animated texture .byte MCMD_END Obviously, you need to add the memory used by the code to "draw" those commands, so in the end I don't know if I ended using less memory x) (there are two more maps like this one).
  2. Well, I wouldn't call it exactly "early" The start of this thread is from 2010 and the map is the same as my last experiment: This was done in Envision PC. The 3 maps after this are done with a kind of "language" that draw the map in memory, so they use less space than the final size of the map. For example the next one: Basically the language let you draw square zones or lines of any type of tile, and also list of objects, if I remember correctly. For people talking about trading slanted borders of a column against vertical resolution.. I don't think it's a good trade off. Remember that you need both orientations for the slope (increasing or decreasing from left to right). That the slope can connect to the side chars, but also to the chars above or below them (because.. perspective). That you need more than the 32 different heights of a column, because for size 32 you still need some different columns, because the inside of the texture changes when you are nearer a wall. And the number of columns in a font is already very limited (128), so it would mean a very coarse vertical resolution in the end. I don't know if I read it well, but using more than one font per line is not useful for this technique. Assuming you can do it (is impossible in the bad lines and you are going to consume all the cpu in the char lines, for every hardware frame!) it doesn't help you, because you can need every possible column variation in any horizontal position of the screen (so they must be in every font used in a line).
  3. Thanks for the feedback, everyone. Not yet. I was hoping to have something that looked good with two players, using a GTIA like resolution (double width and double line for P/M's). What I know is that I would like to have the different sprite zoom levels in memory. I don't think that using a generic scaling routine is going to look good. The pilot running to your ship in Fractalus came to mind.. don't know if that is a good target x) Hmm I think it can do both, with one or two enemies active at the same time, but probably my first experiments will be more "action" oriented. Uff.. I don't think so I don't say it cannot be done, but using IRQ's is a far easier solution. Remember that my "logical" frame can take any number of hardware frames (and we are not talking about an "integer" number of them). If trying to use something similar to a kernel, I would start the kernel code with a DLI, just at the start of the APAC zone, and would return at the end of it. Doing it like that would mean that the PRIOR changes use the less processing time possible, but then you need to do something useful the rest of the time (while still in the kernel). And I don't have a task that I can easily interleave with that job. Rendering sounds like a good candidate, but it would still be difficult. Playing music could fit, but I wouldn't want to do that with RMT.. it would have to be my own code. I don't think they would be less "visible", but if you are talking about the "sensation" that a bigger screen produce, sure. I didn't mention it, but Project X is the perfect candidate to use the full screen. Adding 8 more columns for raycasting would slowdown it, but maybe not that much, and increasing the height is kind of "free" with this renderer. Except for the cost of the extra IRQ's and the display list lines, of course. RIP was the mode that used GTIA 10 and 9?. I would like to test it at some point, but I don't think that the displacement between both modes qualify as "160" width resolution A couple of years sounds good ? I didn't feel this test merited a xex file yet.. the same maze.. simple columns as objects.. so let me think about it x) About the mode.. is pretty simple in reality. Mirroring is not used, the different vertical gradient of colors should give up that away. Is like the idea from Irgendwer, but not for LMS lines. Instead is for columns of chars. It could be done with only 32 bytes. So let me start there.. You have 16 lines of chars and every line has a different font (so I use 16K in fonts). But every line in the display list, points to the same 32 bytes of memory. So when I put a number in the first byte I automatically draw that whole column in the screen! Is like the idea of using different fonts for using char software based sprites, but taken to the extreme x) But as I said, you are very limited in the number of designs you can use for the walls. You need all zoom levels for every column in the fonts. In this case it would have been useful to have fonts with 256 chars.. but that also would mean needing 32K of memory! Finally, with 64 bytes I can have one version of a column for the top half of the screen and another for the bottom half. So I have more "design" options for the walls. I can mix and match different top and bottom parts. Also, I'm not using all of the font rows, so there is still space to use char based software sprites with this.
  4. I had some time after the Raymaze thingy and I used it to test some ideas "accumulated" in my head, after all these years. So be warned, long post ahead, with raycasting ramblings.. I had 3 things that I wanted to see working: - what I call the "line flicker" effect for APAC modes - an idea for a new (very fast) renderer, called Project X, that uses APAC over a char mode - and all the logic to have objects working APAC Line Flicker: The line flicker effect is basically having a normal screen in the "even" frames, and setting the screen one scanline down in the "odd" frames. So for an APAC mode, the GTIA 11 and 9 lines of one frame mix/merge with the GTIA 9 and 11 lines of the next frame. Then this is similar to interlace, but the idea is to reduce the dark lines product of using the GTIA 11 mode. Here.. a video is better.. (you need to set the quality to 720p50Hz to see it): In the middle of the video I activate the "frame blending" option in Altirra, so that's why the effect start looking "better". From what I understand some modern TV's do a similar effect. I'm a little undecided about this, but it could be an option. Probably I could give a final verdict if I see it running in real hardware. I think it would be a little better in NTSC also (30 Hz instead of 25 Hz). Implementing this with DLI's is trivial, but with IRQ's it was kind of a "side quest". First problem was that I was using one IRQ every two scanlines, to flip between GTIA 11 and 9 every line. Why?, because for 32 bytes mode lines, is faster to do a medium IRQ every two lines, than one small IRQ every line. Given that I was also going to implement this effect over a char mode, using one IRQ every two lines was "convenient", to skip the bad lines. But if you want to move your screen one scan line down, every "odd" frame, you will need to re sync the starting point of your IRQ's. That means touching SKCTL (15KHz clock) or STIMER (1.79MHz clock) every frame. And if you also want to play sounds or music, you don't want to write SKCTL or STIMER every frame, because they are going to sound wrong. I don't know if there is a way to do that.. maybe this is a question for phaeron In the end, I also needed to change the font every mode line, so with all those requeriments, the only solution was having one IRQ every line. Using the IRQ on channel 1, clocked to 1.79MHz, I can use the remaining 3 channels without any restriction (no need to force the music to 15KHz). Also you can sync the IRQ's to a point before the start of the badlines, so there is no conflict there (it still needs to be short). And you can move your screen one scan line down every odd frame, without the need to touch STIMER, just by moving the scan line of your DLI that init the IRQ's for that frame. Project X: The idea behind Project X was having a renderer with a processing cost near 0.. is that even possible?, without using all the memory?. Well.. yes. For starters one screen window uses 64 bytes, compared to the 4K per screen of Project M. So is kind of obvious that writing 64 bytes is a loooot faster than writing 4K (we are talking about the same screen resolution). I suppose this is a good example of the flexibility of the A8 to generate special "graphic" modes x) The big drawback of this mode is that you can only have very simple walls, so no complex textures. If you are smart you can have a good number of variations (more with a cartridge), but you have only a few number of different designs to use. The good thing is that they can be colorful, you win a nice and free depth cue effect, and you get back like 16K of ram (comparing it to Project M). Also, most of the processing time can be dedicated now to the "raycasting rays" part, and also.. objects experiments. Project M has a type of renderer that uses a block of around 14K for the scaling code (to scale up or down the textures). The scaling code points to a fixed 8K area in memory, where all the textures reside (and that would be one hell of a use for the banks of a cartridge). This is basically precompiled code, very fast, but still need to fill a 4K area for every logic frame. On the other side, Project X is the type of renderer that has all possible wall columns already scaled in memory, so it only needs to write 2 bytes to generate a final scaled wall column on screen (with background included). For this particular renderer it could be useful to use GTIA 10 instead of 11, to generate the color part of APAC, but I would need to see how that looks, because of the different offset of the GTA 10 pixels against the GTIA 9 pixels. Another advantage of Project X, is that it allows the camera/player to be closer to the walls, so is easier to move through doors. Also, the extra speed allowed me to increase the visual quality, using more precision on some of the raycasting data. Raycast Optimizations: After this, it was time to optimize the raycasting code. Now that the camera pivot is in the player position, there was a way to speed up a lot the camera rotations. It could have minor visual imperfections, but they are noticeable only if you are looking for them, so I tried it on. Then.. rotations were running at 54 fps in PAL ... yeah that's not an error (still NTSC was a little slower than 60). Because my frame rate was never that high and I use double buffering, I never needed a hard screen sync before. So it could happen that I render more than one logical frame per hardware frame. I added a "soft" kind of screen sync, so PAL don't go over 50 (softer than just waiting for a specific VCOUNT value, I wait for a VCOUNT "zone", so you can start rendering the next frame sooner, if the previous one was shorter than average, for example). After that, was the turn to improve all the raycasting that is done outside rotations. I had the idea, long ago, about interpolating most raycast info between 2 rays that were touching the same wall. The full idea means doing something like a binary search over the rays, and a general interpolation between any two rays. But there is a danger that doing all that could end up costing you too much time. So I decided to do a simplified version, that only check if ray N and ray N+2 touch the same wall, and then see if it can interpolate most of the data from ray N+1 (interpolation is also easier this way, with some specifics to the type of data you are interpolating). It was another good optimization. I would say in average 8 rays get interpolated (which is a lot faster than doing the raycast). So the speed up is similar to the one when you run Project M in the smaller window (starting the demo with SHIFT pressed). I can easily move these optimizations to Project M (fighting a little with ram distribution), so that's a low hanging fruit for the future. Objects: The implementation for this is another old idea. It was kind of surprising that it worked so easily and without major issues x) Basically, for every active object, I need to get the direction from the player, the distance and the screen size of the object. For every one of these I have a table that is accessed using the positive deltas between the camera position and the object position. Is little more complex, because there is also a "scale factor" involved, that is related to the distance between the camera and the object. If the object is closer to the player, then the tables provide more "resolution" for the data that they contain. The direction is transformed into a world angle index, that is later changed to a screen angle index, to see if an object is inside the screen. Then the distance is used to see if we need to clip some columns of the object, against walls that can be between the camera and the object. Finally the object should be rendered using the correct sprite frame, for an object of that size and with that orientation. This is different in the video, because for now I only draw columns of different width and size, and also change the color according to the distance. Right now the angle table uses 1K and I think it would look better with more resolution (that would mean 4K instead). The distance table uses 256 words (so 512 bytes), and it haves 7 bits of precision that I'm not using yet, but it works well enough. I was using a size table of 256 bytes, but in the end I don't need it, because objects also need the perpendicular distance to the camera (same correction as wall columns), so I'm using the same code used for the walls, to get this scale factor. In the video I implemented two "objects", one of them moving in a loop. They get activated when they are at a "visible" distance from the player (like 8 tiles away) and if they are disabled they should not cost much processing time. Probably two enemies at the same is a good rational limit for this engine, but I would have to test this more. Set the quality to 720p50Hz also for this.. For the future: (whenever that is..) For Project X, it could be useful to force a max frame rate of 25 in PAL (30 or 20 in NTSC), so it is a little more stable. Now it can go from 50 to a little below 20 (in very specific points of the maze, looking in specific directions and with 2 objects active.. but maybe I can optimize this worst case), so that variation may bother some people. In general I would say the average goes between 25 and 35 fps. So maybe locking the upper limit could be another option. Also, for any movement logic, is better to have a stable frame rate, but you can also solve this moving the logic to an interruption. The next step would be using better graphics for the objects, and that would require more complex clipping and lots of sprite frames . This can be done using P/M's, or char based software sprites in Project X (there is space for that), or just software sprites, in Project M. I also need to move the optimizations and the object code to Project M, but maybe it would be more productive to start migrating everything to a cartridge. Regards!
  5. What happens if you restore the emulation to normal settings (normal speed, collisions on) just before the crash?
  6. Nope (that would have been reeeally weird). I mean, PRINTSCREEN just save what you see in the screen at that moment in the emulator (the correct black). Something like: Versus: (PAL artifacting, with "save frame")
  7. Well mads has the precedence in the documentation: Operators Binary operators: + Addition - Subtraction * Multiplication / Division % Remainder & Bitwise and | Bitwise or ^ Bitwise xor << Arithmetic shift left >> Arithmetic shift right = Equal == Equal (same as =) <> Not equal != Not equal (same as <>) < Less than > Greater than <= Less or equal >= Greater or equal && Logical and || Logical or Unary operators: + Plus (does nothing) - Minus (changes sign) ~ Bitwise not (complements all bits) ! Logical not (changes true to false and vice versa) < Low (extracts low byte) > High (extracts high byte) ^ High 24bit (extracts high byte) = Extracts memory bank : Extracts global variable value Operator precedence: first [] (brackets) + - ~ < > (unary) * / % & << >> (binary) + - | ^ (binary) = == <> != < > <= >= (binary) ! (unary) && (binary) last || (binary) I tried to see it your way, but I couldn't.. I feel that mads is doing the right thing, but maybe is out of habit But I think I would find it strange if: "<LABEL + 1" is different than "1 + <LABEL" ..
  8. Don't know why, but in the last tests, if I do "save frame" with "PAL artifacting" (and only with that artifacting mode), the black backgrounds is a light gray instead..
  9. Nice... never used it, but always believed the common myth about it, that the overflow bit indicates a carry (or overflow) from bit 6.. x)
  10. That's the correct "generic" way of doing it, but you also could have different logic for different "quadrants" for the ray (centered in the viewpoint position). So, for example, a ray moving in a "top-left" direction, could check X against the 0 limit and Y against the 256 limit only (assuming coordinate Y grows from "bottom" to "top"). Also, you normally trace rays from left to right ("clockwise"), so you don't change "quadrants" that often.
  11. I have not seen your code, but the basic algorithm should be something like: loop: - sync to some screen line - show screen buffer 1 work on screen buffer 2: - erase previous sprites in buffer 2 (needs a list of the positions and sprite types previously drawn in buffer 2) - update real sprite positions (and animations, creation, destruction..) - draw sprites in buffer 2 (save positions/types in list for buffer 2) - sync to some screen line - show screen buffer 2 work on screen buffer 1: - erase previous sprites in buffer 1 (needs a list of the positions and sprite types previously drawn in buffer 1) - update real sprite positions (and animations, creation, destruction..) - draw sprites in buffer 1 (save positions/types in list for buffer 1) jump loop:
  12. Have you tried using "speed control: trigger" ? Maybe that way is easier to move at the low speed, and then you can accelerate only when you need it
  13. I have very little play time with any of them, but here is my vote: 1. Gravity Worms 2. Dungeon Hunt II 3. Fruity Pete 4. The Rescue Expedition 5. Berks Four 6. Star Vagrant 7. Castle Defender 8. Jet Set Willy 2019 9. Imogen 10. Monty on the Run
  14. Thanks everyone! About ABBUC, well it wasn't ready on time and I didn't want to wait for the next one x) So maybe I should do something new for this year.. Here is a video (in not-like-a-man's form) from VinsCool, with the soundtrack of the game:
  15. So, somehow a char based, software sprite demo, ended as a game.. We started iterating on this in 2018, with MrFish, but after some months we had to stop for different reasons. At that point the game was already very playable, with the classic levels, so it was kind of sad not publishing it, so people could play it. Then at the end of 2019 I had some time to improve it and finish some features, but it ended with a lot more things added x). VinsCool started working on it and did all the great music (all 3 arcade tunes and more). Therealbountybob did testing and proposed some nice improvements (and also made a case for the PAL version). Synthpopalooza did his magic and created some great sound effects. MrFish came back to do more art and propose new ideas. So, what is this? (from the Readme.txt): Raymaze 2000 is an action game, based on the Taito arcade game Raimais (from 1988), but is not a direct port. It has a set of 14 levels based on the original ones, with classic enemies and powerups, but also adds a lot of new things: - a new branch of 17 original levels - new enemy behaviors - some new powerups and secrets - improved controls and also new ways of controlling your vehicle - 3 difficulty levels (Casual, Medium, Expert) - other new gameplay ideas (Raimais could be seen as an improved version of Head On, or maybe Pac-Man, something like what Taito did with Breakout/Arkanoid or Qix/Volfied). NTSC vs PAL: If you want to play in the emulator, then is better to choose the NTSC version. Not only because of the 60 fps, but also because the game speeds, colors, music, sounds, were first created for NTSC and later translated for PAL. Both versions are pretty similar anyway, let's say over 95%.. but there are some things you cannot replicate perfectly, like the colors and some timings. Future developments: The memory of a 64K computer is almost full, so I will need to create a proper .atr version, with loading, if I want to add anything. We had a lot of ideas between MrFish and I, that we would like to test at some point, but who knows when that will be. But because of that we could say that this is version "0.5" of the game that we had in mind :). Contents of the zip: Raymaze_2000_NTSC.xex (the main version), Raymaze_2000_PAL.xex, Readme.txt (a mini manual), plus some game screens. The game needs an A8 computer with 64K. The .xex start loading from memory address $2800 (10K), but at the end it loads a final segment over an address near $2000 (8K), so I hope it works without problems in real hardware. Enjoy! Raymaze 2000.zip
  16. If you don't need "source" updated at the end, you could just use Y: .export _plot_bitmap_fast destination = $d4 ; address of gfx buffer source = $d6 ; address of 16 byte array .proc _plot_bitmap_fast ldy #0 loop: lda (source), y eor (destination),y sta (destination),y iny ; point to second byte lda (source), y eor (destination),y sta (destination),y iny lda destination clc adc #40-2 bcc no_inc inc destination+1 no_inc: sta destination cpy #8*2 bne loop ; and write the next row of bytes exit_fast_plot: rts .endproc
  17. Well, there is the recent research done in this thread, starting from this post: But I haven't seen anyone talking about important differences, between different machines..
  18. I was thinking about something similar once, but how do you define the "next frame"?. Using VBlank?, similar vcount value?, same code instruction? (assuming the same code is triggered the "next frame"), end of the display list? start of the next one? ...
  19. Is there a document about the debug features, other than the help menu in Altirra and the help from the command line in the debugger? I'm a new (noob) user of the debugger and would like to know a little about the Watch windows, and some examples for the use of the heatmap. I started using the ##trace and ##assert commands from a mads listing, and they are great for logging values and checking conditions. But for my current problem, it would be great to be able to enable/disable "asserts" from the source, or something similar. My idea would be to trap any write to a small table, when it comes from "invalid" code only. Would you say this is already possible, using conditional breakpoints (bx) and using a condition like "(pc != valid_code_adr1) and (pc != valid_code_adr2) ..", listing all the valid code addresses? Also, would it be too difficult (or slow) to have a Memory window that is updated once per frame? I know about the watch commands, but sometimes you need more than 8 watches
  20. Could you do things like following the player from side to side with the camera, or small bobs up and down according to the bumps in the track? (also for the camera, with a spring or sine-like smoothing). Maybe allowing the ships to "jump" when hitting bumps, or rolling a little when moving from side to side.. also projecting a fake shadow in the ground (a black circle/ellipse sprite would be enough). There is a lot of small details that would allow you to "sell" more the 3d effect, but I don't know how flexible is your current engine / 3d pipeline.. And after that, things like allowing the camera pitch to change according to the pitch of the track, or allowing the camera to roll a little if there are turn sections.. Would be too much work to generate your track points procedurally? Regards.
  21. Nope, that's not how you do it. You can have smooth animation and movement of your software sprites, in a char based mode, over a detailed and scrolling background (if you want), without requiring a lot of memory. And in some cases it could be faster than doing the same in bitmap mode.. but that analysis would be for a long post x) You don't need to have every combination of a sprite and background in memory (well.. if you have the memory, then that would be faster :)). What you do is to reserve some some chars in the font for your sprite, and when you want to draw it to the screen, you put those chars over the background. THEN you write the same background info that was there before, INTO the memory in the font, for those chars. After that you write the sprite data over that same font memory, using proper masking (and, ora instructions). There is some extra details, but that's the general idea..
  22. I have done some old experiments with software sprites and I'm also a "macro lover", for precompiled sprites x) From what I remember there were different ideas used, but sadly neither of the examples used a scrolling background. A more recent one, for char software sprites (also with source): https://atariage.com/forums/topic/282434-char-based-software-sprites One interesting thing in the macros of the last one, is that the "write byte" part was "aware" of the previous byte, so it can generate consecutive "sta" if writing the same byte: .macro MACRO_DRAW_BYTE .if (([%%1%%3] == 0) && (:?DRAW_STA_OPT_FLAG == 1) && (:?DRAW_STA_OPT_VALUE == [%%2%%3])) sta (m_newCharFontAddress),y .elseif ([%%1%%3] == 0) // mask byte == 0 ? (only new byte then) lda #[%%2%%3] sta (m_newCharFontAddress),y .def :?DRAW_STA_OPT_FLAG = 1 .def :?DRAW_STA_OPT_VALUE = [%%2%%3] .elseif ([%%1%%3] == $FF) // mask byte == $FF ? (only old byte then) lda (m_oldCharFontAddress),y sta (m_newCharFontAddress),y .def :?DRAW_STA_OPT_FLAG = 0 .else lda (m_oldCharFontAddress),y and #[%%1%%3] // invert the mask here? (in another place is better) ora #[%%2%%3] sta (m_newCharFontAddress),y .def :?DRAW_STA_OPT_FLAG = 0 .endif .if (:4 == 0) iny .endif .endm Anyway, I still think is better to write an external tool to generate the precompiled sprite code
  23. What I used in my clone, to avoid a ball trapped in an "infinite" loop, was using a counter to track the number of times the ball hits unbreakable bricks. If that number gets to 100, I change the current angle of the ball slightly, and reset the counter to 0. Also, if the ball hits any other type of brick, the paddle or an enemy, the counter is also reset to 0. Maybe some powerups could also reset the counter.
×
×
  • Create New...