-
Posts
172 -
Joined
-
Last visited
Everything posted by crem
-
Yes, it's happening, I'm generating the walkthrough for Jet Set Willy, similarly to what I did for Manic Miner. \o/ I'll describe the technical part of it in a later posts, for now I just want to announce that I've started it and start this thread. Initially I thought that I'd make a website where the progress could be tracked, and possibly where people could help with computing power, but: I was lazy to implement it, Single room generation turns out to be much faster than I expected (around 5 minutes instead of 5 hours per room), thanks to the optimizations suggested on this forum and much easier level structure than Manic Miner. I'm still finishing the "strategical routing" algorithm (e.g. order of rooms rather than in-room routing; I call it "journey" rather than "route" just to have a different term for it), during the next days while the "journey planner is not yet ready" I'll use @RuffledBricks speedrun route and will run the script to micro-optimize it. Aaaand to get started with something concrete, here is the speedrun of the very first room. 😛 Enjoy! jsw_init.mp4
-
Thanks, it was indeed a bug on my side. When I saved/restored states in Manic Miner, I saved some memory locations and all registers. For JSW, I thought that there's no need to store registers as when frame starts (pc=#89ad), none of registers are expected to have meaningful value. But actually the PC itself may be wrong. If during the previous attempt Willy hit a guardian (and breakpoint at #8c01), it's not enough to just restore the memory, PC has to be restored too. I'm not sure whether any other register matters at that point (SP maybe?), but just to be on the safe side, I'll include all registers into the state.
-
Quick question. I have a breakpoint at address #8C01, and generate various playthroughs in JSW, and it sometimes happens that number of lives decreases (and guardian cycles seemingly reset) without hitting that breakpoint. I'm fairly sure it's bug in my code, but just checking, maybe I missed something in JSW code... Could you think of some ways of this happening in JSW? (number of lives decreases without hitting breakpoint at #8C01). That happens in the very first room, "The bathroom". Thanks!
-
I didn't write anything for Z80 in C (actually, neither I did in assembler), but my understanding that C compiler produces decently good code as long as you are aware about Z80's limitations: There are no good array indexing instructions in Z80, so accessing e.g. iterating arrays by index should be avoided (the only exception is when array element size is 1 byte and array index is a signed single-byte value). Instead it's better to e.g. compute end pointer and do pointer comparison. Function arguments are passed through registers, so recursion should be avoided. Sorry for another redirect, but I believe this forum should have much more experience in using C with Z80 CPU.
-
Hi! I've noticed that there are two small things about the website which while not not extremely important, cause minor annoyances, which I think would be easy to fix. 1. Favicon This site happens not to have a favicon. That makes it sometimes hard to find among tabs of other websites. 2. Https I don't care about the security aspect of it, but more and more browsers start to shame http only sites. E.g. it took me like 30 seconds to convince Vivaldi browser to send my password over http when I tried to log in. Also there is a rumour, that doing that would put you slightly higher in search engine ranking. With appearing of https://letsencrypt.org, setting up https is both free and (relatively) simple (using their tool called certbot, which in most cases does everything automatically). There is even easier way which don't require managing/renewing the certificate (but would require switching to use cloudflare nameservers though, so maybe not easier): set up cloudflare layer (also free).
-
It is possible that two versions require different route for the Amoebatrons' Revenge. The route for the SP version is here:
-
Totally offtopic for this thread, but I'm just curious. Usually when talking about memory addresses written in hexadecimal form, I can see 3 prefixes are used: #, $ and & (#DA78, $DA78 and &DA78) (Also there's 0xDA78 and DA78h but those I know where they come from). I wonder which of those prefixes is more common and where they all come from? I know that in Pascal $ is a prefix for hex numbers, but weren't there a Z80 assembler which used that?
-
Were all examples of truncated posts truncated on word boundary? If yes, I think maybe there are some Unicode characters that database doesn't understand? Like emojis with codepoint values larger than U+FFFF. Or maybe when copying/pasting around, some control characters (like byte order marks) were carried along, and database didn't like it? Do you know in which format the data is stored in database? Is it possible to look at database for raw posts? Another option could be that there's something weird at parsing level, not at database level (then in the database the posts are still intact). E.g. if there's some unmatched control codes (like [/bold] without [bold]), the post parser/formatter stops formatting.
-
One more case where it could matter is if LDIR overwrites the memory of the instruction itself. Hopefully that doesn't happen in JSW though. Also I'm a bit afraid that after my replacement it with a simple memcpy, I'll leave cpu in wrong state (e.g. forget to set flags which would be needed afterwards... But I think JSW doesn't rely on register/flag values after LDIR instructions). I'll give it a try anyway. Do you think something like that would be good enough (e.g. ignoring all flags altogether)? uint16_t hl = GET_HL(); uint16_t de = GET_DE(); uint16_t bc = GET_BC(); memmove(&memory[de], &memory[hl], bc); // Can overflow if goes over 0xffff but should not happen in JSW SET_HL(hl + bc); SET_DE(de + bc); SET_BC(0); The current emulation code also does some magic with Y, X and V flags, and I never even heard about those Z80 flags. 🙂 Hopefully it's ok not to touch them. Although maybe it makes sense to reset S/Z/C.
-
Thanks a lot, that helped a lot! Without changes I could generate 2450 frames per second. With 3 LDIRs replaced with NOPS, 3950 fps. With your changes (and LDIRs replaced) -- whopping 5130 fps! With LDIR being so slow, I'm thinking of changing the emulator to just run memset() for LDIR instead of emulating it "properly" (with fetching instruction on every iteration, incrementing all the registers and updating t-state count as it runs). Maybe then it would get even higher. For now I'm not sure if that's worth the time to implement it, so any other micro-optimizations like that would be appreciated.
-
Now I'm trying to speed up JSW emulation (and don't care what's displayed in the screen). Do I understand it correctly, that it's safe to remove LDIR at addresses #89FE, #8A2F and #8B10, but not the ones at #89B9 and #89C4? (addresses taken from https://skoolkit.ca/disassemblies/jet_set_willy/hex/asm/89AD.html and https://skoolkit.ca/disassemblies/jet_set_willy/hex/asm/8B07.html)
-
Would you want that in ZX Spectrum or any platform? I believe on PC that would be one week of coding + some weeks of graphics/level/sound design. xxiv) mass multiplayer 😛 ..would add some months to development. 🙂
-
I didn't do the full run, but I started it once watched some "intermediate" bests (the fastest way Willy can get to the particular parts of the level). All those routes had waiting somewhere, so I concluded that waiting would be unavoidable in the final run too, that one extra frame won't help. Yeah, actually I was wrong when said it's the same number of frames but 4 points less solar exposure. Indeed, the route is much longer now, but having one intersection fewer with the solar beam compensates it.
-
Here it is (the rightmost column; two others are frame number and "air left + some constant"). lvl19-air.mp4
-
...and I found the bug. 🙂 Lvl19, Score=1137 The same number of frames as the previously known best, but manages to have 4 more points due to less solar beam exposure. R R R R . Q R . Q R R . Q R R R R R R R R R R R R R R R R . . . . . . . R R R R R R R R R R R R R R R R R R R R R R RM . . . . . . . . . . . . . . . . . . Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q QM . . . . . . . . . . . . . . . . . . Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q QM . . . . . . . . . . . . . . . QM . . . . . . . . . . . . . . . . . . R R R R Q R . Q . R Q . R R R R R RM . . . . . . . . . . . . R R R R R R R R R R R R R RM . . . . . . . . . . . . . . . . . . R R R R R R R R R R R R R R R R R R R Q Q Q M . . . . . . . . . . . . QM . . . . . . . . . . . . R RM . . . . . . . . . . . . . . . Q Q Q Q QM . . . . . . . . . . . . Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q QM . . . . . . . . . . . . . . . . . . Q Q Q Q Q Q Q Q Q . . . . . . . R R R R R R . . . . . . . Q Q R RM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . QM . . . . . . . . . . . . . . . RM . . . . . . . . . . . . . . . . . . Q . R . Q . R . R R R R RM . . . . . . . . . . . . R R R R R R R R R R R R R R R R R R R RM . . . . . . . . . . . . . . . . . . RM . . . . . . . . . . . . QM . . . . . . . . . . . . . . . . . . Q R R . R R Q QM . . . . . . . . . . . . R RM . . . . . . . . . . . . . . . R R R R R R R R RM . . . . . . . . . . . . RM . . . . . . . . . . . . . . . . . . Q Q Q Q Q QM . . . . . . . . . . . . . . . . . . Q Q Q Q QM . . . . . . . . . . . . . . . . . . . . . . Q Q R Q R . Q R Q QM . . . . . . . . . . . . Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q . R R Q QM . . . . . . . . . . . . . . . . . . Q Q Q Q QM . . . lvl19.mp4 lvl19.rzx
-
Indeed I think I didn't post it earlier, here it is. lvl8.mp4
-
Yeah it's possible. I'd estimate the probability that better solution exists less than 50% but still much larger than 0%. Maybe 30% chance. Worth giving another try.
-
I decided to give level 19 another go with extremely long search (2 days long) and extended logging and also additional checks that watch where the search starts to miss the current best score. It turned out that I have a bug somewhere. At frame 720 it said that it found another way to reach the same position with more AIR remaining, so it pruned the original state. At frame 759 it reported that if you press the same keys from that "better" frame 720 as in the original walkthrough, it results on losing a game (probably colliding with a guard). Which means that probably I have a bug in duplicate state detection, those states also differed by something else..
-
Hi all, I've started to work on building tools to generate a walkthrough of JSW (no estimations on timeline yet, and whether I have enough enthusiasm to finish yet; I hope so, although it feels a larger project than MM 🙂 ). I have a few questions on how to interpret the memory state (I have assumptions for most of those but it would be nice to confirm it). 1. There are 1-byte 0x85CF "Willy's Y location" and 2-byte 0x85D3 "Willy's attribute location in a buffer" variables is the game. At the beginning of the frame (when PC=0x89AD), is it always true, that memory[0x85D3]=0x5c00+32*(memory[0x85CF]/16)+x_offset? In other word, can it happen that they go out of sync (on the rope, on the ramp, during the jump, during room transition etc)? 2. Is it true, that [at the beginning of the frame (when PC=0x89AD)], I can ignore/write garbage to 0x85D5 "Jump animation counter" if 0x85D1 "Airborne status indicator" is not 1? 3. To save the resources and not try to press keys when Willy is jumping/falling, in Manic Miner I used the following logic: a) If before the frame, "Airborne status indicator" is 0, try all input combinations, else only try "no keys pressed" b) If _AFTER_ the frame, "Airborne status indicator" is 0, also try all other combinations for the previous frame (if didn't try already). Questions (both for MM where it seemed to work, and in JSW where I hope it to work): - Is it enough? (e.g. are no special cases like falling onto the edge of conveyor belt etc) - Maybe there's simpler logic? 4. It looks like "Willy's Y location" is rounded to the multiple of 16 if Willy is on the ramp. How exactly the logic that draws Willy goes then? "If Willy is in the same cell as ramp and not jumping/falling, move him up depending by the 0x85D2 "Willy's animation frame" value, but if Willy is jumping above ramp, 0x85CF "Willy's Y location" contains true Y position" -- is that understanding correct? Thanks!
-
Level 17 "The Warehouse", Software Project edition Score=1952, one frame improvement (and slightly different route) R R R R R R R R R R R R R . Q . . Q . . . R Q Q . . . . R . . . . Q Q . R R R R . . . R R R Q Q Q Q R . . . R R Q . Q R R R R . . . R . Q R . . R R R . . . R . Q Q Q Q Q Q R R . . . . Q Q Q Q QM . . . . . . . . . . . . R . . . . Q Q . . R R . . . R RM . . . . . . . . . . . . . . . . . . . . RM . . . . . . . . . . . . . . . . . . R R R RM . . . . . . . . . . . . R R R R R R R R R R R R R R . . . . RM . . . . . . . . . . . . R R R R R R R R . Q Q R . . . R R R R R R R R R R R . Q . . . . . QM . . . . . . . . . . . . RM . . . . . . . . . . . . R R R . Q R RM . . . . . . . . . . . . . . . RM . . . . . . . . . . . . RM . . . lvl17-sp.mp4 lvl17-sp.rzx
-
Level 18, Software Projects version, no difference, score=1314 😞 I expected that there would be a difference, probably 1 frame, and not necessary an improvement. Q Q Q QM . . . . . . . . . . . . . . . . . . Q Q Q Q Q Q Q Q Q Q R R R R QM . . . . . . . . . . . . . . . . . . M . . . . . . . . . . . . . . . . . . M . . . . . . . . . . . . . . . . . . QM . . . . . . . . . . . . . . . . . . M . . . . . . . . . . . . . . . . . . QM . . . . . . . . . . . . . . . . . . Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q Q QM . . . . . . . . . . . . R RM . . . . . . . . . . . . . . . Q Q Q Q R R R R RM . . . . . . . . . . . . . . . . . . RM . . . . . . . . . . . . . . . . . . R R R R R R R R R R R R R R Q R R R RM . . . . . . . . . . . . . . . . . . R R RM . . . . . . . . . . . . Q QM . . . . . . . . . . . . Q Q Q Q Q Q Q Q . R R R Q QM . . . . . . . . . . . . . . . . . . Q Q Q Q Q Q Q Q Q Q Q QM . . . . . . . . . . . . . . . . . . Q QM . . . . . . . . . . . . . . . . . . . . R . Q . . . Q . Q Q QM . . . . . . . . . . . . R RM . . . . . . . . . . . . R R RM . . . . . . . . . . . . . . . . . . RM . . . . . . . . . . . . . . . . . . Q R R R R . R . Q R R RM . . . . . . . . . . . . . . . . . . R R RM . . . . . . . . . . . . . . . . . . R R R R R RM . . . . . . lvl18-sp.mp4 lvl18-sp.rzx
-
Works like a charm, thanks! I've started calculating Amoebatrons' Revenge, should have the results in the evening.
-
Thanks for the suggestion, I indeed noticed that 40% of the time my tool spent in LDIR instruction emulation and thought about doing such change, but I was lazy to check whether that change would break something (e.g. maybe something after this instruction relies on BC being equal to 0 or something like that). During the search process I actually only show the screen only once per 10000 frames or so, just to visually control that the search progresses as expected. What I could do is to put LDIRs back only before the frames where I going to show the screen contents. Usually, it took around 10-12 hours to process one cavern. With this optimization it would be 6-10, would surely be useful. However, now that MM is almost "done", I think it's too late to implement such optimization. I'll surely look into that when I start the search in JSW. Will probably need some help in this forum. My experience with Z80 CPU is quite limited, I've read some books on this topic and also read some code, but I believe I've never written a single Z80 instruction myself.
-
Surely will do! Could you help me to pick a right file with this version, is it this one? (from worldofspectrum) Do you know if the memory layout is the same in this version? (currently I use a breakpoint at $870e to separate frames, at $8908 to detect loss and at $902b to detect win. Also some memory locations here to fetch state details) Interesting, I thought all collision detection was pixel-based.
-
During last 3 days, I had five "the final" runs of Level 19, and after every run (which takes ~12 hours) I realized there's a typo or another silly bug in my code. The last such attempt finished a few hours ago. I'll probably take some pause before doing yet another attempt, but for now here is one more interesting lvl19 attempt. Score=1127 (6 points below the current best), but even less sun exposure, only 148 points. Interesting that there are so many different ways to route this level (with 70 frame length difference), which end up having the similar score (within 10 points). lvl19_1127.mp4