Sergioz82 Posted May 18, 2022 Share Posted May 18, 2022 Hello, I'm working on my first game entirely in ASM and I'm using Compute's! Beginner's Guide to Assembly Language. It's nothing innovative, just your everyday Pacman clone, however I think I need to work first on something tried and tested by generations of programmers before dedicating myself to the games I have in mind. I've already set up a labyrinth, the ghosts and the Pacman which can also eat the pills, however I'm kinda stuck at making the sprites detect walls and act accordingly. I found the source code for Munch Man and it gave me some enlightenment but I can't figure out how the programmers implemented the detection. So my question is: how can I do it? My idea is: since I already have a routine to read the character under the sprite (for eating the pill) I could also use it to check a character ahead the one the sprite is on according to the direction.. however, even if I can't figure it out I've got the suspect that Munch Man uses something more efficient in terms of lines of code and the theory behind. Thanks in advance. PS: the sprites have a 2X magnification, in collision detection between Pacman and ghosts I already keep it into account (add 16 pixels for boundaries, I suppose I'll have to do the same with wall collision. 2 Quote Link to comment Share on other sites More sharing options...
+9640News Posted May 18, 2022 Share Posted May 18, 2022 I'm not saying this would be the most efficient, etc, but if you are in a graphics mode, read the graphics data at the point of interest in the direction of travel and test the color if the walls are of a different color from other items. 2 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted May 18, 2022 Share Posted May 18, 2022 Some ideas that I have used. Disclaimer: I do this in Forth but the ideas are the same for Assembly Language. Someone here will no doubt school me on things. To convert a pixel coordinate to a character coordinate you divide the pixel value in a register by 8. This is best done using a shift right instruction. * with pixel value in R1 we can divide by 8 like this * Each bit shift right divides by 2. So shifting 3 bits divides by 8 SRA R1,3 Conversely to convert a character coordinate to a pixel coordinate, multiply by 8 by using a shift left instruction * With a character coordinate in R2, multiply by 8 like this SLA R2,3 With this knowledge you can convert to the appropriate units and compare graphics coords. to pixels coords. --- You get the sprite's coordinates by reading the data from the sprite attribute table. IMPORTANT: This table is in VDP RAM so you have to read the bytes with VSBR and write bytes with VSBW My setup has the table at VDP address >300. Yours may be set to some other location. VDP register settings in your program startup code determine this. There are 4 bytes in the table for each sprite: col,row,char,color So to get the column location (in pixels) of sprite #0 read the byte at >300 (with BLWP @VSBR) Read the row location at >301 The ASCII character at >302 and the color at >303. To get the 4 byte location in the table, of any sprite, you can take the sprite# (option base 0) and multiply by 4 (just use SLA R?,2) and add the result to the base address of the sprite attribute table. Hope that helps and also I hope I didn't tell you things you already knew. 2 1 Quote Link to comment Share on other sites More sharing options...
LostCause Posted May 19, 2022 Share Posted May 19, 2022 You could set up a 16x12 array to map the screen coordinates and base collisions from the array map. 1 Quote Link to comment Share on other sites More sharing options...
Tursi Posted May 19, 2022 Share Posted May 19, 2022 (edited) Sprite to character collision detection is a pain in the butt. You do have an advantage on your side - you know that the characters are every 8 pixels. So if you check correctly on 8 pixel boundaries, you know you should be okay in-between them. You can simply read the joystick at 8 pixel boundaries for new motion, and continue moving between them. (Probably want to allow for instant reversal though). A technique I see a lot of titles used is to choose collision points for a sprite, and just check those. For instance, you could just check the center pixel on each side of the character. If the pixel is in a wall, nudge the character out of it. https://www.gamedeveloper.com/design/the-pac-man-dossier Pac Man appears to use this technique, while continuing the previous direction until reaching the 8 pixel boundary (though it's hard to be sure - there's a LOT more written about the ghosts than the player). This allows the 'cornering' effect and suggests that the game checks and remembers x and y movement separately. It seems to be pretty robust, at least with the defined mazes! Edited May 19, 2022 by Tursi 2 1 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted May 19, 2022 Share Posted May 19, 2022 (edited) 18 hours ago, Sergioz82 said: My idea is: since I already have a routine to read the character under the sprite (for eating the pill) I could also use it to check a character ahead the one the sprite is on according to the direction. That's what I would do, and it usually works very well as long as your walls fill out the characters. If you have corners with only a few pixels you want to skip those. So you need to arrange your characters to make it easy to know which numbers to check for. I don't think you need to worry about performance for this, since you only need to do it a few times every frame. But as mentioned, if you require 32K anyway, it's more efficient to check a map in CPU RAM/ROM than to check the VDP RAM. Edited May 19, 2022 by Asmusr 1 Quote Link to comment Share on other sites More sharing options...
Willsy Posted May 19, 2022 Share Posted May 19, 2022 I don't think I would read the screen at all. Why not have a simple array in memory which represents the directions a sprite can move in. There would be one byte per screen location (though since you only need four bits, you could pack two locations into a single byte). bit 0 = can move left bit 1 = can move right bit 2 = can move up bit 3 = can move down As the character moves eight pixels right (for example) you increase your array pointer by 1, read the array, and the value tells you which directions the character can move in. If the character is moving left, you decrease your array pointer by 1 and read. For moving up, decrease array pointer by 32, for down, increase array pointer by 32. Something like that. 4 1 Quote Link to comment Share on other sites More sharing options...
LostCause Posted May 19, 2022 Share Posted May 19, 2022 Why not just use 0 to represent where the sprite can move and 1 where the sprite can't. 2 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted May 19, 2022 Share Posted May 19, 2022 (edited) It sounds like you're trying to save memory, but most likely you will have a copy of the map in CPU RAM/ROM already, and I don't see why checking an alternative representation would be easier or faster? Also remember that a 16x16 sprite can partially cover up to 9 8x8 characters, so it's not always in one location, unless it can only change direction on 16 pixel boundaries. If you use the method to check characters in the direction you're moving, you need to check at least two points, e.g. top-left and bottom-left if you're moving left, or you could end up moving part of the sprite into a wall. Edited May 19, 2022 by Asmusr 3 1 Quote Link to comment Share on other sites More sharing options...
Sergioz82 Posted May 19, 2022 Author Share Posted May 19, 2022 21 hours ago, 9640News said: I'm not saying this would be the most efficient, etc, but if you are in a graphics mode, read the graphics data at the point of interest in the direction of travel and test the color if the walls are of a different color from other items. At the moment I'm not venturing into bitmap mode, however it's an interesting solution, I'll keep it in mind for the future. @TheBF I solved that part, however I keep forgetting that in ASM I can use register shifts so I used simple address pointers and increments to reach the various sprites but your solution seems better. @LostCause @Asmusr Yes, using an array would save me a lot of calls to VDP routines. For the moment I'm not aiming to save memory so, why not! @Tursi I really like your suggestion of checking the collision every 8 pixels. My idea instead was of doing it at each position increment and I already had doubts about aligning the sprite with the corridors (the player would have to make pixel-perfect turns). Your way will facilitate me a lot of things @Willsy This is another interesting suggestion Thank you very much to all! 6 Quote Link to comment Share on other sites More sharing options...
LostCause Posted May 21, 2022 Share Posted May 21, 2022 (edited) @Asmusr I started in the 80`s with a Commodore Vic-20 and Atari 800XL. I have only been using the Classic99 Emulator for a few Months now and Assembly on the TI for maybe a couple weeks. So, I had to give this some thought. After loading a VDP RAM Dump of Pacman in Magellan the only answer to your question I can come up with is simplicity. Pixel perfect collision on any system is ridiculously over complicated. Since Pacman moves in between the character grid checking any map in RAM seems like a lot of different characters to check collision against. The array does not need to be based on 8x8 or 16x16 it can be anything as long as the horizontal and vertical distances are a multiple of some constant. The Pacman sprite is actually - 11x11. Slicing up the screen dimensions to create the array and using known offsets to position the sprites no actual sprite collision needs to be performed. Just increment the X or Y index to the array after the sprite has moved that constant distance check if the next index in the direction contains either a 0 or 1. if it contains a zero the sprite can continue or otherwise stop. Edited May 21, 2022 by LostCause 2 Quote Link to comment Share on other sites More sharing options...
Sergioz82 Posted July 3, 2022 Author Share Posted July 3, 2022 Hello, the development is going on but I got stuck with an apparently simple task. Below it's the movement routine called with BLWP from the game loop. A quick explanation: JREAD is the joystick read routine which puts into LASTI the input when it's not zero (only when game starts pacman has zero direction and stands still) R5 and R6 contain the characters of pacman sprites (it's made of 2 sprites to give it some color) according to direction, the Jx labels do this: load new sprite pattern , load *R3 with the appropriate position increment (00FF,0100 etc). R9 sets the offset for collision detection that must happen 16 pixels ahead whan going right and down. MOVE does the temporary operation with offset for detecting the pattern of character in front of pacman. If it's not a wall then the routine will update the sprites attributes in VDP. My problem now is: how the hell do I tell it to change direction only each 16 pixels (sprites are 2x magnified)?I tried some solution: COC the position with 0F and allow direction change only when it's true, set up a counter that counts up to 0F and allow direction change only when it's over and so on but each solution messes up with the movement. Second question: with the current code, when the pacman is going let's say right and it's going through a horizontal corridor, if the player moves up the pacman stops, instead I'd like it to keep going in the original direction, ignoring the input. Can you guys help me? Thank you very much Quote TMPWP1 BSS 32 MOVPAC DATA TMPWP1 DATA ENTPT1 ENTPT1 LI R3,PACDIR MOV @PACYX+2,R5 MOV @BANYX+2,R6 CLR R9 BL @JREAD MOV @LASTI,R10 CI R10,0 JEQ NOMOVE J0 CI R10,SX JNE J1 MOV @DSX,*R3 LI R5,PSXA LI R6,BANSX JMP MOVE J1 CI R10,DX JNE J2 MOV @DDX,*R3 LI R9,>000F LI R5,PDXA LI R6,BANDX JMP MOVE J2 CI R10,SU JNE J3 MOV @DSU,*R3 LI R5,PSUA LI R6,BANSU JMP MOVE J3 CI R10,GIU JNE MOVE MOV @DGIU,*R3 LI R9,>0F00 LI R5,PGUA LI R6,BANGU MOVE MOV @PACYX,@TMPVAR AB *R3,@TMPVAR AB @1(R3),@TMPVAR+1 MOV @TMPVAR,R4 AB R9,@TMPVAR SWPB R9 AB R9,@TMPVAR+1 BLWP @RDCHAR MOV @TMPVAR,R9 CI R9,>1100 JLT NOMOVE MOV R4,@PACYX MOV R4,@BANYX MOVB R5,@PACYX+2 MOVB R6,@BANYX+2 LI R7,>0500 MOVB @PACYX+2,R6 *3 RIGHE PER CAMBIO CARATTERE XOR R6,R7 MOVB R7,@PACYX+2 LI R0,>0300 LI R1,PACYX LI R2,8 BLWP @VMBW NOMOVE RTWP Quote Link to comment Share on other sites More sharing options...
Asmusr Posted July 3, 2022 Share Posted July 3, 2022 1 hour ago, Sergioz82 said: My problem now is: how the hell do I tell it to change direction only each 16 pixels (sprites are 2x magnified)?I tried some solution: COC the position with 0F and allow direction change only when it's true, set up a counter that counts up to 0F and allow direction change only when it's over and so on but each solution messes up with the movement. For the first issue, maybe you need to use CZC instead of COC? For the second issue, maybe you don't want to change the direction variables until you know that the passage is free? It would help us to understand the issue if you comment each line of your source. 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted July 3, 2022 Share Posted July 3, 2022 2 hours ago, Sergioz82 said: Hello, the development is going on but I got stuck with an apparently simple task. Below it's the movement routine called with BLWP from the game loop. A quick explanation: JREAD is the joystick read routine which puts into LASTI the input when it's not zero (only when game starts pacman has zero direction and stands still) R5 and R6 contain the characters of pacman sprites (it's made of 2 sprites to give it some color) according to direction, the Jx labels do this: load new sprite pattern , load *R3 with the appropriate position increment (00FF,0100 etc). R9 sets the offset for collision detection that must happen 16 pixels ahead whan going right and down. MOVE does the temporary operation with offset for detecting the pattern of character in front of pacman. If it's not a wall then the routine will update the sprites attributes in VDP. My problem now is: how the hell do I tell it to change direction only each 16 pixels (sprites are 2x magnified)?I tried some solution: COC the position with 0F and allow direction change only when it's true, set up a counter that counts up to 0F and allow direction change only when it's over and so on but each solution messes up with the movement. Second question: with the current code, when the pacman is going let's say right and it's going through a horizontal corridor, if the player moves up the pacman stops, instead I'd like it to keep going in the original direction, ignoring the input. Can you guys help me? Thank you very much As @Asmusr indicated, “Comments, please.” Is it correct for me to presume that JREAD defines, via EQU, the constants (DX,SX,...) used in the “CI R10,...” instructions? An aside: This code, MOV @LASTI,R10 CI R10,0 <---unnecessary instruction JEQ NOMOVE does not need the CI instruction because the MOV will have already set the EQ status bit if the value copied to R10 was 0. ...lee 2 Quote Link to comment Share on other sites More sharing options...
Sergioz82 Posted July 3, 2022 Author Share Posted July 3, 2022 (edited) @Asmusr I'll try CZC. For the second question, I don't know how to implement this behavior: keep going and check collision forward, but if I change direction toward a wall check collision in the new direction then keep going to original direction. Maybe I could store the original direction before the R10 check for joystick and switch back to this value if the path is blocked? @Lee Stewart Yes indeed, SX,DX etc.. are defined with EQU. Please see the commented code below. Quote does not need the CI instruction because the MOV will have already set the EQ status bit if the value copied to R10 was 0. True! I keep forgetting that each operation alters the status register, I still think in terms of high level language, I just wanted to translate an IF instruction. Thank you for the tip! About the code, here's my comments: First four lines set up the worskpace and registers for BLWP (I use labels because I compile with Relative option, so I leave the memory allocation to the compiler, I don't know what address is associated to labels) Quote TMPWP1 BSS 32 MOVPAC DATA TMPWP1 DATA ENTPT1 ENTPT1 LI R3,PACDIR R3 points to word with pacman direction (the increment I need). MOV @PACYX+2,R5 2 lines: pre-load R5 and R6 with the character containing the actual pattern for representing the direction: face left, right, up and down. MOV @BANYX+2,R6 PACYX and BANYX points to each sprite's position in attribute list. +2 for pointing to the character. CLR R9 I get sure 16 pixels offset for collision detection is 0 by default BL @JREAD read joystick input. In the sub the value in LASTI is updated with the joystick position value only if such value is not zero MOV @LASTI,R10 move the value in R10 for immediate comparison CI R10,0 If input is zero skip the routine (when game starts pacman stands still, @LASTI start value is zero) JEQ NOMOVE J0 CI R10,SX SX,DX,SU,GIU (left,right etc..) are constants, EQU to joystick values I get from @KSCAN JNE J1 MOV @DSX,*R3 DSX,DDX,DSU,DGIU contains the increment (0001 for right, 00FF for left, 0100 for down and FF00 for up). LI R5,PSXA for main sprite load the "face left-open mouth" character (PSXA, PDXA,BANSX,BANDX etc.. defined with EQU) LI R6,BANSX for secondary sprite load the "face left" character JMP MOVE ok, go to position update part J1 CI R10,DX JNE J2 MOV @DDX,*R3 LI R9,>000F J1,J2,J3 do the same things in J0, however in J1 and J3 I load in R9 the 16 pixels offset for right and down collision detection LI R5,PDXA LI R6,BANDX JMP MOVE J2 CI R10,SU JNE J3 MOV @DSU,*R3 LI R5,PSUA LI R6,BANSU JMP MOVE J3 CI R10,GIU JNE MOVE MOV @DGIU,*R3 LI R9,>0F00 LI R5,PGUA LI R6,BANGU MOVE MOV @PACYX,@TMPVAR I copy the actual pacman position in a temporary variable for collision detection (characters, collision between sprites is managed in another routine) AB *R3,@TMPVAR *R3 is loaded with the increment, now I add Y value (yy00) AB @1(R3),@TMPVAR+1 add the X value (00xx) MOV @TMPVAR,R4 I store the updated position in R4 AB R9,@TMPVAR I add the potential Y offset, if zero nothing changes SWPB R9 AB R9,@TMPVAR+1 I add the potential X offset, if zero nothing changes BLWP @RDCHAR go to "read the character under the sprite" routine, for the moment I recycle TMPVAR, RDCHAR will get X and Y from it and then store in it the value of the detected character MOV @TMPVAR,R9 move the read value in register 9 for immediate comparison CI R9,>1100 JLT NOMOVE below 11 (pill character) there are the walls characters, so stop (this part will be expanded, will recognize energizers, bonus, replace H11 with H20 (space) when pacman eats the pill etc.. MOV R4,@PACYX 2 lines: ok I can move, copy the updated position to attributes of sprite 1 and 2 of pacman MOV R4,@BANYX MOVB R5,@PACYX+2 2 lines: update the sprites character according to the direction MOVB R6,@BANYX+2 LI R7,>0500 4 lines: with XOR I can swap each cycle the character of sprite 1 with open or close mouth MOVB @PACYX+2,R6 XOR R6,R7 MOVB R7,@PACYX+2 LI R0,>0300 4 lines: write in VDP the updated attributes for sprite 1 and 2. LI R1,PACYX LI R2,8 BLWP @VMBW NOMOVE RTWP Edited July 3, 2022 by Sergioz82 1 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted July 3, 2022 Share Posted July 3, 2022 For the first issue, would adding something like this at the top work? MOV @PACYX,R0 ; Get Y and X coordinates AI R0,>0100 ; Normalize Y LI R1,>0F0F ; Mask for checking position CZC R1,R0 ; Check that X and Y are multiples of 16 JNE MOVE ; Skip read joystick In addition, I guess you also need to save the direction (R9) between calls to MOVPAC. 1 Quote Link to comment Share on other sites More sharing options...
RXB Posted July 3, 2022 Share Posted July 3, 2022 On 5/18/2022 at 2:15 PM, TheBF said: Some ideas that I have used. Disclaimer: I do this in Forth but the ideas are the same for Assembly Language. Someone here will no doubt school me on things. To convert a pixel coordinate to a character coordinate you divide the pixel value in a register by 8. This is best done using a shift right instruction. * with pixel value in R1 we can divide by 8 like this * Each bit shift right divides by 2. So shifting 3 bits divides by 8 SRA R1,3 Conversely to convert a character coordinate to a pixel coordinate, multiply by 8 by using a shift left instruction * With a character coordinate in R2, multiply by 8 like this SLA R2,3 With this knowledge you can convert to the appropriate units and compare graphics coords. to pixels coords. --- You get the sprite's coordinates by reading the data from the sprite attribute table. IMPORTANT: This table is in VDP RAM so you have to read the bytes with VSBR and write bytes with VSBW My setup has the table at VDP address >300. Yours may be set to some other location. VDP register settings in your program startup code determine this. There are 4 bytes in the table for each sprite: col,row,char,color So to get the column location (in pixels) of sprite #0 read the byte at >300 (with BLWP @VSBR) Read the row location at >301 The ASCII character at >302 and the color at >303. To get the 4 byte location in the table, of any sprite, you can take the sprite# (option base 0) and multiply by 4 (just use SLA R?,2) and add the result to the base address of the sprite attribute table. Hope that helps and also I hope I didn't tell you things you already knew. RXB 2022E has CALL COLLIDE and Lee Stewart helped me write the ROM 3 for it. Here is the source if it helps: Spoiler ************************************************************ AORG >6000 TITL 'RXB ROM3' ************************************************************ * EQUATES BIAS EQU >6000 PAD EQU >8300 * TEMP PAD1 EQU >8301 * TEMP PAD2 EQU >8302 * VDP ADDRESS PAD3 EQU >8303 * TEMP PAD4 EQU >8304 * TEMP PAD5 EQU >8305 * TEMP PAD6 EQU >8306 * TEMP BUFFER FOR COINSP PAD8 EQU >8308 * SPRITE 1 PADA EQU >830A * SPRITE 2 BYTES EQU >830C * STRING LENGTH SREF EQU >831C * STRING POINTER FAC EQU >834A * RAM line buffer FAC1 EQU >834B * GCHAR buffer FAC4 EQU >834E * String Address FAC6 EQU >8350 * String Length ARG EQU >835C * ARGUMENT FOR ERRORS STATUS EQU >837C * GPL STATUS BYTE ISR EQU >83C4 * ISR INTERUPT HOOK GR0LB EQU >83E1 * GPLWS R0 LSB GR4LB EQU >83E9 * GPLWS R4 LSB VDPRD EQU >8800 * VDP Read Data address VDPWD EQU >8C00 * VDP Write Data address ************************************************************ * VDP EQUATES VBUFF EQU >03C0 * line buffer in VRAM ************************************************************ UNUSED DATA >0000,>0000,>0000,>0000 DATA >0000,>0000,>0000,>0000 ****************************************************************** * XML table number 7 for RXB ROM3 - must have * * it's origin at >6010 * ****************************************************************** * 0 1 2 3 4 5 6 DATA RROLL,LROLL,UROLL,DROLL,HCHAR,VCHAR,ASCHEX * 7 8 9 A B C D DATA HPUT,VPUT,CLEARP,>0000,>0000,>0000,>0000 * E F DATA ALPHA,CHRLDR ***************************************************************** * XML table number 8 for RXB ROM3 - must have * * it's origin at >6030 * ***************************************************************** * 0 1 2 3 4 5 6 7 DATA COLLSP,>0000,>0000,>0000,>0000,>0000,>0000,>0000 * 8 9 A B C D E F DATA >0000,>0000,>0000,CINIT,XISRON,XISROF,>0000,>0000 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Write VRAM address * Expects address in R0 * * BL here for writing data * VWADD ORI R0,>4000 * set to write VRAM data * * BL here for reading data * VWADDA MOVB @GR0LB,*R15 * write LSB of R0 to VDPWA MOVB R0,*R15 * write MSB of R0 to VDPWA ANDI R0,>3FFF * ensure R0 returned intact RT * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * The following utilities expect * R0 = VRAM address of row * R1 = RAM buffer address * * R2 and R10 will be destroyed * * Copy 1 row of 32 bytes from VDP (R0) to RAM (R1) * VRROW MOV R11,R10 * save return BL @VWADDA * write out VDP read address LI R2,32 * read 1 row LI R8,VDPRD * Register faster then address VRROW1 MOVB *R8,*R1+ * read next VDP byte to RAM MOVB *R8,*R1+ * read next VDP byte to RAM DECT R2 * dec count by 2 JNE VRROW1 * repeat if not done B *R10 * return to caller * * Copy 1 row of 32 bytes from RAM (R1) to VDP (R0) * VWROW MOV R11,R10 * save return BL @VWADD * write out VDP write address LI R2,32 * write one row LI R8,VDPWD * Register faster then address VWROW1 MOVB *R1+,*R8 * write next VDP byte from RAM MOVB *R1+,*R8 * write next VDP byte from RAM DECT R2 * dec count by 2 JNE VWROW1 * repeat if not done B *R10 * return to caller ********************************************************* * CALL ROLLRIGHT(repetion,...) * ********************************************************* RROLL MOV R11,R9 * save return address CLR R0 * set to screen start LI R3,24 * rows to roll * Write row to RAM buffer RROLLP LI R1,FAC+1 * RAM buffer+1 for roll-right positions BL @VRROW * copy row to RAM buffer 2 bytes at a time * Copy last column before first in RAM buffer MOVB @FAC+32,@FAC * copy roll-out byte to roll-in position * Copy rolled row back to screen (R0 still has correct location) LI R1,FAC * reset RAM buffer pointer BL @VWROW * copy rolled line * Process next row AI R0,32 * next row DEC R3 * dec row count JNE RROLLP * roll next row if not done B @PAGER * return to XB ********************************************************* * CALL ROLLLEFT(repetion,...) * ********************************************************* LROLL MOV R11,R9 * save return address CLR R0 * set to screen start LI R3,24 * rows to roll * Write row to RAM buffer LROLLP LI R1,FAC * RAM buffer+1 for roll-left positions BL @VRROW * copy row to RAM buffer 2 bytes at a time * Copy first column after last in RAM buffer MOVB @FAC,@FAC+32 * copy roll-out byte to roll-in position * Copy rolled row back to screen (R0 still has correct location) LI R1,FAC+1 * reset RAM buffer pointer BL @VWROW * copy rolled line 2 bytes at a time * Process next row AI R0,32 * next row DEC R3 * dec row count JNE LROLLP * roll next row if not done B @PAGER * return to XB ********************************************************* * CALL ROLLUP(repetion,...) * ********************************************************* UROLL MOV R11,R9 * save return address CLR R0 * set to screen start LI R3,23 * rows to roll (all but 1st) * Write first row to RAM buffer LI R1,FAC * set RAM buffer BL @VRROW * copy row to RAM buffer 2 bytes at a time * Copy RAM buffer to VRAM buffer LI R0,VBUFF * set VRAM dest to VBUFF LI R1,FAC * set RAM buffer BL @VWROW * copy row to VBUFF 2 bytes at a time * Start copy loop at 2nd row LI R0,32 * point to 2nd row * Write row to RAM buffer UROLLP LI R1,FAC * set RAM buffer BL @VRROW * copy row to RAM buffer 2 bytes at a time * Copy to previous row AI R0,-32 * back up 1 row LI R1,FAC * reset RAM buffer pointer BL @VWROW * copy to previous row 2 bytes at a time * Process next row AI R0,64 * next row DEC R3 * dec row count JNE UROLLP * roll next row if not done * Copy saved row to RAM LI R0,VBUFF * set VRAM source LI R1,FAC * set RAM buffer BL @VRROW * copy row to RAM buffer 2 bytes at a time * Copy saved row to last row LI R0,736 * point to last row LI R1,FAC * reset RAM buffer pointer BL @VWROW * copy to last row 2 bytes at a time B @PAGER * return to XB ********************************************************* * CALL ROLLDOWN(repetion,...) * ********************************************************* DROLL MOV R11,R9 * save return address LI R0,736 * set to last row LI R3,23 * rows to roll (all but last) * Write last row to RAM buffer LI R1,FAC * set RAM buffer BL @VRROW * copy row to RAM buffer 2 bytes at a time * Copy RAM buffer to VRAM buffer LI R0,VBUFF * set VRAM dest to VBUFF LI R1,FAC * set RAM buffer BL @VWROW * copy row to VBUFF 2 bytes at a time * Start copy loop at 2nd-to-last row LI R0,704 * point to row 22 * Write row to RAM buffer DROLLP LI R1,FAC * set RAM buffer BL @VRROW * copy row to RAM buffer 2 bytes at a time * Copy to next row AI R0,32 * down 1 row LI R1,FAC * reset RAM buffer pointer BL @VWROW * copy to next row 2 bytes at a time * Process next row AI R0,-64 * back up 2 rows DEC R3 * dec row count JNE DROLLP * roll next row if not done * Copy saved row to RAM LI R0,VBUFF * set VRAM source LI R1,FAC * set RAM buffer BL @VRROW * copy row to RAM buffer * * 2 bytes at a time * Copy saved row to first row CLR R0 * point to first row LI R1,FAC * reset RAM buffer pointer BL @VWROW * copy to first row 2 bytes at a time B @PAGER * return to caller *********************************************************** * CALL HCHAR(row,column,character#,repetition[,...]) * *********************************************************** * CALL HCHAR(row,column,character#,repetition) * R0 VDP ADDRESS = PAD2 * R1 CHARACTER = PAD * R3 COUNTER - FAC * HCHAR MOV R11,R9 * save return address LI R8,VDPWD * put VDPWD in R8 for faster loop MOV @PAD2,R0 * VRAM start address for HCHAR4 MOV @PAD,R1 * ASCII char code is in MSB AI R1,>6000 * Add screen offset (96) to char in MSB MOV @FAC,R3 * repetition to R3.. MOV R3,R7 * .. and to R4 for manipulation LI R5,768 * get screen end = 768 to a register.. MOV R5,R6 * ..and to R6 for screen size C R6,R7 * scrn_size > cnt, i.e., cnt OK? JGT HCHAR1 * yes; jump MOV R6,R7 * no; cnt = scrn_size HCHAR1 C R0,R5 * VRAM address outside screen? JHE HCHARX * error if so..just exit S R0,R5 * bytes to end of screen HCHAR2 MOV R7,R3 * put cnt in R3 for HCHAR4 JGT HCHAR3 * are we done? JMP HCHARX * yup; we're outta here! HCHAR3 S R5,R7 * no; do we wrap to screen start? JLT HCHAR4 * no MOV R5,R3 * yes, just go to screen end HCHAR4 BL @VWADD * write out VRAM write address LI R8,VDPWD * put VDPWD in R8 for faster loop HCHAR5 MOVB R1,*R8 * Write a byte to next VRAM location DEC R3 * decrement count JNE HCHAR5 * Not done, fill another CLR R0 * wrap for next round MOV R6,R5 * scrn_size to bytes-to-end-of-screen JMP HCHAR2 * see if more HCHARX B @PAGER * return to caller *********************************************************** * CALL VCHAR(row,column,character#,repetition[,...]) * *********************************************************** * CALL VCHAR(row,column,character#,repetition) * R0 VDP ADDRESS = PAD2 * R1 CHARACTER = PAD * R3 COUNTER = FAC VCHAR MOV R11,R9 * save return address MOV @PAD2,R0 * VDP ADDRESS MOV R0,R7 * Copy VDP ADDRESS VCHART CI R7,31 * VDP ADDRESS>=31 top? JLE VCHARD * column<=31 top found AI R7,-32 * VDP ADDRESS-32 JMP VCHART * Loop VCHARD CI R7,31 * column=31? JNE VCHARR * 0 to 30 CLR R7 * Reset column to 0 JMP VCHARZ VCHARR INC R7 * column+1 VCHARZ MOV @PAD,R1 * Character to display AI R1,BIAS * Screen offset 96 MOV @FAC,R3 * Repetition VCHAR1 BL @VWADD * write out VRAM write address LI R8,VDPWD * Register faster then @ MOVB R1,*R8 * write next VRAM byte from R1 CI R0,768 * End of screen? JEQ VCHARE * Yes CI R0,735 * next to last ROW? JLE VCHAR3 * Yes VCHARE MOV R7,R0 * VDP ADDRESS=COPY VDP ADDRESS INC R7 * column+1 CI R7,31 * Next row past last column? JLE VCHAR2 * No CLR R7 * Wrap Column back VCHAR2 DEC R3 * repetition-1 JNE VCHAR1 * No done yet JMP VCHAR4 * Exit VCHAR3 AI R0,32 * ROW+1 CI R0,768 * Off screen? JHE VCHARE * Yes reset DEC R3 * REPETITION-1 JNE VCHAR1 * No loop VCHAR4 B @PAGER * RETURN TO XB ********************************************************** * CALL HPUT(row,column,$variable,...) * * CALL HPUT(row,column,number-variable,...) * ********************************************************** * CALL HPUT(row,column,string or number) * R0 VDP SCREEN ADDRESS = PAD2 R5,R0 * R4 VDP STRING ADDRESS = FAC4 R4,R0 * R3 COUNTER = FAC6 R3 * HPUT MOV R11,R9 * save return address MOV @PAD2,R5 * VDP SCREEN ADDRESS MOV @FAC4,R4 * String address or number MOV @FAC6,R3 * Length LI R7,BIAS * Get Screen bias off set LI R1,VDPWD * Register faster then @ LI R8,VDPRD * Register faster then @ CI R3,0 * Length=0? JEQ HPUT2 * Yes HPUT0 MOV R4,R0 * Get String/number address BL @VWADDA * read out VDP address R4 MOVB *R8,R6 * Get $/# from R4 byte into R6 AB R7,R6 * Add bias MOV R0,R4 * Get new update into R4 INC R4 * STRING ADDRESS+1 MOV R5,R0 * Get SCREEN ADDRESS BL @VWADD * write out VDP write address R5 MOVB R6,*R1 * Put R6 onto screen address R0 MOV R0,R5 * Get new update into R5 INC R5 * SCREEN ADDRESS+1 CI R5,768 * Last row:col? JNE HPUT1 * No, so continue loop CLR R5 * Reset back to top row:col DEC R3 * count by -1 JNE HPUT0 * count=0? Restart at top row:col JMP HPUT2 * return to caller HPUT1 DEC R3 * count by -1 JNE HPUT0 * count=0? HPUT2 B @PAGER * return to caller ********************************************************** * CALL VPUT(row,column,$variable,...) * * CALL VPUT(row,column,number-variable,...) * ********************************************************** * CALL VPUT(row,column,string or number) * R0 VDP SCREEN ADDRESS = PAD2 R5,R0 * R4 VDP STRING ADDRESS = FAC4 R4,R0 * R3 COUNTER = FAC6 R3 * VPUT MOV R11,R9 * save return address MOV @PAD2,R5 * VDP ADDRESS MOV @FAC4,R4 * String address or number MOV @FAC6,R3 * Length LI R7,BIAS * Get Screen bias off set LI R1,VDPWD * Register faster then @ LI R8,VDPRD * Register faster then @ CI R3,0 * Length=0? JEQ VPUT2 * Yes VPUT0 MOV R4,R0 * Get String/number address BL @VWADDA * read out VDP address R4 MOVB *R8,R6 * Get $/# from R4 byte into R6 AB R7,R6 * Add bias MOV R0,R4 * Get new update into R4 INC R4 * STRING ADDRESS+1 MOV R5,R0 * Get SCREEN ADDRESS BL @VWADD * write out VDP write address R5 MOVB R6,*R1 * Put R6 onto screen address R0 MOV R0,R5 * Get new update into R5 CI R5,767 * OFF SCREEN? JEQ VPUT3 * Yes CI R5,735 * Last ROW? JGT VPUT4 * Yes AI R5,32 * ROW+1 VPUT1 DEC R3 * Length-1 JNE VPUT0 * No loop VPUT2 B @PAGER * return to XB VPUT3 CLR R5 * RESET TO TOP LEFT CHARACTER JMP VPUT1 * Always loop VPUT4 INC R5 * COL+1 S @PAD2,R5 * Original address-screen address JMP VPUT1 * Always loop ********************************************************** * CALL INVERSE(chr#,...) * * CALL INVERSE(ALL,...) * ********************************************************** * R0 TEMP VDP * R1 CHARACTER ADDRESS = FAC * R2 NUMBER CHAR COUNT = PAD * R3 ADDRESS OF R4 TO R7 INVERS MOV R11,R9 * save return address MOV @FAC,R1 * CHARACTER ADDRESS CI R1,0 * ALL flag? JNE INV1 * No single character defintion LI R1,>03F0 * Cursor first character LI R2,129 * Load number of characters JMP INV2 * Go do ALL INV1 LI R2,1 * Load 1 character * Get 4 bytes of character definition INV2 LI R3,>83E8 * BUFFER in R4 to R7 MOV R1,R0 * Copy VDP Char Address BL @VWADDA * read out VDP address LI R8,VDPRD * Register faster then address MOVB *R8,*R3+ * read next VDP byte to RAM MOVB *R8,*R3+ * read next VDP byte to RAM MOVB *R8,*R3+ * read next VDP byte to RAM MOVB *R8,*R3+ * read next VDP byte to RAM MOVB *R8,*R3+ * read next VDP byte to RAM MOVB *R8,*R3+ * read next VDP byte to RAM MOVB *R8,*R3+ * read next VDP byte to RAM MOVB *R8,*R3+ * read next VDP byte to RAM INV R4 * INVERT BITS INV R5 * INVERT BITS INV R6 * INVERT BITS INV R7 * INVERT BITS LI R3,>83E8 * BUFFER in R4 to R7 MOV R1,R0 * Copy VDP Char Address BL @VWADD * write out VDP address LI R8,VDPWD * Register faster then address MOVB *R3+,*R8 * write next VDP byte from RAM MOVB *R3+,*R8 * write next VDP byte from RAM MOVB *R3+,*R8 * write next VDP byte from RAM MOVB *R3+,*R8 * write next VDP byte from RAM MOVB *R3+,*R8 * write next VDP byte from RAM MOVB *R3+,*R8 * write next VDP byte from RAM MOVB *R3+,*R8 * write next VDP byte from RAM MOVB *R3+,*R8 * write next VDP byte from RAM AI R1,8 * Next Character Definition DEC R2 * Character counter -1 JNE INV2 * 0? No keep looping B @PAGER * return to XB ************************************************************* * CALL COLLIDE(#SPR,#SPR,TOLERANCE,DOTROW,DOTCOL) * ************************************************************* * PAD = SPRITE 1 RETURN=ROW * PAD2 = SPRITE 2 RETURN=COLUMN * FAC = TOLERANCE COLLSP MOV R11,R9 * save return address * LOOK FOR SPRITE COINCIDENCE COLL LI R8,PAD * PAD CLR R0 * ZERO OUT MOVB *R8+,R0 * Sprite #1 ROW in high byte CLR R4 * ZERO OUT MOVB *R8+,R4 * Sprite #1 COL in high byte CLR R1 * ZERO OUT MOVB *R8+,R1 * Sprite #2 ROW in high byte CLR R5 * ZERO OUT MOVB *R8+,R5 * Sprite #2 COL in high byte MOV @FAC,R7 * TOLERANCE SWPB R7 * Put into high byte CLR @PAD * zero out CLR @PAD2 * zero out *** CHECK FOR OFF SCREEN LI R6,>C000 * Off screen value C R0,R6 * To Sprite #1 ROW to high? JHE COLL * Yes defualt zero C R1,R6 * To Sprite #2 ROW to high? JHE COLL * Yes defualt zero *** Row comparison MOV R1,R8 S R0,R8 * Sprite #2 ROW-Sprite #1 ROW ABS R8 * No negative value C R8,R7 * Within tolerance? JGT COLL * No defualt zero *** Column comparison MOV R5,R8 S R4,R8 * Sprite #2 COL-Sprite #1 COL ABS R8 * No negative value C R8,R7 * Within tolerance? JGT COLLO * No defualt zero SWPB R0 * Sprite #1 ROW in low byte MOV R0,@PAD * Save Sprite #1 ROW to XB SWPB R4 * Sprite #1 COL in low byte MOV R4,@PAD2 * Save Sprite #1 COL to XB COLLO B @PAGER * return to XB *********************************************************** * CALL CLEARPRINT * *********************************************************** CLEARP MOV R11,R9 * save return address LI R0,2 * Screen address start COL 3 LI R1,>8000 * Space Character LI R3,24 * ROW counter LI R4,2 * COL copy LI R8,VDPWD * put VDPWD in R8 for faster loop CLEARL BL @VWADD * write out VRAM write address LI R2,28 * Count COL 28 CLEARR MOVB R1,*R8 * Write a byte to next VRAM location DEC R2 * COUNT-1 JNE CLEARR * No loop AI R4,32 * Start COL copy +32 MOV R4,R0 * Get new ROW:COL DEC R3 * ROW-1 JEQ COLLO * On zero done JMP CLEARL * LOOP forever *********************************************************** * RXB CALL INIT ASSEMBLY ROUTINE * CINIT MOV R11,R9 * save return address LI R0,>2000 * RAM destination address LI R1,ALCEND * ROM source address LI R2,>0274 * COUNT INITLP MOV *R1+,*R0+ * Write next RAM word 1 MOV *R1+,*R0+ * Write next RAM word 2 MOV *R1+,*R0+ * Write next RAM word 3 MOV *R1+,*R0+ * Write next RAM word 4 MOV *R1+,*R0+ * Write next RAM word 5 MOV *R1+,*R0+ * Write next RAM word 6 MOV *R1+,*R0+ * Write next RAM word 7 MOV *R1+,*R0+ * Write next RAM word 8 DEC R2 * COUNT-1 JNE INITLP * Repeat if not done MOV *R1+,*R0+ * Last word to load B @PAGER * DONE RETURN TO XB *********************************************************** ALCEND DATA >205A,>24F4,>4000,>AA55 DATA >2038,>2096,>2038,>217E DATA >2038,>21E2,>2038,>234C DATA >2038,>2432,>2038,>246E DATA >2038,>2484,>2038,>2490 DATA >2038,>249E,>2038,>24AA DATA >2038,>24B8,>2038,>2090 DATA >0000,>0000,>0000,>0000 DATA >0000,>0000,>0000,>0000 DATA >0000,>0000,>0000,>0000 DATA >0000,>0000,>0000,>0000 DATA >6520,>C060,>2004,>0281 DATA >4000,>130E,>C001,>0202 DATA >834A,>8CB0,>1606,>8CB0 DATA >1604,>8CB0,>1602,>C030 DATA >0450,>0221,>0008,>10EF DATA >0200,>2500,>C800,>8322 DATA >02E0,>83E0,>0460,>00CE DATA >C81D,>8322,>10F9,>C01D DATA >C06D,>0002,>06A0,>20DC DATA >C0C1,>0603,>0223,>8300 DATA >D0D3,>1361,>0983,>0643 DATA >1612,>C000,>165C,>C0C5 DATA >05C3,>06A0,>2406,>1653 DATA >05C3,>06A0,>23CA,>0204 DATA >834A,>0202,>0008,>DC74 DATA >0602,>15FD,>0380,>06A0 DATA >20F8,>10F5,>C041,>1347 DATA >0A81,>9060,>8312,>1143 DATA >0981,>C141,>0A35,>0225 DATA >0008,>A160,>8310,>045B DATA >C24B,>0643,>1634,>C0C5 DATA >06A0,>23CA,>C0C1,>06A0 DATA >2406,>112D,>06A0,>211C DATA >06A0,>23CA,>6004,>0A30 DATA >A040,>0459,>C28B,>0A51 DATA >09D1,>C201,>D120,>8343 DATA >0984,>1303,>0600,>1123 DATA >0580,>0206,>0001,>C0C5 DATA >0223,>0004,>06A0,>23CA DATA >C0C1,>0643,>05C3,>06A0 DATA >23CA,>0581,>6044,>3981 DATA >C186,>1611,>C187,>0608 DATA >15F5,>0606,>A184,>8180 DATA >150A,>05C3,>045A,>0200 DATA >0700,>0460,>2084,>0200 DATA >1C00,>0460,>2084,>0200 DATA >1400,>0460,>2084,>C01D DATA >C06D,>0002,>06A0,>20DC DATA >C0C1,>0603,>0223,>8300 DATA >D0D3,>0983,>160E,>C000 DATA >1622,>0202,>0008,>0204 DATA >834A,>C0C5,>06A0,>23CA DATA >CD01,>05C3,>0642,>15FA DATA >0380,>0643,>160F,>C000 DATA >1612,>C0C5,>05C3,>06A0 DATA >2406,>160B,>05C3,>06A0 DATA >23CA,>C101,>0201,>834A DATA >0460,>20CA,>06A0,>20F8 DATA >10F8,>0460,>2166,>0460 DATA >216E,>C81D,>2038,>C82D DATA >0002,>83E2,>C82D,>0004 DATA >2044,>02E0,>83E0,>C80B DATA >2040,>C020,>2044,>06A0 DATA >20DC,>C0C1,>0603,>0223 DATA >8300,>D0D3,>0983,>0603 DATA >1332,>0643,>164A,>C2A0 DATA >2038,>162D,>C0C5,>05C3 DATA >06A0,>2406,>9801,>2058 DATA >1620,>0206,>0008,>0204 DATA >834A,>C0C5,>06A0,>23CA DATA >CD01,>05C3,>0646,>15FA DATA >06A0,>22DA,>0225,>0004 DATA >C105,>C046,>06A0,>23E6 DATA >05C4,>D050,>0981,>06A0 DATA >23E6,>C2E0,>2040,>C820 DATA >203E,>830C,>02E0,>2038 DATA >0380,>0200,>0700,>C2E0 DATA >2040,>0460,>2084,>0200 DATA >1C00,>0460,>226E,>C08B DATA >0643,>16F3,>C0C5,>06A0 DATA >23CA,>C0C1,>06A0,>2406 DATA >1102,>0460,>226A,>C020 DATA >2038,>06A0,>211C,>6004 DATA >0A10,>A0C0,>06A0,>23CA DATA >0452,>06A0,>227E,>0206 DATA >834A,>CD83,>DDA0,>2058 DATA >DD84,>CD81,>C0C1,>1602 DATA >04D6,>1005,>0603,>06A0 DATA >2406,>0981,>C581,>C020 DATA >2044,>06A0,>22DA,>0460 DATA >225A,>C80B,>203A,>C805 DATA >203C,>C2E0,>601E,>069B DATA >C020,>2044,>C160,>203C DATA >D190,>0986,>C820,>830C DATA >203E,>C806,>830C,>C806 DATA >8350,>C2E0,>6012,>069B DATA >C020,>2044,>0206,>834A DATA >0204,>001C,>CD84,>DDA0 DATA >2058,>DD84,>C5A0,>831C DATA >C0A0,>830C,>1309,>C116 DATA >C0C0,>0583,>D073,>06A0 DATA >241A,>0584,>0602,>15FA DATA >C2E0,>6028,>069B,>C020 DATA >2044,>C160,>203C,>C2E0 DATA >203A,>045B,>C01D,>C06D DATA >0002,>06A0,>20DC,>C0C1 DATA >0603,>0223,>8300,>D0D3 DATA >0983,>0603,>1302,>0643 DATA >1623,>C000,>1628,>C02D DATA >0004,>C0C5,>05C3,>06A0 DATA >2406,>9801,>2058,>161D DATA >05C3,>06A0,>23CA,>C041 DATA >1307,>C181,>0601,>C0C1 DATA >06A0,>2406,>9050,>1A15 DATA >DC01,>1309,>C0C6,>0981 DATA >C141,>06A0,>2406,>DC01 DATA >0583,>0605,>15FA,>0380 DATA >06A0,>227E,>C02D,>0004 DATA >10E6,>0460,>2166,>0460 DATA >216E,>0200,>1300,>0460 DATA >2084,>06C3,>D803,>8C02 DATA >06C3,>D803,>8C02,>1000 DATA >D060,>8800,>06C1,>D060 DATA >8800,>06C1,>045B,>06C4 DATA >D804,>8C02,>06C4,>0264 DATA >4000,>D804,>8C02,>1000 DATA >D801,>8C00,>06C1,>D801 DATA >8C00,>06C1,>045B,>06C3 DATA >D803,>8C02,>06C3,>D803 DATA >8C02,>1000,>D060,>8800 DATA >045B,>06C4,>D804,>8C02 DATA >06C4,>0264,>4000,>D804 DATA >8C02,>1000,>D801,>8C00 DATA >045B,>C83E,>83E2,>02E0 DATA >83E0,>C80B,>204E,>C081 DATA >0281,>0040,>1B0A,>C0A1 DATA >6010,>0281,>0004,>1605 DATA >C0A2,>0002,>0692,>2466 DATA >1001,>0692,>02E0,>2038 DATA >C80B,>83F6,>0380,>0200 DATA >0B00,>0460,>2084,>02E0 DATA >83E0,>C80B,>204E,>06A0 DATA >000E,>02E0,>2038,>C80B DATA >83F6,>0380,>06A0,>24CA DATA >D82D,>0002,>8C00,>0380 DATA >06A0,>24CA,>D831,>8C00 DATA >0602,>16FC,>0380,>06A0 DATA >24D0,>DB60,>8800,>0002 DATA >0380,>06A0,>24D0,>DC60 DATA >8800,>0602,>16FC,>0380 DATA >C05D,>D82D,>0001,>8C02 DATA >0261,>8000,>D801,>8C02 DATA >0380,>0201,>4000,>1001 DATA >04C1,>C09D,>D820,>203D DATA >8C02,>E081,>D802,>8C02 DATA >C06D,>0002,>C0AD,>0004 DATA >045B ********************************************************** EAINIT MOV R11,R9 * save return address CLR R0 * ZERO OUT R0 LI R1,>2000 * Start address LI R2,8192 * Counter CLRINT MOV R0,*R1+ * CLEAR WORD DECT R2 * Counter-2 JNE CLRINT * ZERO? LI R0,LOW1 * FOUR WORDS LI R1,>2000 * Set up init BL @FOURWS * LOAD IT LI R0,LOW2 * FOUR WORDS LI R1,>2024 * Set up list BL @FOURWS * LOAD IT LI R0,LOW3 * Routines LI R1,>20FA * Set up routines LI R2,1404 * Counter SLOW3 MOV *R0+,*R1+ * LOAD IT DECT R2 * Counter-2 JNE SLOW3 * ZERO? LI R0,LOW4 * Name List LI R1,>3F38 * NAMES & Address LI R2,200 * Counter SLOW4 MOV *R0+,*R1+ * LOAD IT DECT R2 * Counter-2 JNE SLOW4 * ZERO? B @PAGER * return to XB ************************ FOURWS MOV R11,R10 MOV *R0+,*R1+ MOV *R0+,*R1+ MOV *R0+,*R1+ MOV *R0+,*R1+ B *R10 ********************************************************** * EDITOR ASSEMBLER LOWER 8K SUPPORT * Data for Initialization of * Memory Expansion *********************************** LOW1 DATA >A55A,>2128,>2398,>225A LOW2 DATA >A000,>FFD7,>2676,>3F38 LOW3 DATA >0064,>2000,>2EAA,>2094 DATA >21C4,>2094,>2196,>2094,>21DE,>2094,>21F4 DATA >2094,>2200,>2094,>220E,>2094,>221A,>2094,>2228 DATA >209A,>22B2,>20DA,>23BA,>C80B,>2030,>D060 DATA >8349,>2060,>20FC,>132A,>C020,>8350,>1311,>06A0 DATA >2646,>101E,>0281,>3F38,>1319,>C001,>0202 DATA >834A,>8CB0,>1611,>8CB0,>160F,>8CB0,>160D,>C810 DATA >2022,>02E0,>20BA,>C020,>2022,>1309,>0690 DATA >02E0,>83E0,>C2E0,>2030,>045B,>0221,>0008,>10E4 DATA >0200,>0F00,>D800,>8322,>02E0,>83E0,>0460 DATA >00CE,>5820,>20FC,>8349,>02E0,>2094,>0380,>C83E DATA >83E2,>02E0,>83E0,>C80B,>20AA,>C081,>0281 DATA >8000,>1B07,>09C1,>0A11,>0A42,>09B2,>A0A1,>0CFA DATA >C092,>0692,>02E0,>2094,>C80B,>83F6,>0380 DATA >D060,>8373,>0981,>C87E,>8304,>F820,>20FC,>8349 DATA >02E0,>83E0,>C2E0,>2030,>045B,>02E0,>83E0 DATA >C80B,>20AA,>06A0,>000E,>02E0,>2094,>C80B,>83F6 DATA >0380,>06A0,>223A,>D82D,>0002,>8C00,>0380 DATA >06A0,>223A,>D831,>8C00,>0602,>16FC,>0380,>06A0 DATA >2240,>DB60,>8800,>0002,>0380,>06A0,>2240 DATA >DC60,>8800,>0602,>16FC,>0380,>C05D,>D82D,>0001 DATA >8C02,>0261,>8000,>D801,>8C02,>0380,>0201 DATA >4000,>1001,>04C1,>C09D,>D820,>2099,>8C02,>E081 DATA >D802,>8C02,>C06D,>0002,>C0AD,>0004,>045B DATA >0204,>834A,>C014,>C184,>04F6,>04F6,>C140,>1323 DATA >0740,>0203,>0040,>04F6,>04D6,>0280,>0064 DATA >1A13,>0280,>2710,>1A08,>0583,>C040,>04C0,>3C20 DATA >20FA,>D920,>83E3,>0003,>0583,>C040,>04C0 DATA >3C20,>20FA,>D920,>83E3,>0002,>D920,>83E1,>0001 DATA >D520,>83E7,>0545,>1101,>0514,>045B,>C17E DATA >53E0,>20FC,>C020,>8356,>C240,>0229,>FFF8,>0420 DATA >2114,>D0C1,>0983,>0704,>0202,>208C,>0580 DATA >0584,>80C4,>1306,>0420,>2114,>DC81,>9801,>20FE DATA >16F6,>C104,>1352,>0284,>0007,>154F,>04E0 DATA >83D0,>C804,>8354,>C804,>2036,>0584,>A804,>8356 DATA >C820,>8356,>2038,>02E0,>83E0,>04C1,>020C DATA >0F00,>C30C,>1301,>1E00,>022C,>0100,>04E0,>83D0 DATA >028C,>2000,>1332,>C80C,>83D0,>1D00,>0202 DATA >4000,>9812,>20FF,>16EE,>A0A0,>20A4,>1003,>C0A0 DATA >83D2,>1D00,>C092,>13E6,>C802,>83D2,>05C2 DATA >C272,>D160,>8355,>1309,>9C85,>16F2,>0985,>0206 DATA >208C,>9CB6,>16ED,>0605,>16FC,>0581,>C801 DATA >203A,>C809,>2034,>C80C,>2032,>0699,>10E2,>1E00 DATA >02E0,>209A,>C009,>0420,>2114,>09D1,>1604 DATA >0380,>02E0,>209A,>04C1,>06C1,>D741,>F3E0,>20FC DATA >0380,>C80B,>2030,>02E0,>20BA,>0420,>2124 DATA >02E0,>83E0,>1303,>C2E0,>2030,>045B,>D820,>20BA DATA >8322,>0460,>00CE,>04E0,>2022,>53E0,>20FC DATA >C020,>8356,>0420,>2120,>0008,>1332,>0220,>FFF7 DATA >0201,>0200,>0420,>210C,>0580,>C800,>202E DATA >C1E0,>2024,>C147,>04CC,>06A0,>25E0,>0283,>0001 DATA >1624,>058C,>04C3,>1023,>0283,>0046,>161E DATA >04C2,>06A0,>262E,>0283,>003A,>16F7,>C020,>202E DATA >0600,>0201,>0100,>0420,>210C,>06A0,>25E0 DATA >C020,>2022,>1307,>06A0,>2646,>1005,>CB4E,>0016 DATA >C3A0,>2022,>0380,>D740,>F3E0,>20FC,>0380 DATA >06A0,>25C2,>04C4,>D123,>2662,>0974,>C808,>202C DATA >06A0,>2594,>0464,>23F8,>0580,>0240,>FFFE DATA >C120,>2024,>A100,>1808,>8804,>2026,>1B05,>C160 DATA >2024,>C804,>2024,>100A,>C120,>2028,>A100 DATA >8804,>202A,>140C,>C160,>2028,>C804,>2028,>C1C5 DATA >0209,>0008,>06A0,>262E,>0609,>16FC,>10B6 DATA >0200,>0800,>10CC,>A005,>C800,>2022,>10AF,>A800 DATA >202C,>13AC,>0200,>0B00,>10C2,>A005,>C1C0 DATA >10A6,>A005,>DDC0,>DDE0,>20DB,>10A1,>A005,>06A0 DATA >2566,>C000,>1316,>0226,>FFF8,>8106,>1B02 DATA >0514,>1096,>8594,>16F8,>89A4,>0002,>0002,>16F4 DATA >89A4,>0004,>0004,>16F0,>C0E6,>0006,>C250 DATA >C403,>C009,>16FC,>0224,>0008,>C804,>202A,>10EA DATA >A005,>06A0,>2566,>0226,>FFF8,>8106,>13E3 DATA >C296,>1501,>050A,>8294,>16F7,>89A4,>0002,>0002 DATA >16F3,>89A4,>0004,>0004,>16EF,>C296,>1516 DATA >C0E6,>0006,>C253,>C4C0,>C0C9,>16FC,>C246,>6244 DATA >C286,>022A,>0008,>C0C6,>0643,>064A,>C693 DATA >0649,>16FB,>0224,>0008,>C804,>202A,>10D9,>CB44 DATA >0002,>0200,>0C00,>0460,>2432,>0460,>2494 DATA >C28B,>0209,>0006,>C1A0,>202A,>0226,>FFF8,>C106 DATA >8806,>2028,>1AF3,>C806,>202A,>06A0,>262E DATA >DDA0,>20E1,>0609,>16FA,>C580,>0206,>4000,>045A DATA >C28B,>04C0,>C30C,>1308,>06A0,>262E,>D020 DATA >20E1,>06A0,>262E,>A003,>045A,>0209,>0004,>06A0 DATA >262E,>06A0,>25C2,>0A40,>A003,>0609,>16F8 DATA >045A,>0223,>FFD0,>0283,>000A,>1A05,>0223,>FFF9 DATA >0283,>0019,>1B01,>045B,>0200,>0A00,>0460 DATA >2432,>02E0,>83E0,>0200,>2032,>C330,>C270,>C830 DATA >8354,>C830,>8356,>C050,>1D00,>9820,>4000 DATA >20FF,>161D,>0699,>101B,>1E00,>02E0,>20DA,>C020 DATA >202E,>0201,>20DB,>0202,>0004,>0420,>2118 DATA >7000,>0950,>1610,>0982,>C001,>0201,>203C,>0420 DATA >2118,>04C8,>0602,>11D7,>D0F1,>0983,>A203 DATA >045B,>02E0,>20DA,>04C0,>06C0,>0460,>2432,>0201 DATA >3F40,>0221,>FFF8,>C011,>1105,>8060,>202A DATA >16F9,>05CB,>045B,>0200,>0D00,>045B,>2D52,>5163 DATA >6483,>8455,>045C,>5B5F,>5EF0,>F003,>F0F0 DATA >4700,>00C8,>3F38 LOW4 DATA >5554,>4C54,>4142,>2022,>5041,>4420,>2020,>8300 DATA >4750,>4C57,>5320,>83E0,>534F,>554E,>4420 DATA >8400,>5644,>5052,>4420,>8800,>5644,>5053,>5441 DATA >8802,>5644,>5057,>4420,>8C00,>5644,>5057 DATA >4120,>8C02,>5350,>4348,>5244,>9000,>5350,>4348 DATA >5754,>9400,>4752,>4D52,>4420,>9800,>4752 DATA >4D52,>4120,>9802,>4752,>4D57,>4420,>9C00,>4752 DATA >4D57,>4120,>9C02,>5343,>414E,>2020,>000E DATA >584D,>4C4C,>4E4B,>2104,>4B53,>4341,>4E20,>2108 DATA >5653,>4257,>2020,>210C,>564D,>4257,>2020 DATA >2110,>5653,>4252,>2020,>2114,>564D,>4252,>2020 DATA >2118,>5657,>5452,>2020,>211C,>4453,>524C DATA >4E4B,>2120,>4C4F,>4144,>4552,>2124,>4750,>4C4C DATA >4E4B,>2100 *********************************************************** * RXB Character set *********************************************************** CHRLDR MOV R11,R9 * save return address LI R0,>03F8 * VDP destination address BL @VWADD * write out VDP write address LI R1,CHARS * CHARACTER LIST LI R2,96 * COUNT LI R8,VDPWD * Register faster then address CHRLP MOVB *R1+,*R8 * write next VDP byte from ROM 1 MOVB *R1+,*R8 * write next VDP byte from ROM 2 MOVB *R1+,*R8 * write next VDP byte from ROM 3 MOVB *R1+,*R8 * write next VDP byte from ROM 4 MOVB *R1+,*R8 * write next VDP byte from ROM 5 MOVB *R1+,*R8 * write next VDP byte from ROM 6 MOVB *R1+,*R8 * write next VDP byte from ROM 7 MOVB *R1+,*R8 * write next VDP byte from ROM 8 DEC R2 * COUNT-1 JNE CHRLP * Repeat if not done B @PAGER * DONE ************************************************** CHARS BYTE >00,>00,>00,>00,>00,>00,>00,>00 * 31 BYTE >00,>00,>00,>00,>00,>00,>00,>00 * 32 BYTE >00,>10,>10,>10,>10,>00,>10,>00 * ! 33 BYTE >00,>28,>28,>28,>00,>00,>00,>00 * " 34 BYTE >00,>28,>7C,>28,>28,>7C,>28,>00 * # 35 BYTE >00,>38,>54,>30,>18,>54,>38,>00 * $ 36 BYTE >00,>44,>4C,>18,>30,>64,>44,>00 * % 37 BYTE >00,>20,>50,>20,>54,>48,>34,>00 * & 38 BYTE >00,>08,>10,>20,>00,>00,>00,>00 * ' 39 BYTE >00,>08,>10,>10,>10,>10,>08,>00 * ( 40 BYTE >00,>20,>10,>10,>10,>10,>20,>00 * ) 41 BYTE >00,>00,>28,>10,>7C,>10,>28,>00 * * 42 BYTE >00,>10,>10,>7C,>10,>10,>00,>00 * + 43 BYTE >00,>00,>00,>00,>00,>30,>10,>20 * , 44 BYTE >00,>00,>00,>7C,>00,>00,>00,>00 * - 45 BYTE >00,>00,>00,>00,>00,>30,>30,>00 * . 46 BYTE >00,>04,>08,>10,>20,>40,>00,>00 * / 47 BYTE >00,>3C,>4C,>54,>64,>44,>38,>00 * 0 48 BYTE >00,>10,>30,>10,>10,>10,>38,>00 * 1 49 BYTE >00,>38,>44,>08,>10,>20,>7C,>00 * 2 50 BYTE >00,>38,>44,>18,>04,>44,>38,>00 * 3 51 BYTE >00,>08,>18,>28,>48,>7C,>08,>00 * 4 52 BYTE >00,>78,>40,>78,>04,>44,>38,>00 * 5 53 BYTE >00,>38,>40,>78,>44,>44,>38,>00 * 6 54 BYTE >00,>7C,>04,>08,>10,>20,>20,>00 * 7 55 BYTE >00,>38,>44,>38,>44,>44,>38,>00 * 8 56 BYTE >00,>38,>44,>44,>3C,>04,>78,>00 * 9 57 BYTE >00,>00,>30,>30,>00,>30,>30,>00 * : 58 BYTE >00,>00,>30,>30,>00,>30,>10,>20 * ; 59 BYTE >00,>00,>10,>20,>40,>20,>10,>00 * < 60 BYTE >00,>00,>00,>7C,>00,>7C,>00,>00 * = 61 BYTE >00,>00,>10,>08,>04,>08,>10,>00 * > 62 BYTE >00,>38,>44,>08,>10,>00,>10,>00 * ? 63 BYTE >00,>38,>44,>54,>58,>40,>3C,>00 * @ 64 BYTE >00,>38,>44,>44,>7C,>44,>44,>00 * A 65 BYTE >00,>78,>24,>38,>24,>24,>78,>00 * B 66 BYTE >00,>38,>44,>40,>40,>44,>38,>00 * C 67 BYTE >00,>78,>24,>24,>24,>24,>78,>00 * D 68 BYTE >00,>7C,>40,>78,>40,>40,>7C,>00 * E 69 BYTE >00,>7C,>40,>78,>40,>40,>40,>00 * F 70 BYTE >00,>38,>44,>40,>4C,>44,>38,>00 * G 71 BYTE >00,>44,>44,>7C,>44,>44,>44,>00 * H 72 BYTE >00,>38,>10,>10,>10,>10,>38,>00 * I 73 BYTE >00,>04,>04,>04,>04,>44,>38,>00 * J 74 BYTE >00,>44,>48,>50,>70,>48,>44,>00 * K 75 BYTE >00,>40,>40,>40,>40,>40,>7C,>00 * L 76 BYTE >00,>44,>6C,>54,>44,>44,>44,>00 * M 77 BYTE >00,>44,>64,>54,>54,>4C,>44,>00 * N 78 BYTE >00,>38,>44,>44,>44,>44,>38,>00 * O 79 BYTE >00,>78,>44,>44,>78,>40,>40,>00 * P 80 BYTE >00,>38,>44,>44,>54,>4C,>3C,>00 * Q 81 BYTE >00,>78,>44,>44,>78,>48,>44,>00 * R 82 BYTE >00,>38,>44,>30,>08,>44,>38,>00 * S 83 BYTE >00,>7C,>10,>10,>10,>10,>10,>00 * T 84 BYTE >00,>44,>44,>44,>44,>44,>38,>00 * U 85 BYTE >00,>44,>44,>44,>44,>28,>10,>00 * V 86 BYTE >00,>44,>44,>44,>54,>54,>28,>00 * W 87 BYTE >00,>44,>28,>10,>10,>28,>44,>00 * X 88 BYTE >00,>44,>44,>28,>10,>10,>10,>00 * Y 89 BYTE >00,>7C,>08,>10,>20,>40,>7C,>00 * Z 90 BYTE >00,>38,>20,>20,>20,>20,>38,>00 * [ 91 BYTE >00,>00,>40,>20,>10,>08,>04,>00 * \ 92 BYTE >00,>38,>08,>08,>08,>08,>38,>00 * ] 93 BYTE >00,>10,>38,>54,>10,>10,>10,>00 * ^ 94 BYTE >00,>00,>00,>00,>00,>00,>7C,>00 * _ 95 BYTE >00,>20,>10,>08,>00,>00,>00,>00 * ` 96 BYTE >00,>00,>00,>38,>48,>48,>3C,>00 * a 97 BYTE >00,>20,>20,>38,>24,>24,>38,>00 * b 98 BYTE >00,>00,>00,>1C,>20,>20,>1C,>00 * c 99 BYTE >00,>04,>04,>1C,>24,>24,>1C,>00 * d 100 BYTE >00,>00,>00,>1C,>28,>30,>1C,>00 * e 101 BYTE >00,>0C,>10,>38,>10,>10,>10,>00 * f 102 BYTE >00,>00,>00,>1C,>24,>1C,>04,>38 * g 103 BYTE >00,>20,>20,>38,>24,>24,>24,>00 * h 104 BYTE >00,>10,>00,>30,>10,>10,>38,>00 * i 105 BYTE >00,>08,>00,>08,>08,>08,>48,>30 * j 106 BYTE >00,>20,>20,>24,>38,>28,>24,>00 * k 107 BYTE >00,>30,>10,>10,>10,>10,>38,>00 * l 108 BYTE >00,>00,>00,>78,>54,>54,>54,>00 * m 109 BYTE >00,>00,>00,>38,>24,>24,>24,>00 * n 110 BYTE >00,>00,>00,>18,>24,>24,>18,>00 * o 111 BYTE >00,>00,>00,>38,>24,>38,>20,>20 * p 112 BYTE >00,>00,>00,>1C,>24,>1C,>04,>04 * q 113 BYTE >00,>00,>00,>28,>34,>20,>20,>00 * r 114 BYTE >00,>00,>00,>1C,>30,>0C,>38,>00 * s 115 BYTE >00,>10,>10,>38,>10,>10,>0C,>00 * t 116 BYTE >00,>00,>00,>24,>24,>24,>1C,>00 * u 117 BYTE >00,>00,>00,>44,>28,>28,>10,>00 * v 118 BYTE >00,>00,>00,>44,>54,>54,>28,>00 * w 119 BYTE >00,>00,>00,>24,>18,>18,>24,>00 * x 120 BYTE >00,>00,>00,>24,>24,>1C,>04,>38 * y 121 BYTE >00,>00,>00,>3C,>08,>10,>3C,>00 * z 122 BYTE >00,>0C,>10,>10,>20,>10,>10,>0C * { 123 BYTE >00,>10,>10,>10,>00,>10,>10,>10 * | 124 BYTE >00,>60,>10,>10,>08,>10,>10,>60 * } 125 BYTE >00,>00,>20,>54,>08,>00,>00,>00 * ~ 126 ********************************************************** * CALL HEX($variable,variable,...) * * CALL HEX(variable,$variable,...) * * CALL HEX(">####",variable,...) * ********************************************************** * HEX VDP to RAM (String to Address) LES version * R0 TEMP ASC TO HEX * R1 HEX ADDRESS = FAC * R2 STRING = PAD * R3 COUNTER = R3 ASCHEX MOV R11,R9 * save return address CLR R1 * clear result reg LI R2,PAD * assume 4-bytes in PAD-PAD3 LI R3,4 * load counter HEX01 CLR R0 * zero out work reg MOVB *R2+,R0 * Get ASC byte SWPB R0 * get byte to LSB * ASC CHECK VALUE CI R0,103 * g ? JHE ERROR * ERROR BAD ARGUMENT CI R0,97 * a ? JHE HEX02 * Valid CI R0,71 * G ? JHE ERROR * ERROR BAD ARGUMENT CI R0,65 * A ? JHE HEX02 * Valid CI R0,58 * : ? JHE ERROR * ERROR BAD ARGUMENT CI R0,47 * / ? JLE ERROR * ERROR BAD ARGUMENT * Convert ASC to value HEX02 AI R0,>FFD0 * correct for 0-9 in LSB CI R0,>000A * LSB < 10? JLT HEX03 * we're good AI R0,>FFF9 * correct LSB for A-F * Add digit and shift if not done HEX03 A R0,R1 * add hex digit to result reg LSB DEC R3 * decrement counter JEQ HEX04 * return if done SLA R1,4 * shift hex digit left 1 nybble JMP HEX01 * get another hex digit HEX04 MOV R1,@FAC * get result to FAC for CIF B @PAGER * return to XB ERROR LI R1,>994A * ERROR CODE FLAG NERROR MOV R1,@ARG * LOAD ERROR CODE FLAG B @PAGER * return to XB *********************************************************** * CALL ALPHALOCK(numeric-variable) * *********************************************************** ALPHA MOV R11,R9 * save return address MOV R12,R8 * save R12 value for later CLR R12 * ZERO OUT R12 SBZ 21 * PUT ALPHA LOCK STROBE SRC R12,14 * WAIT TB 7 * ALPHA LOCK DOWN? SBO 21 * RESET ALPHA LOCK STROBE JEQ ALPHAF * RETURN ALPHA LOCK OFF LI R1,>994A * ALPHA LOCK ON ALPHAO MOV R8,R12 * Restore R12 MOV R1,@FAC * Save value to FAC B @PAGER * return to XB ALPHAF CLR R1 * ZERO OUT FLAG JMP ALPHAO * ALPHA LOCK OFF *********************************************************** * CALL ISRON(variable) * *********************************************************** XISRON MOV R11,R9 * save return address MOV @FAC,@ISR * Put FAC into ISR Interupt hook JMP NEXIT * exit *********************************************************** * CALL ISROFF(variable) * *********************************************************** XISROF MOV R11,R9 * save return address MOV @ISR,@ISR * Compare if new ISR HOOK JEQ NHOOK * No MOV @ISR,@FAC * Put ISR Hook into FAC NHOOK CLR @ISR * Clear ISR Hook NEXIT CLR @STATUS * Clear GPL stuse byte B @PAGER * return to XB ************************ SPRLP MOVB R1,*R8 * Write a byte to next VRAM location DEC R2 * COUNT-1 JNE SPRLP * LOOP RT *********************************************************** AORG >7FFA PAGER CLR @>6000 * RESTORE PAGE ONE B *R9 * return to caller *********************************************************** END Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted July 3, 2022 Share Posted July 3, 2022 3 hours ago, Sergioz82 said: . . . each operation alters the status register . . . Actually, some operations have no effect on the status register. For example, you can do multiple conditional jumps on the same status result because none of the jump instructions changes the status register. The same is true of the branch instructions. ...lee 2 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted July 3, 2022 Share Posted July 3, 2022 The one that I found about late was the CLR instruction. You can do a MOV and set the flags. Then CLR another register, Rx, and NOT affect the flags. Then you can JEQ or JNE to set Rx based on the previous MOV. Much handier when you have to return true/false in a language. 1 Quote Link to comment Share on other sites More sharing options...
Sergioz82 Posted July 4, 2022 Author Share Posted July 4, 2022 20 hours ago, Asmusr said: For the first issue, would adding something like this at the top work? MOV @PACYX,R0 ; Get Y and X coordinates AI R0,>0100 ; Normalize Y LI R1,>0F0F ; Mask for checking position CZC R1,R0 ; Check that X and Y are multiples of 16 JNE MOVE ; Skip read joystick In addition, I guess you also need to save the direction (R9) between calls to MOVPAC. I added your code between JREAD and MOV @LASTI,R10. I like Senior Falcon's idea of keeping the command memorized while during the step-16 movement so it will turn on its own. Problem is, now pacman moves diagonally and then stops I have no idea why it happens, it seems I'm not altering other registers except R0.. Another problem is that in a scenario of stop for collision detection + ignore input for step-16 the Pacman gets stuck 1 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted July 4, 2022 Share Posted July 4, 2022 18 hours ago, TheBF said: You can do a MOV and set the flags. Then CLR another register, Rx, and NOT affect the flags. Then you can JEQ or JNE to set Rx based on the previous MOV. Much handier when you have to return true/false in a language. That's true. The opponent of CLR, SETO doesn't change any status bits either. Not too surprising, since the result here is obvious, as you set the destination to contain a pre-defined value. Thus you know already if it's zero or not, for example. Slightly more surprising is that SWPB doesn't modify and status bits. Instructions like LWPI, LIMI and STWP together with SBZ and SBO are also executed without affecting any status bits. 2 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted July 4, 2022 Share Posted July 4, 2022 3 hours ago, Sergioz82 said: I added your code between JREAD and MOV @LASTI,R10. I like Senior Falcon's idea of keeping the command memorized while during the step-16 movement so it will turn on its own. Problem is, now pacman moves diagonally and then stops I have no idea why it happens, it seems I'm not altering other registers except R0.. Another problem is that in a scenario of stop for collision detection + ignore input for step-16 the Pacman gets stuck If it moves diagonally it sounds like you need to clear the movement in X when it finds a free passage in Y and vice versa. Have you to inspect what happens using a debugger? 2 Quote Link to comment Share on other sites More sharing options...
Sergioz82 Posted July 5, 2022 Author Share Posted July 5, 2022 (edited) 14 hours ago, Asmusr said: If it moves diagonally it sounds like you need to clear the movement in X when it finds a free passage in Y and vice versa. Have you to inspect what happens using a debugger? It's a strange thing.. I used the debugger but since I don't manage the addresses It's quite intricate to set the appropriate breakpoints. I start the game by moving right: pacman goes in that direction but also increments its y (If I move to the left it moves one pixel left then it gets stuck). Can't go up or down because there are walls. For what it seems, it's like if moving @pacyx to R0 and manipulating R0 also alters the content of pacyx itself (I double checked I didn't forget @) because with debugger I can see row byte in VDP >0300 is incremented as if AI R0,>0100 affected the actual position. In facts, if I comment your lines the Pacman moves correctly. I have no idea, I only use R0 for CZC and for VMBW.. now I'm going to check the sequence of jumps, maybe implementing the 16 pixels step makes it skip some register valorization. Edited July 5, 2022 by Sergioz82 1 Quote Link to comment Share on other sites More sharing options...
Sergioz82 Posted July 5, 2022 Author Share Posted July 5, 2022 @Asmusr Never mind, found the problem: I decided to not use indirect addressing for R3, therefore when I update position in TMPVAR I had to use SWPB for MOVB R3,@TMPVAR+1 but I forgo to restore the original order before updating @PACYX, so with CZC it used a wrong @PACYX.. Easier done than said ? Now I have to avoid pacman getting stuck when in front of a wall with CZC EQ=0 4 Quote Link to comment Share on other sites More sharing options...
Sergioz82 Posted July 7, 2022 Author Share Posted July 7, 2022 (edited) Finally it works Well, kinda works, there are still a couple of issues (I need a 2 characters read for 2x magnification because as you can see in some turns pacman gets inside walls and same problem for eating some pills) to solve but it's taking shape. Here's the updated movement routine: Quote TMPWP1 BSS 32 MOVPAC DATA TMPWP1 DATA ENTPT1 ENTPT1 BL @INIT loading pacman sprite attributes (+offset) in registers is now a subroutine BL @JREAD read keyboard CB @HALT,@HFF is pacman in front of a wall? HALT byte is FF when true JEQ JL yes, check new direction MOV @PACYX,R0 pacman is moving, HALT is 00. Next 3 lines check a step 8 before accepting input AI R0,>0100 LI R1,>0707 CZC R1,R0 JNE MOVE sprite position is not multiple of 8. Ignore input, keep going JL MOV @LASTI,R10 JEQ NOMOVE J0 CI R10,SX JNE J1 MOV @DSX,R3 LI R5,PSXA LI R6,BANSX CLR R9 JMP MOVE J1 CI R10,DX JNE J2 MOV @DDX,R3 LI R9,>000F LI R5,PDXA LI R6,BANDX JMP MOVE J2 CI R10,SU JNE J3 MOV @DSU,R3 LI R5,PSUA LI R6,BANSU CLR R9 JMP MOVE J3 CI R10,GIU JNE MOVE MOV @DGIU,R3 LI R9,>0F00 LI R5,PGUA LI R6,BANGU MOVE MOV @PACYX,@TMPYX use a temporary variant to check if in next pixel there isn't a wall AB R3,@TMPYX SWPB R3 AB R3,@TMPYX+1 SWPB R3 MOV @TMPYX,R4 one pixel increment according to direction in R3. Store in R4 MOV R9,@OFFSF save the new offset AB R9,@TMPYX SWPB R9 AB R9,@TMPYX+1 BLWP @RDCHAR offset +16 for right and down sprite on character detection is added to TEMPYX (used inside RDCHAR) MOV @RCHVAL,R9 move in r9 the value of the character in front of pacman CI R9,>1100 is not a wall or a pill? JGT C2 then go on CI R9,>1100 is it a wall? JLT C1 then go check if pacman must stop or maintain the direction MOV @RCHPOS,R0 if read value is 11 (pill) then use character position returned from RDCHAR to VSBW a space character LI R1,>2000 BLWP @VSBW JMP C2 C1 C @PACDIR,R3 at TMPYX there's a wall. Did pacman changed direction? JEQ C3 no, then stop BL @INIT yes, restore the original position and repeat the move procedure JMP MOVE C3 SETO @HALT set HALT flag CLR @LASTI set joystick input to zero JMP NOMOVE exit movpac C2 CLR @HALT pacman can move, set HALT flag to zero MOV R3,@PACDIR update pacman sprite attributes and copy them to VDP MOV R4,@PACYX MOV R4,@BANYX MOVB R6,@BANYX+2 LI R7,>0500 3 lines for animation (open-close mouth) XOR R5,R7 MOVB R7,@PACYX+2 LI R0,>0300 LI R1,PACYX LI R2,8 BLWP @VMBW NOMOVE RTWP INIT MOV @PACDIR,R3 MOV @PACYX+2,R5 MOV @BANYX+2,R6 MOV @OFFSF,R9 read the saved offset B *R11 Spacm.AVI Edited July 7, 2022 by Sergioz82 4 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.