intvnut Posted March 31, 2015 Share Posted March 31, 2015 Ok, again untested... I thought I'd try to write up a more optimized 16x16 multiply, using registers in place of the stack. It was a big win, weighing in at 302 cycles (315 counting the cost of CALL), at the expense of trashing most of the registers. Saving/restoring the registers on the stack would add 80 cycles, which still makes it noticeably cheaper. So, a worst case of 395 cycles puts the crossover point at a multiplier of 18 for 16-bit x 16-bit multiply... . ; Quarter Square Multiplication ; Assembly code by Joe Zbiciak, 2015 ; Released to public domain. QSQR8_TBL PROC DECLE $0000, $0000, $0001, $0002, $0004, $0006, $0009, $000C DECLE $0010, $0014, $0019, $001E, $0024, $002A, $0031, $0038 DECLE $0040, $0048, $0051, $005A, $0064, $006E, $0079, $0084 DECLE $0090, $009C, $00A9, $00B6, $00C4, $00D2, $00E1, $00F0 DECLE $0100, $0110, $0121, $0132, $0144, $0156, $0169, $017C DECLE $0190, $01A4, $01B9, $01CE, $01E4, $01FA, $0211, $0228 DECLE $0240, $0258, $0271, $028A, $02A4, $02BE, $02D9, $02F4 DECLE $0310, $032C, $0349, $0366, $0384, $03A2, $03C1, $03E0 DECLE $0400, $0420, $0441, $0462, $0484, $04A6, $04C9, $04EC DECLE $0510, $0534, $0559, $057E, $05A4, $05CA, $05F1, $0618 DECLE $0640, $0668, $0691, $06BA, $06E4, $070E, $0739, $0764 DECLE $0790, $07BC, $07E9, $0816, $0844, $0872, $08A1, $08D0 DECLE $0900, $0930, $0961, $0992, $09C4, $09F6, $0A29, $0A5C DECLE $0A90, $0AC4, $0AF9, $0B2E, $0B64, $0B9A, $0BD1, $0C08 DECLE $0C40, $0C78, $0CB1, $0CEA, $0D24, $0D5E, $0D99, $0DD4 DECLE $0E10, $0E4C, $0E89, $0EC6, $0F04, $0F42, $0F81, $0FC0 DECLE $1000, $1040, $1081, $10C2, $1104, $1146, $1189, $11CC DECLE $1210, $1254, $1299, $12DE, $1324, $136A, $13B1, $13F8 DECLE $1440, $1488, $14D1, $151A, $1564, $15AE, $15F9, $1644 DECLE $1690, $16DC, $1729, $1776, $17C4, $1812, $1861, $18B0 DECLE $1900, $1950, $19A1, $19F2, $1A44, $1A96, $1AE9, $1B3C DECLE $1B90, $1BE4, $1C39, $1C8E, $1CE4, $1D3A, $1D91, $1DE8 DECLE $1E40, $1E98, $1EF1, $1F4A, $1FA4, $1FFE, $2059, $20B4 DECLE $2110, $216C, $21C9, $2226, $2284, $22E2, $2341, $23A0 DECLE $2400, $2460, $24C1, $2522, $2584, $25E6, $2649, $26AC DECLE $2710, $2774, $27D9, $283E, $28A4, $290A, $2971, $29D8 DECLE $2A40, $2AA8, $2B11, $2B7A, $2BE4, $2C4E, $2CB9, $2D24 DECLE $2D90, $2DFC, $2E69, $2ED6, $2F44, $2FB2, $3021, $3090 DECLE $3100, $3170, $31E1, $3252, $32C4, $3336, $33A9, $341C DECLE $3490, $3504, $3579, $35EE, $3664, $36DA, $3751, $37C8 DECLE $3840, $38B8, $3931, $39AA, $3A24, $3A9E, $3B19, $3B94 DECLE $3C10, $3C8C, $3D09, $3D86, $3E04, $3E82, $3F01, $3F80 DECLE $4000, $4080, $4101, $4182, $4204, $4286, $4309, $438C DECLE $4410, $4494, $4519, $459E, $4624, $46AA, $4731, $47B8 DECLE $4840, $48C8, $4951, $49DA, $4A64, $4AEE, $4B79, $4C04 DECLE $4C90, $4D1C, $4DA9, $4E36, $4EC4, $4F52, $4FE1, $5070 DECLE $5100, $5190, $5221, $52B2, $5344, $53D6, $5469, $54FC DECLE $5590, $5624, $56B9, $574E, $57E4, $587A, $5911, $59A8 DECLE $5A40, $5AD8, $5B71, $5C0A, $5CA4, $5D3E, $5DD9, $5E74 DECLE $5F10, $5FAC, $6049, $60E6, $6184, $6222, $62C1, $6360 DECLE $6400, $64A0, $6541, $65E2, $6684, $6726, $67C9, $686C DECLE $6910, $69B4, $6A59, $6AFE, $6BA4, $6C4A, $6CF1, $6D98 DECLE $6E40, $6EE8, $6F91, $703A, $70E4, $718E, $7239, $72E4 DECLE $7390, $743C, $74E9, $7596, $7644, $76F2, $77A1, $7850 DECLE $7900, $79B0, $7A61, $7B12, $7BC4, $7C76, $7D29, $7DDC DECLE $7E90, $7F44, $7FF9, $80AE, $8164, $821A, $82D1, $8388 DECLE $8440, $84F8, $85B1, $866A, $8724, $87DE, $8899, $8954 DECLE $8A10, $8ACC, $8B89, $8C46, $8D04, $8DC2, $8E81, $8F40 DECLE $9000, $90C0, $9181, $9242, $9304, $93C6, $9489, $954C DECLE $9610, $96D4, $9799, $985E, $9924, $99EA, $9AB1, $9B78 DECLE $9C40, $9D08, $9DD1, $9E9A, $9F64, $A02E, $A0F9, $A1C4 DECLE $A290, $A35C, $A429, $A4F6, $A5C4, $A692, $A761, $A830 DECLE $A900, $A9D0, $AAA1, $AB72, $AC44, $AD16, $ADE9, $AEBC DECLE $AF90, $B064, $B139, $B20E, $B2E4, $B3BA, $B491, $B568 DECLE $B640, $B718, $B7F1, $B8CA, $B9A4, $BA7E, $BB59, $BC34 DECLE $BD10, $BDEC, $BEC9, $BFA6, $C084, $C162, $C241, $C320 DECLE $C400, $C4E0, $C5C1, $C6A2, $C784, $C866, $C949, $CA2C DECLE $CB10, $CBF4, $CCD9, $CDBE, $CEA4, $CF8A, $D071, $D158 DECLE $D240, $D328, $D411, $D4FA, $D5E4, $D6CE, $D7B9, $D8A4 DECLE $D990, $DA7C, $DB69, $DC56, $DD44, $DE32, $DF21, $E010 DECLE $E100, $E1F0, $E2E1, $E3D2, $E4C4, $E5B6, $E6A9, $E79C DECLE $E890, $E984, $EA79, $EB6E, $EC64, $ED5A, $EE51, $EF48 DECLE $F040, $F138, $F231, $F32A, $F424, $F51E, $F619, $F714 DECLE $F810, $F90C, $FA09, $FB06, $FC04, $FD02, $FE01 ENDP ; R2 = R0 * R1, where R0 and R1 are unsigned 8-bit values ; Destroys R1 qs_mpy8 PROC MOVR R0, R2 ; 6 ADDR R1, R2 ; 6 a + b SUBR R0, R1 ; 6 a - b BPL @@ok ; 7 NEGR R1 ; 6 @@ok: ADDI #QSQR8_TBL, R2 ; 8 ADDI #QSQR8_TBL, R1 ; 8 MVI@ R2, R2 ; 8 SUB@ R1, R2 ; 8 JR R5 ; 7 ;---- ; 70 ENDP ; R1 = R0 * R1, where R0 and R1 are 16-bit values ; destroys R0, R2, R3, R4, R5 qs_mpy16 PROC PSHR R5 ; 9 MVII #QSQR8_TBL, R5 ; 8 MOVR R0, R2 ; 6 R2 is orig 16-bit a MOVR R1, R3 ; 6 R3 is orig 16-bit b ; lo * lo ANDI #$FF, R0 ; 8 R0 is lo(a) MOVR R0, R4 ; 6 R4 is lo(a) ANDI #$FF, R1 ; 8 R1 is lo(b) PSHR R1 ; 9 save lo(b) ADDR R1, R4 ; 6 R4 = lo(a) + lo(b) SUBR R0, R1 ; 6 R1 = lo(a) - lo(b) BPL @@pos_ll ; 7 NEGR R1 ; 6 @@pos_ll: ADDR R5, R4 ; 6 R4 = &qstbl[lo(a)+lo(b)] ADDR R5, R1 ; 6 R1 = &qstbl[lo(a)-lo(b)] MVI@ R4, R4 ; 8 R4 = qstbl[lo(a)+lo(b)] SUB@ R1, R4 ; 8 R4 = lo(a)*lo(b) ;---- ; 113 ; lo * hi SWAP R3 ; 6 ANDI #$FF, R3 ; 8 R3 = hi(b) MOVR R0, R1 ; 6 R0 = R1 = lo(a) ADDR R3, R1 ; 6 R1 = hi(b) + lo(a) SUBR R0, R3 ; 6 R3 = hi(b) - lo(a) BPL @@pos_lh ; 7 NEGR R3 ; 6 @@pos_lh: ADDR R5, R1 ; 6 R1 = &qstbl[hi(b)+lo(a)] ADDR R5, R3 ; 6 R3 = &qstbl[hi(b)-lo(a)] MVI@ R1, R1 ; 8 R1 = qstbl[hi(b)-lo(a)] SUB@ R3, R1 ; 8 R1 = lo(a)*hi(b) ;---- ; 73 ; 113 (carried forward) ;---- ; 186 ; hi * lo SWAP R2 ; 6 ANDI #$FF, R2 ; 8 R2 = hi(a) PULR R3 ; 11 R3 = lo(b) MOVR R3, R4 ; 6 R4 = lo(b) ADDR R2, R3 ; 6 R3 = hi(a) + lo(b) SUBR R4, R2 ; 6 R2 = hi(a) - lo(b) BPL @@pos_hl ; 7 NEGR R2 ; 6 @@pos_hl: ADDR R5, R3 ; 6 R3 = &qstbl[hi(a)+lo(b)] ADDR R5, R2 ; 6 R2 = &qstbl[hi(a)-lo(b)] ADD@ R3, R1 ; 8 \_ R1 = lo(a)*hi(b) + hi(a)*lo(b) SUB@ R3, R1 ; 8 / ;---- ; 84 ; 186 (carried forward) ;---- ; 270 SWAP R1 ; 6 ANDI #$FF00, R1 ; 8 ADDR R4, R1 ; 6 PULR PC ; 12 ;---- ; 32 ; 270 (carried forward) ;---- ; 302 ENDP . That's making "library function for var*var multiply" seem even more attractive for IntyBASIC, if you ask me. Now someone just needs to test this code... writing's cheap, testing is a bit more costly. ;) qsqr2.asm 1 Quote Link to comment Share on other sites More sharing options...
intvnut Posted March 31, 2015 Share Posted March 31, 2015 Now someone just needs to test this code... writing's cheap, testing is a bit more costly. ;) I still haven't tested it, but I did spot an error while rereading it over morning coffee. . @@pos_hl: ADDR R5, R3 ; 6 R3 = &qstbl[hi(a)+lo(b)] ADDR R5, R2 ; 6 R2 = &qstbl[hi(a)-lo(b)] ADD@ R3, R1 ; 8 \_ R1 = lo(a)*hi(b) + hi(a)*lo(b) SUB@ R3, R1 ; 8 / . The SUB@ should be SUB@ R2, R1. Oops. qsqr2.asm 1 Quote Link to comment Share on other sites More sharing options...
intvnut Posted April 1, 2015 Share Posted April 1, 2015 I still haven't tested it, but I did spot an error while rereading it over morning coffee. . @@pos_hl: ADDR R5, R3 ; 6 R3 = &qstbl[hi(a)+lo(b)] ADDR R5, R2 ; 6 R2 = &qstbl[hi(a)-lo(b)] ADD@ R3, R1 ; 8 \_ R1 = lo(a)*hi(b) + hi(a)*lo(b) SUB@ R3, R1 ; 8 / . The SUB@ should be SUB@ R2, R1. Oops. I spent about 20 minutes writing up a quick test harness this evening and found one other bug. I was clobbering R4 here: . MOVR R3, R4 ; 6 R4 = lo(b) ADDR R2, R3 ; 6 R3 = hi(a) + lo(b) SUBR R4, R2 ; 6 R2 = hi(a) - lo(b) . I changed R4 to R0 and ran it through over 30,000,000 random test vectors through qs_mpy16. (Turning off rate control in jzIntv and minimizing the window allowed it to run around 270x real time on my system.) It looks quite solid now. Attached is the final version. I'll go ahead and post this gem to another thread. Maybe others can improve on it further. qsqr2.asm 1 Quote Link to comment Share on other sites More sharing options...
freewheel Posted April 1, 2015 Share Posted April 1, 2015 (edited) IntyBASIC "feature": you cannot put comments on the same line as ASM statements. I nipped this from Joe's code in the Desert Bus thread (I usually don't worry about atomicity in simple games like this, but what the heck, thought I'd try it): ASM DIS ' disable interrupts for atomic access to "FRAME" ticks = ticks + FRAME - prev_frame prev_frame = FRAME ASM EIS ' re-enable interrupts Those comments ended up throwing errors. I guess IntyBASIC takes the entire line after ASM and dumps it into the .asm without looking for comments. Also, question: is there a way to do a soft-reset of the console? Basically mimicking what hitting the reset switch does? If so, what does this do with a multicart inserted? Edited April 1, 2015 by freeweed Quote Link to comment Share on other sites More sharing options...
intvnut Posted April 1, 2015 Share Posted April 1, 2015 (edited) IntyBASIC "feature": you cannot put comments on the same line as ASM statements. I nipped this from Joe's code in the Desert Bus thread (I usually don't worry about atomicity in simple games like this, but what the heck, thought I'd try it): ASM DIS ' disable interrupts for atomic access to "FRAME" ticks = ticks + FRAME - prev_frame prev_frame = FRAME ASM EIS ' re-enable interrupts Those comments ended up throwing errors. I guess IntyBASIC takes the entire line after ASM and dumps it into the .asm without looking for comments. Also, question: is there a way to do a soft-reset of the console? Basically mimicking what hitting the reset switch does? If so, what does this do with a multicart inserted? I wonder if replacing the ' with ; will make the comments on the ASM lines work. I'm at work and can't try it. Semicolon is the comment delimiter in assembly. On soft reset: A jump to location $1000 will restart the EXEC. It doesn't pulse any external signal, so a multicart won't know you did it unless it's actively trying to detect a jump to $1000. There isn't a good reason for a multicart to try to look for such a jump. So, a jump to $1000 should just restart the current game. Edited April 1, 2015 by intvnut Quote Link to comment Share on other sites More sharing options...
freewheel Posted April 1, 2015 Share Posted April 1, 2015 I wonder if replacing the ' with ; will make the comments on the ASM lines work. I'm at work and can't try it. Semicolon is the comment delimiter in assembly. Seems to work. IntyBASIC doesn't complain anyway. It just looks weird in my text highlighter now. ;'comment almost cleans it up. Really not a huge deal unless a person uses large amounts of ASM statements - and comments in-line like that. On soft reset: A jump to location $1000 will restart the EXEC. It doesn't pulse any external signal, so a multicart won't know you did it unless it's actively trying to detect a jump to $1000. There isn't a good reason for a multicart to try to look for such a jump. So, a jump to $1000 should just restart the current game. Neat. I'm gonna play with that. Sounds like exactly what I was thinking about. One of the more "playful" features of Desert Bus is a timer that basically kills the current game on you if you don't provide input fast enough at a certain point (this is essentially to prevent people from being able to take breaks). Instead of bothering with state tracking and making sure I'm jumping back to a proper "beginning", I'm thinking about just resetting. Guaranteeing that you wipe out your score and accumulated time. Just being lazy, mostly, as I re-factor routines. It's not an actual feature that I'm arsed to put a lot of effort into (right now it's just an ugly GOTO that eventually will overflow the stack). Mind you, if I ever included this on a multi-game ROM, that would be a bit awkward. So it was more of a theoretical question. Quote Link to comment Share on other sites More sharing options...
intvnut Posted April 1, 2015 Share Posted April 1, 2015 One of the more "playful" features of Desert Bus is a timer that basically kills the current game on you if you don't provide input fast enough at a certain point (this is essentially to prevent people from being able to take breaks). Instead of bothering with state tracking and making sure I'm jumping back to a proper "beginning", I'm thinking about just resetting. Guaranteeing that you wipe out your score and accumulated time. Just being lazy, mostly, as I re-factor routines. It's not an actual feature that I'm arsed to put a lot of effort into (right now it's just an ugly GOTO that eventually will overflow the stack). Mind you, if I ever included this on a multi-game ROM, that would be a bit awkward. So it was more of a theoretical question. I guess it depends on how you integrate the multiple games onto one ROM. If you program them separately, so that none of them know about each other, and none of them use page-flipping, then you can integrate them all into a larger ROM fronted by a menu that page-flips the appropriate game into play. (I've done this on a number of occasions, and it's fairly straightforward. Go For The Gold works this way too.) In fact, once the proper game is "flipped in," the menu generally dispatches to the flipped in game by asking the EXEC to reinitialize, so it sees the newly selected game. Why? A proper RESET will flip all the page-flipped ROMs back to PAGE 0. Restarting the EXEC (by jumping to $1000) will not. So, if Desert Bus, say, was integrated with some other games in this manner, so that it thought it owned the machine, and Desert Bus were to soft-reset by jumping to $1000, then you'd end up soft-resetting Desert Bus without resetting to the menu. Quote Link to comment Share on other sites More sharing options...
Kiwi Posted April 1, 2015 Share Posted April 1, 2015 I was thinking to overflow the stack you would use goto to jump out of a gosub thread. Gosub adds to the stack, then a return will pop that stack. I think adding goto to go up to the beginning of the program wouldn't effect anything. Quote Link to comment Share on other sites More sharing options...
intvnut Posted April 1, 2015 Share Posted April 1, 2015 I was thinking to overflow the stack you would use goto to jump out of a gosub thread. Gosub adds to the stack, then a return will pop that stack. I think adding goto to go up to the beginning of the program wouldn't effect anything. If you GOTO the top of your program without RETURNing from all your GOSUBs will eventually fill up the stack. So, if in the middle of a PROCEDURE somewhere you have a "GOTO START", then those GOSUBs will build up and eventually overflow the stack. It sounds like freeweed's GOTO is one of those. Quote Link to comment Share on other sites More sharing options...
Kiwi Posted April 1, 2015 Share Posted April 1, 2015 In Spunky Supercar, each level is it own function. When the level is complete, then it exit that function. But if you collide with something, then it'll set a variable, exit the function and then a if statement right after that handle the goto level1start, restarting the entire level. He probably can do that in his game. Quote Link to comment Share on other sites More sharing options...
intvnut Posted April 1, 2015 Share Posted April 1, 2015 Seems to work. IntyBASIC doesn't complain anyway. It just looks weird in my text highlighter now. ;'comment almost cleans it up. Really not a huge deal unless a person uses large amounts of ASM statements - and comments in-line like that. Cool. FWIW, it makes sense IntyBASIC would just pass through the rest of the line. The apostrophe is a valid character in ASM syntax. For example, MVII #'A', R0 puts the ASCII value of 'A' in R0. The digraph ;' just ends up serving as a comment in both languages: one to appease the assembler and the other to appease your syntax highlighter. :-) Quote Link to comment Share on other sites More sharing options...
freewheel Posted April 2, 2015 Share Posted April 2, 2015 In Spunky Supercar, each level is it own function. When the level is complete, then it exit that function. But if you collide with something, then it'll set a variable, exit the function and then a if statement right after that handle the goto level1start, restarting the entire level. He probably can do that in his game. Oh absolutely, there's a fairly easy way out of this. But given that this kind of "game over" literally resets the entire game anyway, I figured a soft reset might be easier than bothering to code much of anything. Again, being lazy. It's the kind of thing I doubt anyone would ever actually overflow anyway - it's just a couple of GOSUBs deep at that point, and it takes a certain kind of masochist to get to the condition that would trigger it in the first place, let alone multiple times. However there's a part of me that just can't handle leaving in the possibility. 1 Quote Link to comment Share on other sites More sharing options...
+nanochess Posted April 23, 2015 Author Share Posted April 23, 2015 Now updated to IntyBASIC v1.0.4, mainly bug fixes and small improvements, but at last support for secondary PSG in ECS. See list of changes in first post Edit: I've optimized multiplications for constants bigger than 128, but just I've noted there is a small caveat in generated code, if the left side is zero, the successive addition will happen 65536 times. At least this is best than previous behavior, the code would cycle the number of times of your constant Looking to solve this is next release, not really important. 2 Quote Link to comment Share on other sites More sharing options...
+Tarzilla Posted April 23, 2015 Share Posted April 23, 2015 support for secondary PSG in ECS. If we use sound 5-9 do we have to detect the ECS first and code different routines, or will the generated code fall back gracefully on a regular Inty, like how the Voice command set is smart enough not to crash if the Intellivoice isnt present? Quote Link to comment Share on other sites More sharing options...
+nanochess Posted April 23, 2015 Author Share Posted April 23, 2015 If we use sound 5-9 do we have to detect the ECS first and code different routines, or will the generated code fall back gracefully on a regular Inty, like how the Voice command set is smart enough not to crash if the Intellivoice isnt present? It doesn't happen nothing if ECS isn't present, because then SOUND statement would write in non-used ports and these would be ignored gracefully. Quote Link to comment Share on other sites More sharing options...
freewheel Posted April 27, 2015 Share Posted April 27, 2015 Solved bug where if last statement inside last IF was RETURN, PROCEDURE wouldn't insert final RETURN. Way cool. I think I kept hitting this bug, but never figured out what the deal was and assumed it must be me misunderstanding something about RETURN vs END again. I ended up changing how I handled certain cases but good to know I can go back to it if necessary. Although I do like the GOTO end_of_proc instead of RETURN for cleanliness. 1 Quote Link to comment Share on other sites More sharing options...
+nanochess Posted April 27, 2015 Author Share Posted April 27, 2015 Way cool. I think I kept hitting this bug, but never figured out what the deal was and assumed it must be me misunderstanding something about RETURN vs END again. I ended up changing how I handled certain cases but good to know I can go back to it if necessary. Although I do like the GOTO end_of_proc instead of RETURN for cleanliness. Yep, embarrassingly it was a pretty obscure bug, the only symptom was an unexpected crash or strange behavior as control passed directly into next procedure or past end of program. Quote Link to comment Share on other sites More sharing options...
freewheel Posted May 1, 2015 Share Posted May 1, 2015 (edited) Random IntyBASIC thingy. This line throws an error: MUSIC G4,G1,-,- However, it compiles fine (with the error) and plays the G1 note as G2. Just found it curious. I guess this is failing gracefully. As it turns out, the music I'm working on sounds pretty nice with G2 so it works for me. I know the documentation says octaves 2-6 only but I wasn't paying attention. Also something else weird. Drums don't work with some notes (in this case G3): MUSIC C4,G3,-,M3 I've played with a lot of combinations and for whatever reason, the drum just doesn't get played here. It's fine in combination with other notes. Edit: it seems to be a problem specifically with lower tones, or perhaps just G? Oh well, maybe this song doesn't need a rhythm track Edited May 1, 2015 by freeweed Quote Link to comment Share on other sites More sharing options...
+DZ-Jay Posted May 3, 2015 Share Posted May 3, 2015 (edited) Edit: I've optimized multiplications for constants bigger than 128, but just I've noted there is a small caveat in generated code, if the left side is zero, the successive addition will happen 65536 times. At least this is best than previous behavior, the code would cycle the number of times of your constant Can you provide some details? I was the one who enhanced Joe's constant multiplication macro to support values greater than 128. What did I screw up? Never mind, I see that I had problems with values greater than 128 so I reverted it in my own code. The change I made was to use SWAP in place of 8 shifts. -dZ. Edited May 3, 2015 by DZ-Jay 1 Quote Link to comment Share on other sites More sharing options...
+nanochess Posted May 4, 2015 Author Share Posted May 4, 2015 Random IntyBASIC thingy. This line throws an error: MUSIC G4,G1,-,- However, it compiles fine (with the error) and plays the G1 note as G2. Just found it curious. I guess this is failing gracefully. As it turns out, the music I'm working on sounds pretty nice with G2 so it works for me. I know the documentation says octaves 2-6 only but I wasn't paying attention. Yep, only octaves 2 to 6. Also something else weird. Drums don't work with some notes (in this case G3): MUSIC C4,G3,-,M3 I've played with a lot of combinations and for whatever reason, the drum just doesn't get played here. It's fine in combination with other notes. Edit: it seems to be a problem specifically with lower tones, or perhaps just G? Oh well, maybe this song doesn't need a rhythm track Be sure you're using the latest version of IntyBASIC, the first one with PLAY NONE had a bug in drums. 1 Quote Link to comment Share on other sites More sharing options...
freewheel Posted May 7, 2015 Share Posted May 7, 2015 (edited) Be sure you're using the latest version of IntyBASIC, the first one with PLAY NONE had a bug in drums. Heeeeeeeeeeelp! I finally installed the latest version, and now NOTHING works. All of my programs are failing with "missing ELSE". For example: IF CONT.LEFT THEN p1x=p1x-p1x_speed Error: missing ELSE in IF in line 81 Warning: Invalid extra characters in line 81 What is wrong with using syntax like this? Many times there's no ELSE needed! Edit: and this is why it helps to post the exact offending line. It turns out that this works fine: IF c1=0 THEN soundok=1 So you've changed something with the CONT handling. I use it all over the place which explains why I get so many errors. While I haven't gone through every one of my currently hundreds of errors, it seems like IF CONT without ELSE is causing it. Note: it does NOT trigger an error for IF CONT1 or IF CONT2. It only generates an error when using IF CONT to handle both controllers at the same time. Oh, and to complete the forensic analysis, IF CONT.LEFT THEN p1x=p1x-p1x_speed ELSE x=1 still generates the "missing ELSE" error. So obviously a bug of some sort. This worked in 1.0.3, broken in 1.0.4. Edited May 7, 2015 by freeweed Quote Link to comment Share on other sites More sharing options...
+nanochess Posted May 7, 2015 Author Share Posted May 7, 2015 Heeeeeeeeeeelp! I finally installed the latest version, and now NOTHING works. All of my programs are failing with "missing ELSE". For example: IF CONT.LEFT THEN p1x=p1x-p1x_speed Error: missing ELSE in IF in line 81 Warning: Invalid extra characters in line 81 What is wrong with using syntax like this? Many times there's no ELSE needed! Edit: and this is why it helps to post the exact offending line. It turns out that this works fine: IF c1=0 THEN soundok=1 So you've changed something with the CONT handling. I use it all over the place which explains why I get so many errors. While I haven't gone through every one of my currently hundreds of errors, it seems like IF CONT without ELSE is causing it. Note: it does NOT trigger an error for IF CONT1 or IF CONT2. It only generates an error when using IF CONT to handle both controllers at the same time. Oh, and to complete the forensic analysis, IF CONT.LEFT THEN p1x=p1x-p1x_speed ELSE x=1 still generates the "missing ELSE" error. So obviously a bug of some sort. This worked in 1.0.3, broken in 1.0.4. What platform are you using? I'm surprised by this bug, because I don't have changed nothing in that section of code A fast compilation of my test code in Mac OS X works fine: IF CONT.UP THEN A=1 IF CONT.DOWN THEN A=2 IF CONT.LEFT THEN A=3 IF CONT.RIGHT THEN A=4 IF CONT.BUTTON THEN A=5 IF CONT.B0 THEN A=6 IF CONT.B1 THEN A=7 IF CONT.B2 THEN A=8 A = CONT.KEY Please test with your platform. Quote Link to comment Share on other sites More sharing options...
freewheel Posted May 7, 2015 Share Posted May 7, 2015 (edited) What platform are you using? I'm surprised by this bug, because I don't have changed nothing in that section of code Linux. The only thing that jumps out at me is this comment from the changelog: Solved bug where RETURN inside IF was taken as RETURN at end of PROCEDURE Seems like a remote chance, but it's all I can think of. Here's the compiled output between using CONT and CONT1, not sure if this helps at all. It certainly is a bit weird to me. T5 is just the label for the following line of BASIC. Apologies for the profanity, I find it makes it very easy to locate things ;[14] IF CONT.UP THEN fuck=1 50B9 0280 0115 MVI V2,R0 50BB 0080 TSTR R0 50BC 0204 0000 BEQ T5 ;[14] IF CONT1.UP THEN fuck=1 50B9 0280 01FF MVI 511,R0 50BB 0018 COMR R0 50BC 03B8 0004 ANDI #4,R0 50BE 0204 0004 BEQ T5 50C0 02B8 0001 MVII #1,R0 50C2 0240 0118 MVO R0,V2 Edited May 7, 2015 by freeweed Quote Link to comment Share on other sites More sharing options...
+nanochess Posted May 7, 2015 Author Share Posted May 7, 2015 Linux. The only thing that jumps out at me is this comment from the changelog: Seems like a remote chance, but it's all I can think of. Here's the compiled output between using CONT and CONT1, not sure if this helps at all. It certainly is a bit weird to me. T5 is just the label for the following line of BASIC. Apologies for the profanity, I find it makes it very easy to locate things ;[14] IF CONT.UP THEN fuck=1 50B9 0280 0115 MVI V2,R0 50BB 0080 TSTR R0 50BC 0204 0000 BEQ T5 ;[14] IF CONT1.UP THEN fuck=1 50B9 0280 01FF MVI 511,R0 50BB 0018 COMR R0 50BC 03B8 0004 ANDI #4,R0 50BE 0204 0004 BEQ T5 50C0 02B8 0001 MVII #1,R0 50C2 0240 0118 MVO R0,V2 Ok, it looks like I've compiled an old version of IntyBASIC for Linux or the C++ compiler has a bug, more probably my fault. I'll check and recompile as soon as possible. Thanks! Quote Link to comment Share on other sites More sharing options...
freewheel Posted May 7, 2015 Share Posted May 7, 2015 Ok, it looks like I've compiled an old version of IntyBASIC for Linux or the C++ compiler has a bug, more probably my fault. I'll check and recompile as soon as possible. Thanks! Oh not at all, thank YOU! 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.