kensu Posted February 26, 2023 Share Posted February 26, 2023 (edited) I incorporated a modified verison of the DLI routine from this Action! program into a character set redefiniton program I'd previously written, which draws six rows of Breakout-style bricks. This actually works, but it only changes the color of rows 3-6, no matter how I modify it, I can't get the first two rows to change. Those lines do have DLI enabled, but the Playfield Color 1 (0) is only changed starting with the third line. DEFINE RTI="$40", PHA="$48", PLA="$68", TXA="$8A", TAX="$AA", TYA="$98", TAY="$A8", JMP="$4C" BYTE CHBAS = $2F4, PMBASE = $D407, RAMTOP=$6A, NMIEN=$D40E, COLP0=$D016,WSYNC=$D40A, COUNT=[0] CARD SDLSTL=560, VDSLST=512 BYTE ARRAY COLTABLE(0) = [$42 $74 $C4 $18 $00 $0E] BYTE ARRAY DLIST PROC DLINT() BYTE DUM [PHA TXA PHA TYA PHA] DUM=COLTABLE(COUNT) WSYNC=1 COLP0=DUM COUNT ==+ 1 IF COUNT=6 THEN COUNT=0 FI [PLA TAY PLA TAX PLA RTI] PROC INIT_GR() GRAPHICS(1) SETCOLOR(0,2,10) SETCOLOR(1,5,12) SETCOLOR(2,0,0) RETURN PROC DLSETUP() BYTE I INIT_GR() NMIEN=$40 DLIST=SDLSTL VDSLST=DLINT FOR I = 6 TO 11 DO DLIST(I)=134 OD NMIEN=$C0 RETURN PROC CHANGE_CHARSET() BYTE ARRAY NC0 = [255 128 128 128 128 128 128 255 255 1 1 1 1 1 1 255 ] CARD MEMTOP MEMTOP = RAMTOP - 8 MEMTOP = MEMTOP * 256 ZERO(MEMTOP,512) MOVEBLOCK(MEMTOP,57344,512) MOVEBLOCK(MEMTOP+8,NC0,16) CHBAS = MEMTOP/256 RETURN PROC MAIN() CARD SAVMSC=$58 BYTE I CHANGE_CHARSET() DLSETUP() FOR I = 0 to 120 STEP 2 DO POKE(SAVMSC+I,1) POKE(SAVMSC+I+1,2) OD DO OD RETURN (for some reason I can't edit the code portion, Change_Charset() and DLsetp() are in the wrong order in the main procedure) A couple of additional questions for Action! experts. Why is count set to [0] instead of 0? I'm beginning to understand that anything in brackets is not actually an array, but some sort of machine code instruction, but I'm not clear on why it's done this way (if you remove the brackets there's a different result.) Also, why is Coltable dimensionalzed with a size of 0? This is the only example I've seen where an inline array declaration dimensionalizes the array, much less saying it's empty when it has a size of 6. Edited February 26, 2023 by kensu Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted February 26, 2023 Share Posted February 26, 2023 A DLI to change colours has to be on the line before the change is required so a line with a DLI active is called, you set everything, do a WSYNC which waits for that line to complete, then starts your code to change the colours Quote Link to comment Share on other sites More sharing options...
kensu Posted February 26, 2023 Author Share Posted February 26, 2023 Hmm, the Graphics 1 (for BASIC and Action!) display list is: 112 112 112 70 128 157 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 adr 0 1 2 3 4 5 6 7 8 9 1011121314151617181920 Bacially the first 6 of those 6s are turned into 134 (6 with bit 7 set). So if I wanted it to start on the first line, I would want to change offset 5, but that's actually the high component of the address of the beginning of the screen buffer. So what do I do in this case? Also, if it starts on offset 6, which would be the first line of the screen, why are the first two lines the original color, instead of just the first line? As I recall, aren't there two mode lines per row? Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted February 27, 2023 Share Posted February 27, 2023 (edited) If you want the first line to change, you set the DLI on the 3rd "8 blank lines", so change the above to 112 112 240 70 128 157 etc.... you can also set a DLI on the LMS instruction, change the 70 to 198 so in your example, the numbers would be 112 112 240 198 128 157 86 86 86 86 6 6 6 6 6 etc.... DLI HERE ^ ^ ^ ^ ^ ^ that would give you a colour change for the first 6 lines. This is from the Hardware Manual, it shows all possibilities. Edited February 27, 2023 by TGB1718 1 Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted February 27, 2023 Share Posted February 27, 2023 (edited) I don't have ACTION, but wrote a small assembler routine to simulate what your trying to do, I'm switching COLBK just to see the colours, changed the table a little just to add colours to each line and then turn the screen black, so an extra DLI at the end. As you changing character colours, you don't need to do this. Here's the actual display list in memory Edited February 27, 2023 by TGB1718 Quote Link to comment Share on other sites More sharing options...
E474 Posted February 27, 2023 Share Posted February 27, 2023 I'm not an ACTION hacker, so it's not clear how to do this, but a display list can't cross a 1K boundary without a JMP instruction (IIRC), so you need to make sure it avoids a 1K boundary, or takes this into account. Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted February 27, 2023 Share Posted February 27, 2023 21 minutes ago, E474 said: I'm not an ACTION hacker, so it's not clear how to do this, but a display list can't cross a 1K boundary without a JMP instruction (IIRC), so you need to make sure it avoids a 1K boundary, or takes this into account. From the code, it looks like Action is using the OS to open the screen, so the display list is located in a good position and not crossing a 1K boundary, I think the issue is as I have described, a DLI on the last blank line and on the LMS instruction followed by 4 more "normal" lines with DLI set. 16 hours ago, kensu said: Hmm, the Graphics 1 (for BASIC and Action!) display list is: 112 112 112 70 128 157 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 i.e. display list is at $9D60 just in front of the screen which is at $9D80 Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted February 27, 2023 Share Posted February 27, 2023 Just for the fun of it, I made a few minor changes to swap character sets and set the colours as you are doing, here's the result. Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted February 27, 2023 Share Posted February 27, 2023 Ok, so I just learnt some Action Here's your fixed code:- Highlighted bit is all you need to change, not sure if you meant to have $00 as the 5th byte in your colour table as it will be black so you can't see it, unless your background is some other colour. DEFINE RTI="$40", PHA="$48", PLA="$68", TXA="$8A", TAX="$AA", TYA="$98", TAY="$A8", JMP="$4C" BYTE CHBAS = $2F4, PMBASE = $D407, RAMTOP=$6A, NMIEN=$D40E, COLP0=$D016,WSYNC=$D40A, COUNT=[0] CARD SDLSTL=560, VDSLST=512 BYTE ARRAY COLTABLE(0) = [$42 $74 $C4 $18 $00 $0E] BYTE ARRAY DLIST PROC DLINT() BYTE DUM [PHA TXA PHA TYA PHA] DUM=COLTABLE(COUNT) WSYNC=1 COLP0=DUM COUNT ==+ 1 IF COUNT=6 THEN COUNT=0 FI [PLA TAY PLA TAX PLA RTI] PROC INIT_GR() GRAPHICS(1) SETCOLOR(0,2,10) SETCOLOR(1,5,12) SETCOLOR(2,0,0) RETURN PROC DLSETUP() BYTE I INIT_GR() NMIEN=$40 DLIST=SDLSTL VDSLST=DLINT DLIST(2)=240 DLIST(3)=198 FOR I = 6 TO 9 DO DLIST(I)=134 OD NMIEN=$C0 RETURN PROC CHANGE_CHARSET() BYTE ARRAY NC0 = [255 128 128 128 128 128 128 255 255 1 1 1 1 1 1 255 ] CARD MEMTOP MEMTOP = RAMTOP - 8 MEMTOP = MEMTOP * 256 ZERO(MEMTOP,512) MOVEBLOCK(MEMTOP,57344,512) MOVEBLOCK(MEMTOP+8,NC0,16) CHBAS = MEMTOP/256 RETURN PROC MAIN() CARD SAVMSC=$58 BYTE I CHANGE_CHARSET() DLSETUP() FOR I = 0 TO 120 STEP 2 DO POKE(SAVMSC+I,1) POKE(SAVMSC+I+1,2) OD DO OD RETURN 1 1 Quote Link to comment Share on other sites More sharing options...
danwinslow Posted February 27, 2023 Share Posted February 27, 2023 (edited) 23 hours ago, kensu said: Why is count set to [0] As far as I can see, it shouldn't be. It should be set to just 0. The code uses it as a variable, but count[0] sets up an array. Not sure about Action! but in some languages you would be incrementing the array pointer by doing things like count=count+1. that would be bad. Remove the brackets is my advice. Edited February 27, 2023 by danwinslow Quote Link to comment Share on other sites More sharing options...
E474 Posted February 27, 2023 Share Posted February 27, 2023 3 hours ago, TGB1718 said: From the code, it looks like Action is using the OS to open the screen, so the display list is located in a good position and not crossing a 1K boundary, I think the issue is as I have described, a DLI on the last blank line and on the LMS instruction followed by 4 more "normal" lines with DLI set. i.e. display list is at $9D60 just in front of the screen which is at $9D80 Hi @TGB1718, Thanks, my bad for not reading the code properly; I got bitten by this bug (crossing a 1K boundary) a couple of weeks ago, so am probably over-sensitive to it. Quote Link to comment Share on other sites More sharing options...
kensu Posted February 27, 2023 Author Share Posted February 27, 2023 7 hours ago, danwinslow said: As far as I can see, it shouldn't be. It should be set to just 0. The code uses it as a variable, but count[0] sets up an array. Not sure about Action! but in some languages you would be incrementing the array pointer by doing things like count=count+1. that would be bad. Remove the brackets is my advice. That's very strange, if you remove the brackets it will loop through the colors in a different order (3,4,5,0,1,2). I think what's happening here is similar to what happens when you use something like "Byte x=$FF" where it sets up the variable as a direct reference to that spot in memory without having to do any dereferncing with the ^. In this case it seems to be using Action's memory allocation routine to find a free spot in memory and then assigning that variable as a reference to it. I still don't understand why it has a different result from just a normal assignment.... I wish we could ask the author of the original example, but this code is from 1984, if they were still around I doubt they'd remember why they did it that way. Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted February 28, 2023 Share Posted February 28, 2023 11 hours ago, kensu said: Remove the brackets is my advice. No, the manual says it's not creating an array, it's just initialising count to 0 that's the syntax it uses. Arrays use the ARRAY keyword:- Quote Link to comment Share on other sites More sharing options...
danwinslow Posted February 28, 2023 Share Posted February 28, 2023 (edited) Oh brackets vs. parens, yeah. Brackets are apparently initializer lists. So what does a non bracketed number do? Does INT COUNT=0 do anything different? For that matter, what would INT COUNT=[0,1,2,3] do ? Its not an array declaration. Edited February 28, 2023 by danwinslow Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted February 28, 2023 Share Posted February 28, 2023 It would appear that INT COUNT=0 sets COUNT (or any other variable) to be a pointer the that memory location. I just tried setting COUNT=88, then printed COUNT and the result was 40000 i.e. the screen address likewise setting COUNT to 560 have the result 39968 which would equate to the display list location. So without the [] it creates a pointer to a memory location. doing INT COUNT[0,1,2,3] generates a compile error Quote Link to comment Share on other sites More sharing options...
danwinslow Posted February 28, 2023 Share Posted February 28, 2023 Interesting. So when he removed the brackets he got a pointer to location 0? Surprised he didn't crash. Thanks for the explanation. Quote Link to comment Share on other sites More sharing options...
kensu Posted March 1, 2023 Author Share Posted March 1, 2023 11 hours ago, danwinslow said: Interesting. So when he removed the brackets he got a pointer to location 0? Surprised he didn't crash. Thanks for the explanation. It might be Zero Page address zero, which I think is clear for variable use. I wonder why it always has a starting value of 3? This also explains a lot of weird issues I've been running into with Action!, and why I couldn't really understand how dereferncing of variables worked. Action appears to be much closer to the metal than I thought, and just using my knowledge of C wasn't enough. Quote Link to comment Share on other sites More sharing options...
Alfred Posted March 1, 2023 Share Posted March 1, 2023 Count = 0 sets the address of Count to absolute address zero, which would also be zero page zero. Since this location is unused after powerup, no crash occurs. However it means the value of Count is undetermined, it will be whatever was last deposited at 0. So if it was say 57, the DUM assignment on the first pass becomes DUM = COLTABLE(57) which probably is junk as far as colour goes. It will keep on being junk until it loops back around to zero. Action! does not initialize variables unless you tell it to do so. The fact that it always seems to be three is strictly coincidence, whatever is using $00 just happens to always leave a 3 in it when it is done. Count = [0] says to initialize Count to zero, thus the loop operates correctly. Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted March 1, 2023 Share Posted March 1, 2023 @kensu we have digressed a bit, but all good fun, however you haven't said if the solution to your original question has provided a fix for your issue. Quote Link to comment Share on other sites More sharing options...
kensu Posted March 2, 2023 Author Share Posted March 2, 2023 16 hours ago, TGB1718 said: @kensu we have digressed a bit, but all good fun, however you haven't said if the solution to your original question has provided a fix for your issue. Yep, worked like a charm, I pinned a Thanks trophy to the message with the code that fixed it. Thanks! Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted March 4, 2023 Share Posted March 4, 2023 Have to thank @kensu for raising this topic, I had never heard of action bitd, so had a look at it because of this post, been playing just to see what it's like and although it's a bit "quirky" it's certainly producing fast code, although a quick look shows it really need an optimiser, it seems full of this sort of code:- 22C3 JMP 22C6 4C C622 22C6 STA 22C2 8D C222 299D JMP 29A0 4C A029 29A0 LDA 299B AD 9B29 29C2 JMP 29C5 4C C529 29C5 LDA #00 A900 I gave it a try using player/missile graphics example from De-Re Atari but put a movement routine in a VB overall quite impressed so far. One little criticism, having to define a procedure/function in your code before you call it, if you define it somewhere after the call to it, it errors during the compile, so you have to move it. PMGVBI1.ACT Quote Link to comment Share on other sites More sharing options...
Alfred Posted March 4, 2023 Share Posted March 4, 2023 1 hour ago, TGB1718 said: Have to thank @kensu for raising this topic, I had never heard of action bitd, so had a look at it because of this post, been playing just to see what it's like and although it's a bit "quirky" it's certainly producing fast code, although a quick look shows it really need an optimiser, it seems full of this sort of code:- 22C3 JMP 22C6 4C C622 22C6 STA 22C2 8D C222 299D JMP 29A0 4C A029 29A0 LDA 299B AD 9B29 29C2 JMP 29C5 4C C529 29C5 LDA #00 A900 I gave it a try using player/missile graphics example from De-Re Atari but put a movement routine in a VB overall quite impressed so far. One little criticism, having to define a procedure/function in your code before you call it, if you define it somewhere after the call to it, it errors during the compile, so you have to move it. PMGVBI1.ACT 1.38 kB · 0 downloads What you are seeing is a deliberate design decision. It allows for the redirection of procedures. For example, the manual shows how to replace the Error function. So in code you see: Proc Error(byte rc) which becomes as you see Error JMP Erro2 Error2 STA rc so you define your own proc Proc MyError(byte rc) but now you can do Error = MyError which changes Error thusly Error JMP MyError Error2 STA rc so any call to Error is redirected to your MyError procedure. The way to turn this off is to use the '*' keyword: Proc Error=*(byte rc) and now it becomes Error code starts here Note that using * also disables the storing of any passed parameters, so you must do it yourself: Proc MyError=*(byte rc) MyError STA rc Action! is a 1 pass compiler so things must be declared before they are used. By using the assignment of functions ability though you can call functions before they are defined. Proc Dummy() RETURN Proc Dosomething() Dummy() RETURN Proc TheRealProc() dowork return Proc Main Dummy=TheRealProc return I think this is all talked about in the Action! runtime manual. Also see the articles at Ken Squiggle's page https://ksquiggle.neocities.org/action/online 3 Quote Link to comment Share on other sites More sharing options...
TGB1718 Posted March 4, 2023 Share Posted March 4, 2023 @Alfred thanks, that's some light reading for me tomorrow Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.